Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0c93397
Prepare release 0.3.4
jmclaughlin724 Jun 19, 2026
309efbd
Add CI failure inbox
jmclaughlin724 Jun 19, 2026
db4bf0d
Fix default agent bundle install boundary
jmclaughlin724 Jun 19, 2026
7718c64
standardize agent runtime enforcement
jmclaughlin724 Jun 19, 2026
b4694f6
Fix CI inbox and hook check failures
jmclaughlin724 Jun 19, 2026
f351f58
Standardize CI failure marker sync
jmclaughlin724 Jun 19, 2026
32689ef
Remove unauthorized DCO blocker
jmclaughlin724 Jun 20, 2026
45004db
Run public checkout guard pass locally
jmclaughlin724 Jun 20, 2026
9f1ae75
Cover policy guard in public checkout mode
jmclaughlin724 Jun 20, 2026
670ffd8
Use tracked files for public guard scans
jmclaughlin724 Jun 20, 2026
d98ec93
Fix CI inbox and agent hook enforcement
jmclaughlin724 Jun 20, 2026
7838398
Address review feedback for sync and bundle hooks
jmclaughlin724 Jun 20, 2026
d0c93de
Fix hook policy gaps and Windows test timeout
jmclaughlin724 Jun 20, 2026
ee32079
Fix Codex skill path detection on Windows
jmclaughlin724 Jun 20, 2026
52430c6
Codify cross-platform skill load detection
jmclaughlin724 Jun 20, 2026
f328453
Remove CI inbox hook surface
jmclaughlin724 Jun 20, 2026
bfa0f4d
Reorganize hooks, guards, and tests into single-concern domain modules
jmclaughlin724 Jun 21, 2026
2ffad44
Fix docs validate and Windows check-os timeouts on PR #53
jmclaughlin724 Jun 21, 2026
01d5267
Bump actions/checkout to v7.0.0 and actions/attest to v4.1.0
jmclaughlin724 Jun 22, 2026
3b99291
Address Codex PR review feedback on PR #53
jmclaughlin724 Jun 22, 2026
bc6cf44
Reject migrationsDir identical to a schemaPaths entry
jmclaughlin724 Jun 22, 2026
985fa63
Keep 0.3.4 a clean patch: revert public API narrowing
jmclaughlin724 Jun 22, 2026
69b7d98
Detect migrationsDir/schemaPaths overlap via path normalization
jmclaughlin724 Jun 22, 2026
4b1972b
Standardize path comparison: canonical resolve-based owner + enforcement
jmclaughlin724 Jun 22, 2026
d3127db
Widen path-comparison guard to repo-wide JS/TS coverage
jmclaughlin724 Jun 22, 2026
e439163
Refactor source ownership surfaces
jmclaughlin724 Jun 23, 2026
0d5dc85
Address PR 53 review feedback
jmclaughlin724 Jun 23, 2026
c0725e6
Update agent instructions
jmclaughlin724 Jun 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
38 changes: 29 additions & 9 deletions .agents/prompts/supaschema-install.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ For workspaces, `cd` into the owning member package before install and setup unl
| npm | `npm install supaschema` | `npm exec -- supaschema init` |
| pnpm | `pnpm add supaschema` | `pnpm exec supaschema init` |
| Yarn | `yarn add supaschema` | `yarn exec supaschema init` |
| Bun | `bun add supaschema` | `bunx --no-install supaschema init` |
| Bun | `bun add supaschema` | `./node_modules/.bin/supaschema init` |

Use the matching local runner for every command after install:

Expand All @@ -36,19 +36,37 @@ Use the matching local runner for every command after install:
| npm | `npm exec -- supaschema <cmd>` |
| pnpm | `pnpm exec supaschema <cmd>` |
| Yarn | `yarn exec supaschema <cmd>` |
| Bun | `bunx --no-install supaschema <cmd>` |
| Bun | `./node_modules/.bin/supaschema <cmd>` |

