From 31151e7aa68c970320e1e9db2179797d6cdbd5db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Tue, 25 Aug 2026 09:45:37 +0000 Subject: [PATCH] todo: refresh mid-turn folds the still-running tool call Co-Authored-By: Claude Fable 5 --- TODO.md | 6 +-- ...h-mid-tool-call-renders-the-turn-folded.md | 45 +++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 todo/known-bugs/refresh-mid-tool-call-renders-the-turn-folded.md diff --git a/TODO.md b/TODO.md index 48934da7..bbf595ad 100644 --- a/TODO.md +++ b/TODO.md @@ -21,7 +21,7 @@ the owner's OS user and can never be granted. Indirection there really is accide ## Themes -**94 open, 30 closed**, across 32 themes. +**95 open, 30 closed**, across 32 themes. | Theme | Open | Closed | | ------------------------------------------------------------------------------------------ | ---- | ------ | @@ -37,7 +37,7 @@ the owner's OS user and can never be granted. Indirection there really is accide | [Fleet — one command across every server](todo/fleet/) | 5 | 2 | | [Headscale](todo/headscale/) | 0 | 5 | | [Infra (alpha)](todo/infra/) | 7 | 0 | -| [Known bugs](todo/known-bugs/) | 4 | 3 | +| [Known bugs](todo/known-bugs/) | 5 | 3 | | [Memory — one store instead of per-harness files](todo/memory/) | 1 | 0 | | [Mobile apps](todo/mobile-apps/) | 3 | 0 | | [Multi-user](todo/multi-user/) | 17 | 5 | @@ -69,6 +69,7 @@ the owner's OS user and can never be granted. Indirection there really is accide - `2026-08-25` **An affordance: a scoped agent warns when a request lands outside its scope** — [affordances/an-affordance-a-scoped-agent-warns-on-the](todo/affordances/an-affordance-a-scoped-agent-warns-on-the.md) - `2026-08-25` **Resurrect Projects/Apps** — [backburner/resurrect-projects-apps](todo/backburner/resurrect-projects-apps.md) +- `2026-08-25` **Refresh mid-turn folds the live tool call — it reads as finished while still running** — [known-bugs/refresh-mid-tool-call-renders-the-turn-folded](todo/known-bugs/refresh-mid-tool-call-renders-the-turn-folded.md) - `2026-08-25` **The model picker shows `claude-code` instead of the model that is running** — [known-bugs/the-model-picker-shows-the-bare-harness](todo/known-bugs/the-model-picker-shows-the-bare-harness.md) - `2026-08-25` **Understand how Claude and opencode do memory, then centralize both into one vector database** — [memory/understand-and-centralize-agent-memory-into-a](todo/memory/understand-and-centralize-agent-memory-into-a.md) - `2026-08-25` **Add a favorites tab/panel to the file browser** — [multi-user/add-a-favorites-tab-panel-to-the-file-browser](todo/multi-user/add-a-favorites-tab-panel-to-the-file-browser.md) @@ -76,4 +77,3 @@ the owner's OS user and can never be granted. Indirection there really is accide - `2026-08-23` **An agent cannot learn its own transcript id, so it cannot sign its own work** — [agent-coordination/an-agent-cannot-learn-its-own-session-id](todo/agent-coordination/an-agent-cannot-learn-its-own-session-id.md) - `2026-08-23` **The SendOff file size limit is one constant for everybody** — [sendoff/per-user-size-limit](todo/sendoff/per-user-size-limit.md) - `2026-08-22` **A commander picks the cheapest model that will do the job — for itself and for what it spawns** — [background-jobs/a-commander-picks-the-cheapest-model-that-will](todo/background-jobs/a-commander-picks-the-cheapest-model-that-will.md) -- `2026-08-22` **Revisit the bun 1.3 pin once 1.4 has been watched for a while** — [infra/revisit-the-bun-1-3-pin-once-1-4-has-been](todo/infra/revisit-the-bun-1-3-pin-once-1-4-has-been.md) diff --git a/todo/known-bugs/refresh-mid-tool-call-renders-the-turn-folded.md b/todo/known-bugs/refresh-mid-tool-call-renders-the-turn-folded.md new file mode 100644 index 00000000..bc127da5 --- /dev/null +++ b/todo/known-bugs/refresh-mid-tool-call-renders-the-turn-folded.md @@ -0,0 +1,45 @@ +--- +id: known-bugs/refresh-mid-tool-call-renders-the-turn-folded +title: 'Refresh mid-turn folds the live tool call — it reads as finished while still running' +theme: known-bugs +status: open +created: 2026-08-25 +date_source: stated +order: 5 +--- + +**Refresh mid-turn folds the live tool call.** Reported 2026-08-25: refreshing while an agent is mid +tool-run collapses that turn's tool calls instead of leaving them expanded, so the chat reads as +finished when the agent is still working. Requested fix: the last, still-running turn must always +render EXPANDED across a refresh or a back-navigation, never folded. + +**This is not unbuilt — there is already code for exactly this case, and it is being defeated +somewhere between the transcript load and the live-state confirmation.** `turn-rows.ts`'s `buildRows` +computes `generatingNow = isLast && isGenerating` and refuses to fold the last turn when it is true — a +comment there names this precise failure mode: _"for those few frames every unfinished turn looks +finished."_ So the intended behaviour is real; the bug is that the frames it warns about are not always +brief. + +Where the race most likely lives, traced but not proven — `hooks/useChat.ts`: + +- **`historicalCount` starts at `preloadedMessages?.length ?? 0`** (line ~110) — the whole HTTP-loaded + transcript, tool call included, counted as history from the first render. +- **`isGenerating` starts `false`** and is only set true when the socket confirms it — via + `sync:live` (rebinding to a turn that kept running) or `sync:messages` (a full resume). +- **`sync:live`'s own comment says messages are "deliberately absent — the transcript already loaded + over HTTP"** — it sets `isGenerating` but does not touch `historicalCount`. `sync:messages`, by + contrast, sets both together in one call (`setHistoricalCount(transcript.length)` immediately before + `setIsGenerating(msg.isGenerating)`), which is the version that should self-correct. + +So the two socket messages that confirm "still generating" do not treat `historicalCount` the same way, +and a refresh's actual sequence — HTTP transcript first, socket confirmation after — is exactly the +gap the `generatingNow` guard was written to close but may not fully reach depending on which message +arrives. Worth checking first: whether `sync:live` reliably fires before the user notices, and whether +server-side `session.isGenerating` (true from turn-start to turn-end in `claude-manager.ts`, tool calls +included) is actually what reaches the client in that message — or whether it's a timing gap rather +than a wrong value. + +Possibly related, same neighbourhood (refresh + a live turn + folding), not confirmed as the same +cause: `known-bugs/refreshing-a-finished-chat-turn-loses-output` — a different symptom (a turn that DID +finish loses its output entirely and misreports `0 turns · 0 tok`) but the same refresh-time seam +between what the transcript says and what the live socket confirms.