Skip to content

fix(core): preserve global canonical on session moves - #53874

Open
Dante-dan wants to merge 3 commits into
anomalyco:devfrom
Dante-dan:empty-repo-move
Open

Dante-dan wants to merge 3 commits into
anomalyco:devfrom
Dante-dan:empty-repo-move

Conversation

@Dante-dan

@Dante-dan Dante-dan commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Issue for this PR

Refs #50979 (partial: canonical rewrite when the previous source directory is gone).

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

If global points to a directory that has disappeared, moving a session into an empty git repository currently replaces the global canonical with the destination. Exclude the catch-all project from checkout-rename recovery; real project renames still work.

This does not change empty repositories’ shared project identity or the all-project session picker. The original two-existing-directory rewrite was not reproduced.

How did you verify your code works?

  • Real Session.move regression: baseline fails (canonical A becomes B); patched test passes, 2 assertions: the move reaches the destination and the global worktree remains the deleted source. The regression was narrowed in response to review; its baseline still fails at the canonical assertion.
  • Existing Project suite: 21 passed, including checkout rename/clone cases.
  • Core bun typecheck and git diff --check: passed.
  • Root bun run check (normal pre-push hook): all 36 tasks passed. Node 22.16 required NODE_OPTIONS=--experimental-strip-types; sandbox validation used isolated XDG paths, ASTRO_TELEMETRY_DISABLED=1 and TURBO_ENV_MODE=loose. Installed dependencies from the unchanged lockfile after a stale workspace dependency caused an initial missing-module failure.

Screenshots / recordings

No UI changes.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I reproduced the bug with the new regression test, which uses the real Session.move service. On the base branch the global project's worktree is rewritten from the deleted source repo to the destination. With this change it stays put. The session-move and project suites pass, and so does the core typecheck.

The fix looks right to me. Every empty git repo resolves to global, so the clone/rename recovery in persist should not adopt whichever empty repo was resolved last as global's directory. Real project renames and clone recovery are unaffected.

This is a partial fix for #50979: empty repos still share global, as the description says. One small request on the test, inline.

Comment thread packages/core/test/session-move.test.ts Outdated
expect(yield* sessions.get(created.id)).toMatchObject({
projectID: Project.ID.global,
location: { directory: destination },
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could this test be cut down to the fixed behaviour? The core case is: global points at a deleted empty repo, a session is moved into another empty repo, and global's worktree is unchanged. The source/destination list checks, the extra remaining/other sessions and the final sessions.remove check session isolation rather than this bug, which makes the test longer and harder to follow.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Simplified in 7dcc68e: removed the extra sessions, list checks and deletion check. The test now only verifies that the actual move reaches the destination and that global retains the deleted source as its worktree. The focused regression still fails without the guard and passes with it (2 assertions); the normal pre-push check also passed.

@thdxr
thdxr changed the base branch from v2 to dev October 10, 2026 19:36

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant