Skip to content

fix(persistence): move fork-only schema onto its own migration ledger - #13

Merged
yordis merged 2 commits into
mainfrom
yordis/fix-fork-migration-chain
Jul 31, 2026
Merged

fix(persistence): move fork-only schema onto its own migration ledger#13
yordis merged 2 commits into
mainfrom
yordis/fix-fork-migration-chain

Conversation

@yordis

@yordis yordis commented Jul 31, 2026

Copy link
Copy Markdown
Member
  • The shared migrator ledger only remembers the highest migration id that ran, so carrying fork migrations in the shared chain forced renumbering every incoming upstream migration at each sync, a tax that grows forever now that the subagent-threads divergence will not be upstreamed.
  • The documented fallback of reserving ids >= 1000 for fork migrations was a latent bug: the first one to run would make every later upstream migration arrive below the ledger's high-water mark and be silently skipped, drifting the schema.
  • A second migration chain with its own ledger table makes fork and upstream ids structurally unable to collide, and lets the shared chain and every upstream migration file stay byte-identical to upstream so future syncs stop conflicting there.
  • Existing installs already recorded the fork's ProjectionThreadParent as shared id 33, so a one-time realignment returns their ledger to upstream numbering before the shared migrator runs; fresh and already-realigned installs no-op.

The shared migrator ledger only remembers the highest id that ran, so
carrying fork migrations in the shared chain either displaces upstream
ids at every sync or, under the reserved high-id convention, would make
installs silently skip future upstream migrations. A separate ledger
removes both failure modes and keeps the shared chain byte-identical to
upstream.

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@cursor

cursor Bot commented Jul 31, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Changes how every database is migrated at startup, including one-time ledger rewriting for existing installs; incorrect realignment or fork/shared ordering could skip migrations or leave schema out of sync.

Overview
Fork-only schema no longer rides in the shared effect_sql_migrations chain. ProjectionThreadParent moves to a separate fork migrator (ForkMigrations.ts) with its own trogonstack_fork_migrations ledger and Migrations/fork/001_… numbering, so shared Migrations.ts and upstream migration files can match upstream ids 33–35 again without renumbering on every sync.

SQLite startup now runs realign → shared migrations → fork migrations. realignSharedMigrationLedger is a one-time repair for databases that still have ProjectionThreadParent recorded as shared id 33 (shifting upstream entries back to 33–35); fresh installs skip it.

The old Migrations.test.ts guard (reserved id ≥ 1000) is replaced by ForkMigrations.test.ts, which asserts fork names never appear in migrationEntries and covers fresh, full legacy, and mid-history upgrade paths. The fork parent migration is idempotent when the column already exists (legacy installs).

Reviewed by Cursor Bugbot for commit d338f88. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L labels Jul 31, 2026
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yordis, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 50 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fcb61b69-d8d8-400e-b8ee-48c0f14e6a25

📥 Commits

Reviewing files that changed from the base of the PR and between 33c89e9 and d338f88.

📒 Files selected for processing (1)
  • apps/server/src/persistence/ForkMigrations.ts

Walkthrough

The persistence layer separates fork migrations from upstream migrations. It restores shared migration IDs 33–35, adds transactional repair for legacy ledgers, runs the fork chain through a separate ledger, and adds fresh-install and legacy-install coverage.

Changes

Migration chain separation

Layer / File(s) Summary
Restore shared migration numbering
.agents/skills/trogonstack-sync-upstream/SKILL.md, apps/server/src/persistence/Migrations.ts, apps/server/src/persistence/Migrations/*
Shared migrations 33–35 now contain the upstream schema changes. The title-regeneration test targets migration 035.
Implement the fork migration chain
apps/server/src/persistence/ForkMigrations.ts, apps/server/src/persistence/Migrations/fork/*
ProjectionThreadParent runs through trogonstack_fork_migrations with an optional inclusive migration limit.
Realign legacy installations
apps/server/src/persistence/ForkMigrations.ts, apps/server/src/persistence/Layers/Sqlite.ts
SQLite initialization repairs legacy shared-ledger state, runs shared migrations, then runs fork migrations.
Validate fresh and legacy migration states
apps/server/src/persistence/ForkMigrations.test.ts, apps/server/src/persistence/Migrations.test.ts
Tests cover metadata, fresh installs, legacy full and mid-history installs, ledger contents, schema changes, and idempotent realignment. The former migration validation test is removed.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Poem

A rabbit hops through ledgers bright,
Forked paths keep the numbers right.
Old rows shift, new columns grow,
Separate chains now neatly flow.
Test by test, the burrow’s sound.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: moving fork-only schema migrations to a separate migration ledger.
Description check ✅ Passed The description clearly explains what changed and why, but it omits the template headings and checklist.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch yordis/fix-fork-migration-chain

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…lout

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/server/src/persistence/ForkMigrations.ts (1)

105-108: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the unused ForkMigrationsLive export.

ForkMigrationsLive only appears in apps/server/src/persistence/ForkMigrations.ts; the SQLite setup imports and calls runForkMigrations() directly. Remove the dead exported layer if no future entry point needs it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/server/src/persistence/ForkMigrations.ts` around lines 105 - 108, Remove
the unused ForkMigrationsLive export and its Layer.effectDiscard wrapper from
ForkMigrations.ts. Keep runForkMigrations unchanged, since SQLite setup invokes
it directly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.agents/skills/trogonstack-sync-upstream/SKILL.md:
- Around line 42-45: Correct the fail-fast test command in the migration-sync
guidance to follow the CLI convention: use the built-in Vite+ test form with the
file path, removing the extra “run” token. Keep the referenced test file and
surrounding migration instructions unchanged.

---

Nitpick comments:
In `@apps/server/src/persistence/ForkMigrations.ts`:
- Around line 105-108: Remove the unused ForkMigrationsLive export and its
Layer.effectDiscard wrapper from ForkMigrations.ts. Keep runForkMigrations
unchanged, since SQLite setup invokes it directly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6da6d6fe-5fb1-425f-91ae-b6c35f4d28e1

📥 Commits

Reviewing files that changed from the base of the PR and between 37d4c44 and 33c89e9.

📒 Files selected for processing (11)
  • .agents/skills/trogonstack-sync-upstream/SKILL.md
  • apps/server/src/persistence/ForkMigrations.test.ts
  • apps/server/src/persistence/ForkMigrations.ts
  • apps/server/src/persistence/Layers/Sqlite.ts
  • apps/server/src/persistence/Migrations.test.ts
  • apps/server/src/persistence/Migrations.ts
  • apps/server/src/persistence/Migrations/033_ProjectionThreadsSettled.ts
  • apps/server/src/persistence/Migrations/034_ProjectionThreadsSnoozed.ts
  • apps/server/src/persistence/Migrations/035_ProjectionThreadTitleRegeneration.test.ts
  • apps/server/src/persistence/Migrations/035_ProjectionThreadTitleRegeneration.ts
  • apps/server/src/persistence/Migrations/fork/001_ProjectionThreadParent.ts
💤 Files with no reviewable changes (1)
  • apps/server/src/persistence/Migrations.test.ts

Comment on lines +42 to +45
- Upstream migrations sync as-is, keeping their own ids. `Migrations.ts` and every file under `apps/server/src/persistence/Migrations/` (excluding `fork/`) must stay byte-identical to upstream. If either conflicts during a sync, take upstream's side wholesale rather than hand-merging.
- Fork-only schema never lands in `Migrations.ts`. It lives only in `apps/server/src/persistence/ForkMigrations.ts`, numbered independently under `apps/server/src/persistence/Migrations/fork/`, and tracked in its own `trogonstack_fork_migrations` ledger table instead of the shared `effect_sql_migrations` table.
- Because the two chains never share a ledger, id collisions between fork and upstream migrations are structurally impossible - there is nothing to renumber or offset during a sync.
- After resolving `Migrations.ts`, run the fail-fast guard: `vp test run apps/server/src/persistence/ForkMigrations.test.ts`. It rejects any fork migration name that leaks into the shared `migrationEntries` chain.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Verify the vp test run command syntax against the CLI convention.

Line 45 uses vp test run apps/server/src/persistence/ForkMigrations.test.ts. The coding guideline states two valid forms: vp test for the built-in Vite+ test command, and vp run test only for the test package script. vp test run <path> matches neither form and looks like a merge of the two.

Confirm the intended command and correct it. If the intent was to run vp test against a specific file, drop run.

📝 Proposed fix
-- After resolving `Migrations.ts`, run the fail-fast guard: `vp test run apps/server/src/persistence/ForkMigrations.test.ts`. It rejects any fork migration name that leaks into the shared `migrationEntries` chain.
+- After resolving `Migrations.ts`, run the fail-fast guard: `vp test apps/server/src/persistence/ForkMigrations.test.ts`. It rejects any fork migration name that leaks into the shared `migrationEntries` chain.

As per coding guidelines, "Use vp test for the built-in Vite+ test command; use vp run test only when specifically requiring the test package script."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- Upstream migrations sync as-is, keeping their own ids. `Migrations.ts` and every file under `apps/server/src/persistence/Migrations/` (excluding `fork/`) must stay byte-identical to upstream. If either conflicts during a sync, take upstream's side wholesale rather than hand-merging.
- Fork-only schema never lands in `Migrations.ts`. It lives only in `apps/server/src/persistence/ForkMigrations.ts`, numbered independently under `apps/server/src/persistence/Migrations/fork/`, and tracked in its own `trogonstack_fork_migrations` ledger table instead of the shared `effect_sql_migrations` table.
- Because the two chains never share a ledger, id collisions between fork and upstream migrations are structurally impossible - there is nothing to renumber or offset during a sync.
- After resolving `Migrations.ts`, run the fail-fast guard: `vp test run apps/server/src/persistence/ForkMigrations.test.ts`. It rejects any fork migration name that leaks into the shared `migrationEntries` chain.
- Upstream migrations sync as-is, keeping their own ids. `Migrations.ts` and every file under `apps/server/src/persistence/Migrations/` (excluding `fork/`) must stay byte-identical to upstream. If either conflicts during a sync, take upstream's side wholesale rather than hand-merging.
- Fork-only schema never lands in `Migrations.ts`. It lives only in `apps/server/src/persistence/ForkMigrations.ts`, numbered independently under `apps/server/src/persistence/Migrations/fork/`, and tracked in its own `trogonstack_fork_migrations` ledger table instead of the shared `effect_sql_migrations` table.
- Because the two chains never share a ledger, id collisions between fork and upstream migrations are structurally impossible - there is nothing to renumber or offset during a sync.
- After resolving `Migrations.ts`, run the fail-fast guard: `vp test apps/server/src/persistence/ForkMigrations.test.ts`. It rejects any fork migration name that leaks into the shared `migrationEntries` chain.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.agents/skills/trogonstack-sync-upstream/SKILL.md around lines 42 - 45,
Correct the fail-fast test command in the migration-sync guidance to follow the
CLI convention: use the built-in Vite+ test form with the file path, removing
the extra “run” token. Keep the referenced test file and surrounding migration
instructions unchanged.

Source: Coding guidelines

@yordis
yordis merged commit 711f8cf into main Jul 31, 2026
9 of 13 checks passed
@yordis
yordis deleted the yordis/fix-fork-migration-chain branch July 31, 2026 05:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant