Uh oh!
There was an error while loading. Please reload this page.
fix(chat): pending shell row stops impersonating an error; chips survive a shell-driven session - #99
Merged
Conversation
…s survive a shell-driven session
Two reports from the same screenshot, two unrelated causes.
1. "A CONSTANT ERROR NOT GOING AWAY EVEN THOUGH MY SESSION IS PROGRESSING."
The shell row's label chain was `command ?? title ?? description`. A PENDING
bash part has no `input.command` yet, so it fell through to the model's
free-text description and rendered a full prose sentence in the slot where
users read a command — for the command's whole duration (1m55s observed).
The text was a paraphrase of agent guidance: "A local launch is REFUSED by
amico-run while this solver is selected (exit 64), so attempting one only
wastes a turn." Nothing had failed. The solve underneath was on iteration 29
with frames on disk, and the solver was `piccolo`, so the sentence was not
even applicable.
The description fallback is worth keeping (often a useful "Install deps"), so
the fix is not to drop it but to stop it impersonating a command: unwrap
quotes, first line only, clamp to 72 chars with an ellipsis. Prose can no
longer fill the row.
2. "WHAT HAPPENED TO THE CHIPS AT THE TOP."
The rail's session gate was `part.tool.startsWith("amicode_")`, so a session
that did its amicode work through the SHELL showed no chips at all. Observed
the same session create a problem workspace, write a solvespec, and drive a
solve to iteration 29 — entirely via bash and amico-run — with the rail hidden
the whole time. It had real entities to describe and refused to.
The gate now also matches a shell part whose command drives amicode
(`amico-run`, `.amico/problems`, `amico plan|spec`). It stays SESSION-scoped,
which is the point of the gate — an unrelated session still shows nothing, and
there is a test pinning that.
The refetch key is deliberately NOT broadened: shell parts don't mutate the
problem view through the tool seam, so counting them would refetch on
unrelated shell activity.
Both rules are extracted to pure modules (rail-gate.ts, shell-row.ts) because
neither was testable inside its .tsx and both shipped a user-visible bug. 15 new
tests; ui suite 318 pass; tsgo clean in ui and app.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>Reported right after the chips: "where did the little amico icon go, why is that not active anymore?" Same cause. The working-presence lane (the pulsing H-mark + thinking line) gated on its own copy of the amicode_* tool-name test: p.type === "tool" && /^amicode_/.test(p.tool) identical in spirit to the rail's gate, and duplicated. So a session that did its amicode work through the SHELL lost the chips and Amico's presence together — the mark read as "inactive" while a solve was running at iteration 29. It now calls sessionHasAmicodeParts, so there is ONE definition of "this session is amicode work" and one place to widen it. Behaviour for tool-driven sessions is unchanged; shell-driven sessions get their presence back. Worth noting this was the third symptom of a single assumption — that amicode work always arrives as an amicode_* tool part. Chips, presence mark, and (indirectly) the missing telemetry all traced to it. ui 318 pass; tsgo clean in ui and app. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Rchari1force-pushed
the
rchari/chat-row-and-rail-gate
branch
from
July 29, 2026 09:54
3c4e6fc to
c138994CompareUh oh!
There was an error while loading. Please reload this page.
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 freeto 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.
Two reports from the same screenshot, two unrelated causes. Both were untestable where they lived, and both shipped a user-visible bug, so each rule is extracted to a pure module with tests.
1. "A constant error not going away even though my session is progressing"
The shell row's label chain was
command ?? title ?? description. A pending bash part has noinput.commandyet, so it fell through to the model's free-textdescriptionand rendered a full prose sentence in the slot where users read a command — and held it for the command's whole duration (1m55s observed).The text was a paraphrase of agent guidance:
Nothing had failed. The solve underneath was on iteration 29 with frames on disk, and the solver was
piccolo, so the sentence wasn't even applicable. It just looked exactly like a hard error that wouldn't clear.The description fallback is worth keeping — it's often a useful "Install deps" — so the fix isn't to drop it but to stop it impersonating a command: unwrap quotes, first line only, clamp to 72 chars with an ellipsis.
2. "What happened to the chips at the top"
The rail's session gate was
part.tool.startsWith("amicode_"). A session that did its amicode work through the shell therefore showed no chips at all.That's what happened here: the same session created a problem workspace, wrote a
solvespec.json, and drove a solve to iteration 29 — entirely viabash+amico-run, never calling anamicode_*tool. The rail stayed hidden the whole time despite having real entities to describe.The gate now also matches a shell part whose command drives amicode (
amico-run,.amico/problems,amico plan|spec). It stays session-scoped, which is the entire point of the gate — an unrelated session still shows nothing, and there's a test pinning that.The refetch key is deliberately not broadened. Shell parts don't mutate the problem view through the tool seam, so counting them would refetch the problem on unrelated shell activity.
any(the gate) widens;completed(the refetch key) doesn't.Testing
15 new tests, including the exact reported strings as regression cases: the quoted guidance sentence must clamp and lose its quote, and a shell-launched solve must open the gate while
git statusmust not. Plus the fiddly edges — pending parts with no input, empty-string commands not beating a usable description, exact clamp boundaries.ui: 318 pass.tsgoclean inuiandapp. Both fixes verified present in the builtdarwin-arm64binary (the clamp constant and the shell markers; symbol names are minified away).Note
These are UI-only. Neither is deploy-gated — worth saying because the chips in particular looked like they might be fixed by shipping something, and they weren't: the gate was rejecting a legitimate session shape.