Skip to content

fix(app): resolve a session's project by directory, not by shared ID - #39666

Open
Luppa90 wants to merge 1 commit into
anomalyco:devfrom
Luppa90:fix-project-avatar
Open

fix(app): resolve a session's project by directory, not by shared ID#39666
Luppa90 wants to merge 1 commit into
anomalyco:devfrom
Luppa90:fix-project-avatar

Conversation

@Luppa90

@Luppa90 Luppa90 commented Jul 30, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #39667

The root cause is #36233 — project identity derived solely from the git remote is what makes two distinct directories collide on one ID, and #35714 reports the same collision causing wrong-project redirects. This PR deliberately does not close either: it does not change how identity is derived, it stops the UI misattributing sessions once a collision already exists.

Type of change

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

What does this PR do?

With two projects open, every session tab showed the first project's name and avatar — a chat in project B and a chat in project T both rendered as B.

A project ID does not identify an opened directory. Project.resolve keys it off the git remote, falling back to a cached ID and then the repo's root commit:

const id = (yield* remote(repo)) ?? previous ?? (yield* root(repo))

So separate clones, sibling worktrees, and a directory nested inside another's repo all resolve to the same ID — as does every directory outside a repo, under the global ID.

projectForSession looked that ID up before the directory, so every session across those directories resolved to whichever project was opened first. It isn't only cosmetic: the same helper feeds the command palette and the home session list, so sessions were attributed to the wrong project there too. The server compounds it — worktree: projectID === ID.global ? worktree : existing.worktree keeps the first directory's worktree on the shared row.

The fix matches the worktree or a sandbox path first, since either identifies an opened project on its own, and falls back to the ID only for sessions below a repo root where no path matches exactly. Repo setups are unaffected: a session in a subdirectory still resolves through the ID, which is exactly the fallback case.

How did you verify your code works?

  • Reproduced with two projects open in the web UI: a session in the second project rendered the first project's avatar. Applied the fix and it resolved correctly; reverted the build and it came back; reapplied and it went away again.
  • Unit tests for projectForSession covering both collision routes (directories sharing a repo identity, and directories outside a repo sharing the global ID), plus the repo-subdirectory fallback, sandbox matching, and the no-match case. Both collision tests were checked against the pre-fix implementation to confirm they actually fail there.
  • bun test for the app package and typecheck are clean. The only failing test is the pre-existing ar i18n parity gap, which fails identically on dev.

Screenshots / recordings

Not a visual change beyond the corrected label: tabs for a second project now show that project's own name and avatar instead of the first project's.

Checklist

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

@github-actions

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.

A project ID does not identify an opened directory. Project.resolve keys it
off the git remote, falling back to a cached ID and then the repo's root
commit, so separate clones, sibling worktrees and a directory nested inside
another's repo all resolve to the same ID - as does every directory outside a
repo, under the global ID.

projectForSession looked that ID up first, so every session across those
directories resolved to whichever project was opened first: tabs for a second
project showed the first project's name and avatar, and the same misattribution
reached the command palette and the home session list. The server compounds it
by keeping the first directory's worktree on the shared row.

Match the worktree or a sandbox path first, since either identifies an opened
project on its own, and fall back to the ID only for sessions below a repo root
where no path matches exactly.

This does not change how project identity is derived (anomalyco#36233); it stops the UI
misattributing sessions when two directories collide on one ID.
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.

Web UI: session tabs show the first opened project's name and avatar when two directories share a project ID

1 participant