Follow-up to #226. That issue is being fixed by detect-and-refuse: meta migrate --dialect d1 now throws a clear generation-time error instead of silently emitting a migration that fails against production when it would rebuild a foreign-key-referenced table (design: docs/superpowers/specs/2026-07-27-d1-referenced-table-rebuild-refuse-design.md).
This issue tracks the deferred auto-fix: instead of refusing, generate a cascade that actually applies on remote D1.
What was prototyped (Appendix A of the #226 design)
A cascade works, validated against libSQL modelling remote D1 (batch in one implicit transaction, foreign_keys=ON):
- rebuild each referencing child without its FK -> rebuild the parent -> restore the children's FKs, all in one pass;
defer_foreign_keys=ON as a belt; temp tables reference each other's temp names (SQLite resolves FK targets lazily) and RENAME rewrites them to final names;
- two load-bearing ordering rules: referrers-first
DROP, parents-first RENAME.
Validated for single-parent, transitive (g→c→p), multi-child, and self-referential graphs — data intact, FKs re-enforced.
Why it was deferred
Disproportionate for a niche dialect's edge case: needs a reverse FK-graph + topological sort + self-ref special-casing, and multi-table cycles (A↔B) have no reliable atomic sequence and would still need refusing. Detect-and-refuse removes the dangerous (silent, production) behavior at ~10% of the cost.
If picked up
- Build the reverse FK-graph + topological order over the affected set (recreate set ∪ transitive referrers).
- Emit the validated cascade; keep refusing genuine multi-table cycles.
- Gate the migrate-doctrine way: emit → apply to a real engine (libSQL, batch-in-one-transaction to model remote D1) → re-diff EMPTY, per topology.
Follow-up to #226. That issue is being fixed by detect-and-refuse:
meta migrate --dialect d1now throws a clear generation-time error instead of silently emitting a migration that fails against production when it would rebuild a foreign-key-referenced table (design:docs/superpowers/specs/2026-07-27-d1-referenced-table-rebuild-refuse-design.md).This issue tracks the deferred auto-fix: instead of refusing, generate a cascade that actually applies on remote D1.
What was prototyped (Appendix A of the #226 design)
A cascade works, validated against libSQL modelling remote D1 (batch in one implicit transaction,
foreign_keys=ON):defer_foreign_keys=ONas a belt; temp tables reference each other's temp names (SQLite resolves FK targets lazily) andRENAMErewrites them to final names;DROP, parents-firstRENAME.Validated for single-parent, transitive (
g→c→p), multi-child, and self-referential graphs — data intact, FKs re-enforced.Why it was deferred
Disproportionate for a niche dialect's edge case: needs a reverse FK-graph + topological sort + self-ref special-casing, and multi-table cycles (A↔B) have no reliable atomic sequence and would still need refusing. Detect-and-refuse removes the dangerous (silent, production) behavior at ~10% of the cost.
If picked up