feat(08.6): one row per repo + branch picker on launch#84
Merged
Conversation
Collapse worktrees in the Sidebar so the session list shows ONE row per GitHub repo, and surface a worktree/branch picker dropdown in the Launch button so users choose WHICH local checkout to spawn against. Hub: - GET /api/sessions enriches each row with `local_paths[]` from the inventory cache (cap 20, canonical first). Empty for legacy/local-only sessions. - POST /api/sessions/:id/launch accepts `local_path` in the body; validated against the inventory for the session's repo_key (400 invalid_local_path otherwise). Falls back to canonical → project_dir. - New `getKnownLocalPathsForRepoKey(userId, repoKey)` helper in supervisor-registry. Supervisor (v0.5.0): - git-introspect.ts reads `git symbolic-ref --short HEAD` per repo (branch nullable on detached HEAD). Forwarded through scanRoots → hub-client → supervisor.repo_inventory wire payload (optional / back-compat for pre-0.5 hubs). Web: - Sidebar collapses any duplicate `repo_key` rows (defensive UI dedupe, keep most-recently-active). When the running cwd is in `local_paths`, the row caption shows `on <branch> · <path>`. - LaunchButton renders a `<select>` next to the button when `session.local_paths.length > 1`; option labels are `<basename> · <branch> [worktree]`. Single-path UX unchanged. - CodeSession type gains `local_paths?`. `launchSession()` accepts a `local_path` in the body. Tests: - hub/test/known-paths-registry.test.ts (6 new) covers canonical-first sort, case-insensitive repo_key match, 20-entry cap, null-branch tolerance, and resolveLocalPathForRepoKey parity. - hub/test/sessions-launch.test.ts adds two cases: local_path body pins worktree cwd; unknown local_path → 400. Diagnosis (per QC report from user): no duplicate-row bug in the V2 dedupe — the visible clutter was a mix of (a) GitHub-keyed rows showing multiple worktree captions and (b) legacy local-only rows with no repo_key. The fix collapses (a) at the API + UI layer and surfaces worktree choice via the dropdown instead of distinct rows. Version bump 0.4.3 → 0.5.0 in all 5 places (supervisor/src/index.ts, supervisor/src/hub-client.ts, supervisor/tauri/src-tauri/Cargo.toml, supervisor/tauri/src-tauri/tauri.conf.json, supervisor/tauri/ui/package.json). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
repo_key, the UI defensively dedupes to the most-recently-active row (DB-level partial unique index on(user_id, repo_key)is still the primary mechanism). When the running cwd is known to the inventory, the caption showson <branch> · <path>.GET /api/sessionsenriches each row withlocal_paths[](cap 20, canonical first) from the per-user inventory cache.LaunchButtonrenders a<select>next to the button whenlocal_paths.length > 1; option labels are<basename> · <branch> [worktree]. Selected path is sent aslocal_pathin the launch body and validated against the inventory (400invalid_local_pathif the path is not in the supervisor inventory for this repo_key).git-introspect.tsrunsgit symbolic-ref --short HEAD(null on detached HEAD). Wire field is optional + back-compat — pre-0.5 supervisors keep working; picker just omits the branch suffix.Diagnosis (root cause confirmed)
Per the user's QC report and code reading: the V2 dedupe at
findOrCreateAgentSessionV2is correct. The visible clutter came from (a) GitHub-keyed rows whose worktree captions made them look like separate rows, and (b) legacy / local-only rows with norepo_keymixed in. The fix collapses (a) at the API + UI layer and surfaces worktree choice through the dropdown instead of distinct sidebar rows.Versions
Supervisor + Tauri bumped 0.4.3 → 0.5.0 in all 5 places:
supervisor/src/index.tssupervisor/src/hub-client.tssupervisor/tauri/src-tauri/Cargo.tomlsupervisor/tauri/src-tauri/tauri.conf.jsonsupervisor/tauri/ui/package.jsonTest plan
cd hub && bun test— no NEW failures (8 fail in this branch all pre-existing onorigin/main: insertRunV2 ×4, insertDeploymentRun, supervisor-registry reconnect race ×2, 1 unnamed). 374 pass total. 6 new tests forgetKnownLocalPathsForRepoKey+ 2 new tests forlaunch'slocal_pathbody all pass.cd web && bun run build— clean, 2.11s.bunx tsc --noEmiton changed files — clean.<basename> · <branch> [worktree]labels./health200 on Coolify deploy after merge.supervisor-v0.5.0after merge (separate step — Tauri release CI).Files
hub/src/api/sessions.ts,hub/src/ws/supervisor-protocol.ts,hub/src/ws/supervisor-registry.tssupervisor/src/git-introspect.ts,supervisor/src/repo-scanner.ts,supervisor/src/hub-client.ts,supervisor/src/index.ts,supervisor/tauri/{src-tauri/Cargo.toml,src-tauri/tauri.conf.json,ui/package.json}web/src/components/LaunchButton.tsx,web/src/components/Sidebar.tsx,web/src/hooks/useSessions.tshub/test/known-paths-registry.test.ts(new),hub/test/sessions-launch.test.ts(extended)docs/github-session-keying.mdCo-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
🤖 Generated with Claude Code