Replaces #6812, which waited on #6647; #6647 is merged (23709b9c), so the pins are now one file per migration, src/core/migration-pins/<name>.pin, on main.
A migration on main is history. Today a pull can edit a migration and its .pin together, and pinBreaks (src/kernel/migrate.ts) still passes.
Done:
[ ] A pure function, e.g. pinEdits(changes: {status, path}[]): string[] in a small module of its own (src/kernel/pin_edits.ts), names every modified, deleted or renamed path under src/core/migration-pins/. An added pin passes.
[ ] The check runs it against the pull's diff to its base ($FORGE_CHECK_BASE..HEAD, which check.fast already receives; check.run falls back to the merge base with main), through bun scripts/gate.ts or scripts/pin-migrations.ts, and exits non-zero naming each file.
[ ] The message says: add a new migration instead. When the migration itself is not on the base yet, it says: delete the pin and re-run bun scripts/pin-migrations.ts.
[ ] test/pin-edits.test.ts fails without the change: modified → named, deleted → named, added → passes, a path outside the folder → ignored.
Files: src/kernel/pin_edits.ts (new), scripts/gate.ts or scripts/pin-migrations.ts, test/pin-edits.test.ts.
Risk: the frozen src/core/migration-pins.json is also history; refuse edits to it the same way.
Suggested: scout.
Replaces #6812, which waited on #6647; #6647 is merged (23709b9c), so the pins are now one file per migration,
src/core/migration-pins/<name>.pin, on main.A migration on main is history. Today a pull can edit a migration and its
.pintogether, andpinBreaks(src/kernel/migrate.ts) still passes.Done:
pinEdits(changes: {status, path}[]): string[]in a small module of its own (src/kernel/pin_edits.ts), names every modified, deleted or renamed path undersrc/core/migration-pins/. An added pin passes.$FORGE_CHECK_BASE..HEAD, whichcheck.fastalready receives;check.runfalls back to the merge base with main), throughbun scripts/gate.tsorscripts/pin-migrations.ts, and exits non-zero naming each file.bun scripts/pin-migrations.ts.test/pin-edits.test.tsfails without the change: modified → named, deleted → named, added → passes, a path outside the folder → ignored.Files: src/kernel/pin_edits.ts (new), scripts/gate.ts or scripts/pin-migrations.ts, test/pin-edits.test.ts. Risk: the frozen
src/core/migration-pins.jsonis also history; refuse edits to it the same way. Suggested: scout.