Always run the matching explicit setup command from the owning package directory after install. The command is idempotent and leaves existing config intact. Default `supaschema init` combines the consuming repo's detected package manager, workspace owner, provider markers, schema paths, and migration paths with the packaged config contract only. It does not install active AI-agent rules, hooks, skills, prompts, or settings. When the user explicitly approves AI-agent enforcement, `<local-runner> init --agent-bundle` installs the reviewed raw bundle, preserves existing hook entries, appends missing supaschema hook entries at the end of the relevant event array, and refreshes the managed agent surfaces.
Always run the matching explicit setup command from the owning package directory after install. The command is idempotent and leaves existing config intact. Default `supaschema init` combines the consuming repo's detected package manager, workspace owner, provider markers, schema paths, migration paths, and focused non-apply package scripts with the packaged config contract only. It does not install active AI-agent rules, hooks, skills, prompts, settings, `AGENTS.md`, `CLAUDE.md`, backup directories, or apply-capable package scripts. When the user explicitly approves AI-agent enforcement, review `node_modules/supaschema/agent-bundle/INSTALL.md` and follow its manual copy/merge instructions.

```bash
npm exec -- supaschema init
pnpm exec supaschema init
yarn exec supaschema init
bunx --no-install supaschema init
./node_modules/.bin/supaschema init
```

Use `<local-runner> init --dry-run --json` when you need to preview setup before writing files.

After setup, use package scripts from the owning package for focused non-apply lanes:

| Manager | Diff | Stage | Types | Check |
| --- | --- | --- | --- | --- |
| npm | `npm run supaschema:diff` | `npm run supaschema:stage` | `npm run supaschema:types` | `npm run supaschema:check` |
| pnpm | `pnpm supaschema:diff` | `pnpm supaschema:stage` | `pnpm supaschema:types` | `pnpm supaschema:check` |
| Yarn | `yarn supaschema:diff` | `yarn supaschema:stage` | `yarn supaschema:types` | `yarn supaschema:check` |
| Bun | `bun run supaschema:diff` | `bun run supaschema:stage` | `bun run supaschema:types` | `bun run supaschema:check` |

Use direct CLI commands for setup diagnostics, full sync, apply, and database execution verification:

```bash
<local-runner> config validate --json
<local-runner> sync
<local-runner> apply
<local-runner> verify
```

## What Install Provides

The package provides:
Expand All @@ -64,9 +82,10 @@ Default `supaschema init` writes or merges these project files into the consumin

- `supaschema.config.json` when the project does not already have one;
- configured schema and migration directories;
- focused non-apply `supaschema:*` package scripts when `package.json` exists: `supaschema:diff`, `supaschema:stage`, `supaschema:types`, and `supaschema:check`;
- `.supaschema/install.json` only when detected paths need confirmation.

Install does not edit schema files, generate migrations, connect to a database, apply migrations, write real database credentials, create duplicate supaschema-only database credential files, install active AI-agent rules/hooks/skills/settings by default, install maintainer editor/MCP/FastMCP tooling, run `npx skills`, or copy supaschema source/test infrastructure into the consumer project. To install AI-agent enforcement on demand, review `node_modules/supaschema/agent-bundle/INSTALL.md` and run `<local-runner> init --agent-bundle` only when the user approves the bundle.
Install does not edit schema files, generate migrations, connect to a database, apply migrations, write real database credentials, create duplicate supaschema-only database credential files, install active AI-agent rules/hooks/skills/settings, write `AGENTS.md` or `CLAUDE.md`, create backup directories, install maintainer editor/MCP/FastMCP tooling, run `npx skills`, or copy supaschema source/test infrastructure into the consumer project. To install AI-agent enforcement on demand, review `node_modules/supaschema/agent-bundle/INSTALL.md` and apply those instructions only when the user approves the bundle.

## First Tasks After Install

Expand All @@ -79,18 +98,19 @@ Install does not edit schema files, generate migrations, connect to a database,

## Schema Change Workflow

For schema changes, edit only the configured declarative SQL tree from `schemaPaths`. Then run:
For schema changes, edit only the configured declarative SQL tree from `schemaPaths`. Then run the one-command workflow:

```bash
<local-runner> diff
<local-runner> check
<local-runner> sync
```

`sync` owns the full reconcile path: diff, target selection, migration-history reconciliation, check, generated contracts, stage, safety gates, verify, selected-runner apply, and final reconciliation or dry-run reporting. Bare `sync` selects at most one `sync.targets.<name>` entry with `mode: "auto"`; multiple automatic targets are refused because cross-target apply is not atomic.

If installed hooks are trusted and fire after a schema-tree write, treat their returned migration name or `SUPA_*` diagnostic as authoritative. If they do not fire, run the commands manually.

Generated migrations containing `-- supaschema: lineage` are artifacts. Do not hand-edit them; change the schema tree and regenerate.

