web: fold the activity group and the settled approval card to one line - #173
Merged
Conversation
A long run's transcript is the answers, not the plumbing. Consecutive tool lines now sit under one native details whose summary reads "Working on it" and the latest line's phrase while the turn is adding to it, and the count, "3 steps" or "3 steps, 1 failed", once it is closed. The lines themselves are built exactly as before and are one click away. Every place that used to null the group now goes through closeActivityGroup, so the summary is finalised in one place, and a replayed group is closed as soon as it is drawn. The approval card is a details too: open and refusing a click on its head while it waits, folded to its head with the outcome and the tool name once settled, with the arguments and the note under it. Both pieces of DOM building move out of main.ts into activity-group.ts and approval-card.ts so they can be tested without a page. The phrase on the summary is read off the line and written through textContent after the same clamp the line used. Nothing about what is stored or sent changed. Claude-Session: https://claude.ai/code/session_01PG2vuux5tMsjnZBLWJzMyp
…it reports The browser's tool line no longer writes its status word beside the phrase. The result is the bullet's colour, from exactly one of activity-ok, activity-fail or activity-running on the line, with the word kept in the line's title and, for a shell call, under the verbatim command in the details. stateForStatus in web/src/activity-line.ts is the one mapping: exit 0 and passed are ok, the tools' failure vocabulary is fail, and the other tools' own success summaries stay ok, the same split the agent loop uses for succeeded. The verify line keeps its word and takes the same classes. Renderer::tool_starting is a new trait method with an empty default, called from Agent::run_tool after approval and before dispatch, so a denied call never draws as running. WebRenderer sends it as a tool_started frame with the name and phrase the tool frame will carry; the browser appends a running line on the first and settles it in place on the second. A replayed session has every result, so no replayed line is in progress, and a turn that ends with a line pending fails it with the reason in its title. Claude-Session: https://claude.ai/code/session_01PG2vuux5tMsjnZBLWJzMyp
…y-and-approval Resolves the overlap in web/src/main.ts: both imports, both pieces of state, the tool line comment says colour and collapse, and every reset site closes the group and drops the pending tool line. Both decision entries are kept. Claude-Session: https://claude.ai/code/session_01PG2vuux5tMsjnZBLWJzMyp
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.
What
Browser only, no Rust. Two collapses in the transcript, both native
detailswith no toggle code of their own.Activity group. Consecutive tool, verify and notice lines now sit under one
details.activity. Its summary reads "Working on it · " while the turn is still adding to the group, and "N steps" or "N steps, M failed" once it is closed. The lines themselves are built exactly as before byactivity-line.tsand are one click away. The phrase is read off the latest line's.activity-briefor.activity-nameand written back throughtextContentafterclampPhrase, imported fromactivity-line.tsrather than written twice. Appending never toggles the group, so a reader who opened it keeps it open. Group state is computed from the lines'activity-ok/activity-fail/activity-runningclasses withclassList.containsand put on thedetails, which colours the marker; a line with none of the three counts as ok, so nothing depends on those classes existing.Every place that used to write
activityGroup = nullnow goes through onecloseActivityGroup(), and thedoneevent and the replay inopenSessioncall it too, so the summary is finalised in exactly one place. Nothing inappendActivityscrolls;applyEventstill decides that once, after the event, from where the reader was, and a collapsed group does not change height on append, so it cannot steal scroll position.Approval card.
details.card.card-approvalwith the head as itssummary. Open while pending, and a click on the head is refused withpreventDefaultwhile the buttons are live, so a person cannot fold away what they are deciding on.settlesetsopen = false, so the settled card is its head line only: the outcome title,code.tool-nameand the outcome tag, with the arguments and the note one click under it.prettyArgumentsoutput still goes throughtextContentonly.Modules. The two pieces of DOM building move out of
main.tsintoweb/src/activity-group.tsandweb/src/approval-card.ts, in the shape ofactivity-line.tsandapproval-mode.ts(take aDocument, return the element plus small update functions), so they can be tested without a page.tsconfig.jsongainsallowImportingTsExtensionssoactivity-group.tscan import./activity-line.tswith the extension thatnode --testneeds; esbuild resolves it the same way.Docs.
docs/DECISIONS.mdentry dated 2026-09-05, and one sentence each in theweb/bullet ofCLAUDE.mdandAGENTS.md, identical.Tests
web/test/activity-group.test.ts(8) andweb/test/approval-card.test.ts(6): an injection string in a phrase and in a tool name or arguments renders as text; a fresh group reads "Working on it" and follows the latest phrase, clamped; the lines are kept as built; appending never toggles; closing gives "1 step", "3 steps", "3 steps, 2 failed"; the group takes running over failed over ok; a waiting card is open and refuses a head click; a settled card is closed with the tool name in its summary and the arguments and note still underneath; every outcome has its title and note.From
web/:npm run check,npm test(373 pass, 0 fail) andnpm run buildall pass.Not changed
What is stored or sent.
activityLine,verifyLine,noticeLineandactivity-line.tsare untouched.https://claude.ai/code/session_01PG2vuux5tMsjnZBLWJzMyp