Skip to content

Commit 4c3f3fa

Browse files
docs(db-migrate): add contract-pending TODO convention for deferred drops
Establishes a durable, greppable marker (`contract-pending(<precondition>): ...`) left on the legacy column in schema.ts when an expand defers a drop, so the contract phase doesn't rot. The outstanding-work list is `grep -rn contract-pending`; the contract PR's `-- migration-safe:` annotation references the expand and deletes the marker. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent a986f58 commit 4c3f3fa

1 file changed

Lines changed: 24 additions & 2 deletions

File tree

.agents/skills/db-migrate/SKILL.md

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,28 @@ Never put expand and contract in the same PR. If this PR both removes the code t
3939

4040
A `CREATE INDEX`, `ADD COLUMN`, or `ADD CONSTRAINT` against a table **created in the same migration** is always safe (no rows, no live traffic) — the lint already suppresses those.
4141

42+
## Tracking the contract (don't let it rot)
43+
44+
The contract half is deferred to a later deploy — and that is exactly when it gets forgotten, leaving dead columns, orphaned tables, and `NOT NULL`s that never land. Every deferred contract must become a durable, greppable TODO.
45+
46+
When an expand defers a drop, leave a **`contract-pending`** marker on the legacy column/table in `packages/db/schema.ts` — that is the file you will be editing when you finally do the drop, so the reminder lives where the work happens:
47+
48+
```ts
49+
// contract-pending(after #5035 is fully deployed): drop once permission-check.ts stops reading it
50+
workspaceId: text('workspace_id'),
51+
```
52+
53+
Format: `contract-pending(<precondition>): <what to drop> — <why it's safe once the precondition holds>`. The precondition names the PR/release that removes the last reader and **must be fully deployed** before the contract ships.
54+
55+
- **The TODO list is a grep** — always accurate, never drifts: `grep -rn "contract-pending" packages/db apps/sim`. Run it when starting migration work to see what is owed.
56+
- For anything with a real owner or schedule, also open a tracking issue and put its number in the marker.
57+
- **Close the loop in the contract PR:** the contract migration's `-- migration-safe:` annotation references the expand, and you **delete the `contract-pending` marker** in the same PR:
58+
```sql
59+
-- migration-safe: contract of #5035 — workspace_id readers removed there, deployed 2026-06-10
60+
ALTER TABLE "permission_group" DROP COLUMN "workspace_id";
61+
```
62+
- An expand merged **without** a marker for the drop it defers, or a contract merged **without** removing its marker, is a bug — flag it in review.
63+
4264
## The judgment the lint can't do
4365

4466
The lint flags risky *shapes*; it cannot know whether a given drop is *safe right now*. For each flagged statement, do the work it can't:
@@ -49,9 +71,9 @@ The lint flags risky *shapes*; it cannot know whether a given drop is *safe righ
4971

5072
## Workflow
5173

52-
1. Edit `packages/db/schema.ts`, then `cd packages/db && bunx drizzle-kit generate` to produce the SQL.
74+
1. Edit `packages/db/schema.ts`, then `cd packages/db && bunx drizzle-kit generate` to produce the SQL. If this is an expand that defers a drop, leave a `contract-pending` marker on the legacy column (see "Tracking the contract"). If this is the contract, delete the marker it resolves.
5375
2. Hand-edit the generated SQL where the playbook requires it: `CONCURRENTLY` + `COMMIT;` breakpoint for indexes on existing tables, `NOT VALID` for constraints, batching for backfills.
54-
3. Run `bun run check:migrations` (or `bun run scripts/check-migrations-safety.ts main` locally).
76+
3. Run `bun run check:migrations` (base defaults to `origin/staging`).
5577
- **Hard errors** (`add-not-null-no-default`, `rename`, `index-not-concurrent`, `constraint-not-valid`, …): rewrite into expand/contract. Do **not** try to annotate them away — the lint won't accept it.
5678
- **Annotate tier** (`drop-table`, `drop-column`, `drop-default`, `set-not-null`, `alter-type`, `drop-index`): only after you've confirmed steps 1–3 above, add a comment on the line directly above the statement:
5779
```sql

0 commit comments

Comments
 (0)