Use bare `<local-runner> sync` for the configured workflow. Do not run `<local-runner> sync --target <name>` unless the user explicitly asks to override target selection. `sync.targets.<name>.mode` decides automatic target selection. Never set a remote approval variable on the user's behalf.
Use `<local-runner> diff`, `<local-runner> check`, `<local-runner> types`, `<local-runner> stage`, or `<local-runner> apply` only when the user asks for that focused lane. Do not run `<local-runner> sync --target <name>` unless the user explicitly asks to override target selection. Never set a remote approval variable on the user's behalf.

## Completion Report

Expand Down
19 changes: 11 additions & 8 deletions .agents/skills/supaschema/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ metadata:

This skill is a direct execution contract for producing schema migrations with supaschema. Follow the workflow in order; do not hand-author migration SQL for changes the declarative tree can express, and never edit a generated migration (the `-- supaschema: lineage` marker) by hand.

When the bundled PostToolUse hook is wired (`.claude/settings.json` / `.codex/hooks.json`) and `workflow.schema_diff` / `workflow.migration_check` keep their defaults, a write to a schema-tree `.sql` file auto-runs steps 2–3 — `diff` then `check <generated migration path...>` — and returns the generated migration name, or the blocking `SUPA_*` diagnostic, as context. If `workflow.migration_sync` allows automatic sync, the hook first confirms every selected `sync.targets` entry is `mode: "auto"`, every database URL reference resolves, and any remote target has its configured approval variable set; only then does it delegate to `supaschema sync` for diff, generated outputs, type/RLS safety gates, apply, and target reconciliation. If the generated-migration `check` or `sync` fails, the hook emits loop-continuation feedback; inspect the diagnostic, identify the canonical root source in the declarative tree, config, or generated migration chain, search for similar or correlated migration failures, fix the canonical owner, and rerun the failing command. Read that context as the workflow result and act on any reported code.
When the bundled PostToolUse hook is wired (`.claude/settings.json` / `.codex/hooks.json`) and `workflow.schema_diff` / `workflow.migration_check` keep their defaults, a write to a schema-tree `.sql` file auto-runs `diff` then `check <generated migration path...>` and returns the generated migration name or blocking `SUPA_*` diagnostic. If `workflow.migration_sync` allows automatic sync, the hook first confirms exactly one `sync.targets` entry is selected with `mode: "auto"`, its database URL reference resolves when its runner needs one, and any remote target has its configured approval variable set; only then does it delegate to `supaschema sync` for the full source, diff, target-selection, history, check, generated-contract, stage, safety, verify, runner, and reconciliation workflow. If `check` or `sync` fails, inspect the diagnostic, fix the canonical source, and rerun the failing command.

## Installed Setup

The normal consumer setup is package install plus one explicit setup command through the consuming project's package manager. Default `supaschema init` writes only `supaschema.config.json`, configured schema directories, configured migration directories, and `.supaschema/install.json` when paths need confirmation. It does not write active `.agents`, `.claude`, `.codex`, `AGENTS.md`, or `CLAUDE.md` surfaces. The raw AI-agent bundle ships under `node_modules/supaschema/agent-bundle/`; read `agent-bundle/INSTALL.md` and install it only after the user asks for AI-agent enforcement or approves the bundle. Use `supaschema init --agent-bundle` only for that explicit opt-in path.
The normal consumer setup is package install plus one explicit setup command through the consuming project's package manager. Default `supaschema init` writes `supaschema.config.json`, configured schema directories, configured migration directories, safe focused package scripts when `package.json` exists (`supaschema:diff`, `supaschema:stage`, `supaschema:types`, and `supaschema:check`), and `.supaschema/install.json` when paths need confirmation. It does not write active `.agents`, `.claude`, `.codex`, settings, hooks, `AGENTS.md`, `CLAUDE.md`, backup directories, or apply-capable package scripts. The raw AI-agent bundle ships under `node_modules/supaschema/agent-bundle/`; read `agent-bundle/INSTALL.md` and follow its manual copy/merge instructions only after the user asks for AI-agent enforcement or approves the bundle. Use direct CLI commands for setup diagnostics, full sync/apply, and database execution verification: `supaschema config validate`, `supaschema sync`, `supaschema apply`, and `supaschema verify`.

