Repository navigation
fix(git): a timed-out worktree list is never read as 'no family' - #1450
Merged
Juliusolsson05 merged 9 commits intoSep 27, 2026
Merged
Juliusolsson05 merged 9 commits into
Juliusolsson05 merged 9 commits into
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Follow-up of #1429. listWorktreesForCwdDetailed is exported and every other consumer acts on timedOut: the conversations family is marked gitTimedOut, not cached, and the picker says siblings may be missing; worktree activity answers { ok: false, timedOut: true } (worktrees.read activityTimedOut, the dump says 'Git timed out'); the agent-activity repo root retries once and then throws instead of filing a worktree's activity under its folder; history chunks skip worktree attribution on a timeout (worktreesForAttribution). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… never as the worktree folder (#1430, q126) Two git timeouts made the recorder fall back to the cwd as repoRoot; the store persisted it and summarize grouped by it, so a worktree became a repository of its own that later intervals could not fold back. It is now recorded as '' (the existing Unknown), with the cwd still naming the worktree row. Pinned through the real recorder and store. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…imed-out history to the reconciler a: a page built after git recovered is not appended to one built while it timed out (useConversationList restarts from page 1 when the family changes). a+b: a history chunk read while git timed out is handed to the live reconciler (WorkspaceRefs.worktreeReconcilerRef, handHistoryToReconciler) so a recovered catalog replays it, instead of losing its worktree evidence. b: the picker note only in Repository scope. a: assert the repository- unknown warning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… drop the dead lister (#1430 review c) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
Author
|
Round-1 disposition. a and b were FIX-BEFORE-MERGE, and c was MERGE-READY on the fixed head. Every valid finding is fixed fail-first.
Head: 93ff416. 🤖 Generated with Claude Code |
…ages never override a known context (#1450 verification a/b) a: with a fresh catalog already cached, refresh() answers 'cached' and never notifies, so a timed-out history chunk never repainted. replayCachedCatalog replays against a real cached catalog; the hand-off calls it on 'cached'. Pinned with the recorded codex-0151 window (was main cwd, now worktree-2). b: the older-history loader handed pages over even when the pane knew a newer context; the reconciler treats observed records as newest, so a recovered catalog moved the pane back. Hand over only while the context is unknown, the same recency rule as the answered-git backfill. Pinned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
Author
|
Verification disposition at 9596a99. Verifiers a and b were both FIX-BEFORE-MERGE; both findings are gaps in the round-1 hand-off, and both are fixed fail-first. The capped pass is now spent.
B6: the verification cap is spent, so please manager-verify a and b at 9596a99. 🤖 Generated with Claude Code |
…lerRef (#1450 CI) useIpcSubscriptions publishes the live reconciler into WorkspaceRefs (round 1); this harness builds refs by hand and lacked the slot, so the publish threw. Also incidental proof the production publish runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nce (#1450 B6 verify) A scroll-up during a git timeout handed the older page over as if it were the newest, so a recovered catalog moved the pane to the older worktree. observe() takes a position; older pages go to the old end of the window (overflow dropped, never folded over newer baseline evidence). Pinned with the recorded codex-0151 window + three-worktree catalog. Also fixes the stale resolveRepoRoot header (Unknown, not the cwd). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…consumers # Conflicts: # src/main/conversations/service.system.test.ts
Owner
Author
|
B6 manager verification (FIX) disposition, at 3279b5b (6492db7 is the fix; the rest is the origin/main merge).
🤖 Generated with Claude Code |
Juliusolsson05
changed the base branch from
main
to
integration/batch-2026-09-27-q
September 27, 2026 21:04
Juliusolsson05
merged commit Sep 27, 2026
74536b6
into
integration/batch-2026-09-27-q
2 checks passed
This was referenced Sep 27, 2026
Merged
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.
Fixes #1430 (found by #1429 review b, findings 2 and 3). Refs #1250.
All four consumers are delivered. B6 manager-verified a and b as MERGE-READY at 3279b5b, which also covers the history bullet's fix (6492db7).
What was wrong
#1429 made the Worktrees panel, GitBar and
worktrees.readsay a git timeout. The exportedlistWorktreesForCwdstill answered[]on a timeout, and four other consumers read that as "this checkout has no siblings":resolveFamilyfell back to the cwd alone, so from a linked checkout the main checkout's conversations dropped out. The service cached that guess for 3 s, and nothing said so.{ ok: false }, the same as "not a repository". The dump showed "Agent activity: unavailable", as if the index were missing.Fix
listWorktreesForCwdDetailedis exported, and each consumer acts ontimedOut.RepositoryFamily.gitTimedOut, andListWorktreesaccepts the detailed answer (a plain list still means git answered);ConversationListResponse.family.gitTimedOut, and the picker shows a muted status line outsidecwdscope: "Git didn't answer in time. Conversations from this repository's other worktrees may be missing."{ ok: false, timedOut: true };loadWorktreeDump.activityTimedOutandworktrees.read'sactivityTimedOutcarry it;resolveRepoRootAfterGitretries a timeout once. After two timeouts it throwsRepoRootUnknown. The recorder then records that interval's repository as Unknown ('', the store's existing "no repository" value) and warns; it never records the cwd. The worktree row keeps its cwd, and the next interval asks git again. It never loops. A real non-repository (git answered, no worktrees) keeps the cwd, as before.worktreesForAttributionreturnsnullfor a timeout, and both history paths then skip attribution for that chunk;WorkspaceRefs.worktreeReconcilerRef,handHistoryToReconciler), so a recovered catalog replays it (round 1, a+b);refreshanswerscachedand never notifies, so the hand-off replays at once (replayCachedCatalog; verification a, 9596a99);observe(..., 'older')). Before this, a scroll-up during a timeout was appended as the newest evidence, and a recovered catalog moved the pane to the older worktree. Overflow is dropped, never folded over newer evidence (B6 verification, 6492db7);[].listWorktreesForCwdremoved: it had no callers left (round 1, c).Tests (fail-first)
service.system.test.ts, on the recorded conversation corpus, from a linked checkout with the list timing out:family.gitTimedOut;worktreeActivity.test.ts, the real handler: timeout vs non-repository vs repository.resolveRepoRoot.test.ts: answered, retry-then-answered, two timeouts throw, and a non-repository keeps the cwd.AgentActivityRecorder.test.ts(q126): the real recorder and store with the real retry policy. Two timeouts then an answer give the first interval under Unknown and the second under the repository, and no worktree-folder repository ever appears. It failed before 74a5c0b, showing a/dev/agent-code/.worktrees/fixrepository.control.renderer.test.ts:activityTimedOutthrough the realworktrees.readandloadWorktreeDump, plus the dump line.worktreesForAttribution.test.ts: the threegit:worktreesanswers.ConversationsPicker.renderer.test.tsx: the note when git timed out, and none when it answered.historyWorktreeTimeout.renderer.test.tsruns the real reconciler with the recordedcodex-0151window and the recorded three-worktree catalog:worktree-2;worktree-1: the newest chunk is the same recorded records moved toworktree-1, and the recorded window is the older page. It was red before 6492db7 (worktree-2).history.renderer.test.tsx:'older';useIpcSubscriptions, and now carriesworktreeReconcilerRef(f5fc358, the CI failure at 9596a99).[](2 red);npx tsc -bclean at 3279b5b (origin/main merged in). Main's side of the conflict inservice.system.test.tswas empty; this branch's timeout test was kept. 1654/1654 across 216 files: conversations, renderer workspace, the conversations feature, agent activity and the worktree-activity IPC.Residuals (accepted by B6)
LiveWorktreeReconciler.retainOlder's two overflow branches have no test (surviving mutations, and B6 found no failure sequence):deferredRaw.worktreeReconcilerRefinuseIpcSubscriptionsis unasserted. The Codex continuity harness mounts it and proves it runs without throwing.Merge order and overlaps
src/main/index.ts, in separate hunks. Whichever reaches READY first merges first, and they never share a batch. The second merges origin/main after the first is on main, runs tsc plus the index.ts-touching startup and shutdown tests, and states that combined check in its body before READY. A test-merge with fix(shutdown): dispose the goal loop at quit, after sessions and the MCP host stop #1449 today is clean.initialHistory.ts. Whichever lands second resolves it.service.system.test.tsnear its end. Whichever lands second merges origin/main again.🤖 Generated with Claude Code