If this skill was installed through `npx skills`, treat it as portable workflow context only. Agent Skills installs `SKILL.md`-based folders into a user-selected skill location; it does not create `supaschema.config.json`, schema/migration directories, passive rule files, hook scripts, or hook registration. To install project enforcement surfaces, install the npm package with the consuming project's manager from the owning package directory, review `node_modules/supaschema/agent-bundle/INSTALL.md`, then install the raw bundle on demand.
If this skill was installed through `npx skills`, treat it as portable workflow context only. Agent Skills installs `SKILL.md`-based folders into a user-selected skill location; it does not create `supaschema.config.json`, schema/migration directories, passive rule files, hook scripts, or hook registration. To install project enforcement surfaces, install the npm package with the consuming project's manager from the owning package directory, review `node_modules/supaschema/agent-bundle/INSTALL.md`, then manually install the raw bundle on demand.

Before the first schema edit, inspect `supaschema.config.json`. Normal resolved installs do not create `.supaschema/`; if `.supaschema/install.json` exists, treat it as pending path-confirmation state. If it says `"pathConfirmationNeeded": true`, inspect its candidate `schemaPaths` and `migrationsDirs`, ask the user which `schemaPaths`, `sources.to`, and `migrationsDir` to use, update `supaschema.config.json`, then run the workflow. Do not generate a migration from a guessed path; the bundled hooks also skip auto-diff until all three fields are explicit.

Expand All @@ -35,8 +35,8 @@ Read `supaschema.config.json` before editing schemas. Treat these four decisions

- **Schema tree:** `schemaPaths`, `sources.to`, and `migrationsDir`. Edit only the configured schema roots; `dir:` sources read nested `.sql` files recursively and merge them into one model. `sources.to` is the explicit target for zero-source-flag `diff`, `plan`, and `verify`. Generated migrations write to `migrationsDir`.
- **Diff baseline:** `sources.from` and `sources.to`. Install writes `sources.from: "auto"` and `sources.to: "dir:<schemaPaths[0]>"`; examples or fixture projects can pin `dump:`, `dir:`, `git:`, `database:`, `catalog:`, or `empty:` values when that source is the project contract.
- **Generated contracts:** `typesFile`, `zodFile`, `workflow.type_generation`, `workflow.zod_generation`, and `workflow.type_usage`. The default `create_or_refresh` policy creates or updates TypeScript and Zod outputs after `diff`; `zod_validated` means agents should use generated Zod validators at runtime boundaries.
- **Apply policy:** `workflow.migration_sync` and `sync.targets`. The default `migration_sync: "auto"` keeps bare `supaschema sync` apply-capable, but only targets with `mode: "auto"` are selected. Set a target to `manual` to omit it from bare sync, set `workflow.migration_sync` to `manual` to require `--target <name>`, or set it to `disabled` to block apply. Remote targets also require `requireApprovalEnv`.
- **Generated contracts:** `typesFile`, `zodFile`, `workflow.type_generation`, `workflow.zod_generation`, and `workflow.type_usage`. `supaschema types` creates or refreshes TypeScript and Zod outputs from the configured schema source; `zod_validated` means agents should use generated Zod validators at runtime boundaries.
- **Apply policy:** `workflow.migration_sync` and `sync.targets`. The default `migration_sync: "auto"` keeps bare `supaschema sync` apply-capable for one target with `mode: "auto"`. Set a target to `manual` to omit it from bare sync, set `workflow.migration_sync` to `manual` to require `--target <name>`, or set it to `disabled` to block apply. Multiple automatic targets are refused because cross-target apply is not atomic. Remote targets also require `requireApprovalEnv`.

Other config fields refine those decisions: `managedSchemas` blocks externally owned schemas, `transactionMode` mirrors the apply runner, `environments` optionally holds extra `$ENV_NAME` URL references, and `adapter: "auto"` is a provider-neutral sentinel rather than workflow consent.

Expand All @@ -56,7 +56,10 @@ Other config fields refine those decisions: `managedSchemas` blocks externally o
- Renames: declare `{ "from": "<key>", "to": "<key>" }` in `hints.renames`; renames are never inferred.

3. **Check replay safety:** `supaschema check` gates every `.sql` in the migrations directory (or name specific files) — must exit 0 for generated and hand-authored migrations alike.
4. **Verify execution** (when any database is resolvable — URL precedence is `--database-url` (`$ENV` supported), named `config.environments` via global `--env`, `SUPASCHEMA_DATABASE_URL`, then the nearest `supabase/config.toml`):
4. **Regenerate contracts:** `supaschema types` refreshes TypeScript and Zod outputs from the configured schema source. Use generated Zod validators at runtime boundaries when `workflow.type_usage` is `zod_validated`.
5. **Stage generated migrations:** `supaschema stage` git-stages changed migration files containing the `-- supaschema: lineage` marker and leaves hand-authored SQL untouched.
6. **Apply pending migrations:** `supaschema apply` applies already-generated pending migrations through the configured runner without generating a new diff. Do not mutate a database unless config, target resolution, safety gates, and required runtime approval allow that target.
7. **Verify execution** (when any database is resolvable — URL precedence is `--database-url` (`$ENV` supported), named `config.environments` via global `--env`, `SUPASCHEMA_DATABASE_URL`, then the nearest `supabase/config.toml`):

```bash
supaschema verify
Expand All @@ -66,11 +69,11 @@ Other config fields refine those decisions: `managedSchemas` blocks externally o

Add `--ensure-roles` when the migration grants to roles a bare PostgreSQL server lacks (e.g. `authenticated`). Use `--ensure-environment` when a plain PostgreSQL verification server needs Supabase-provisioned surfaces. A fingerprint mismatch itemizes the differing objects in the diagnostic hint.

5. **Commit** the tree change, the generated migration, and refreshed generated outputs together. The diff/check/verify workflow never stages changes; apply happens only through configured `supaschema sync` target selection or an explicit user-approved target override. TypeScript and Zod outputs come from the tree (`diff` creates or refreshes `database.types.ts` / `database.zod.ts` by default). When `workflow.type_usage` is `zod_validated`, use generated Zod validators for runtime parsing/validation instead of hand-authored database-shape validators — never wait for a deploy or run introspection-based typegen to get correct types.
8. **Commit** the tree change, generated migration, and generated outputs together. `sync` is the one-command workflow for schema changes; `diff`, `stage`, `apply`, `types`, and `check` remain focused lanes for explicit operation. Never wait for a deploy or run introspection-based typegen to get correct types.

## Operational Sync

`supaschema sync` is the operational apply path, not the default generation workflow. Bare `sync` selects every configured `sync.targets.<name>` entry with `mode: "auto"` when `workflow.migration_sync` is `"auto"`. `workflow.migration_sync: "manual"` leaves bare `sync` on the dry-run gate and allows explicit `--target <name>` overrides. `workflow.migration_sync: "disabled"` refuses apply. `--target <name>` is the only public override path; do not use removed local/remote aliases. Remote automatic targets must require a runtime approval variable such as `SUPASCHEMA_REMOTE_SYNC_APPROVED=1`. Do not mutate a database unless config, target resolution, safety gates, and required runtime approval allow that specific target.
`supaschema sync` is the canonical one-command workflow. It composes apply policy, source resolution, diff generation, target selection, migration-history reconciliation, replay-safety check, generated TypeScript/Zod refresh according to workflow policy, generated-migration staging when Git is available, deploy safety gates, disposable-database verification of the ordered pending migration set, selected runner apply, and final reconciliation or dry-run reporting. It refreshes generated contracts and runs the local stage lane even when no migration is pending. Use the explicit command lanes (`diff`, `check`, `types`, `stage`, `apply`) only when the user asks for a focused step. Bare `sync` may select one configured `sync.targets.<name>` entry with `mode: "auto"` when `workflow.migration_sync` is `"auto"`; multiple automatic targets are refused because cross-target apply is not atomic. `workflow.migration_sync: "manual"` leaves bare `sync` on the dry-run gate and allows explicit `--target <name>` overrides. `workflow.migration_sync: "disabled"` refuses apply while allowing non-mutating sync lanes. Remote automatic targets must require a runtime approval variable such as `SUPASCHEMA_REMOTE_SYNC_APPROVED=1`.

## Drift Detection

Expand Down
4 changes: 4 additions & 0 deletions .claude/hooks/context-permission-denied.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env node
import { runAgentHookEvent } from "../../scripts/agent-hooks/runner.mjs";

runAgentHookEvent("PermissionDenied");
4 changes: 4 additions & 0 deletions .claude/hooks/context-post-tool-use.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env node
import { runAgentHookEvent } from "../../scripts/agent-hooks/runner.mjs";

runAgentHookEvent("PostToolUse");
Loading
Loading