Split agent-card.tsx into header, status, details, and actions files - #803
Merged
Conversation
agent-card.tsx had grown to 829 lines rendering four logically independent regions in one render tree. Each region is now its own file, leaving the card as a composition shell that owns only layout, expansion state, and the drag-handler effect. - agent-card-header.tsx (254) — type icon, session name, rename prompt (state and handler moved along with it), status badges, resume, expand toggle - agent-card-status.tsx (160) — setup/archive phase lines, latest-event summary, repo label - agent-card-details.tsx (207) — branch/worktree panel, diff stats, IDE launch, sandbox indicator (owns its own copy-to-clipboard state) - agent-card-actions.tsx (123) — persona launcher plus lifecycle controls - agent-card.tsx 829 → 267 Purely structural: markup, class names, and test IDs are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Jul 20, 2026
selfcontained added a commit
that referenced
this pull request
Jul 24, 2026
* Cover the agent-card split: header, status, details, and actions PR #803 split agent-card.tsx into four presentational files, none of which had direct unit coverage. Add agent-card.test.tsx, which renders the real AgentCard (only /lib/api is mocked) and asserts the wiring that a split like this is most likely to break: - the connected-child override that neutralizes the parent's visual state and drops its selection highlight - header row click routing: attach, detach-and-collapse when already connected, ignore clicks on controls, no-op while stopped - the rename prompt's gating and its POST, plus the disabled window that stops a double click firing twice - setup/archive phase lines, and the latest-event line's terminal-agent and expanded-message branches - worktree vs plain working-dir details, full-access vs sandboxed, and the copy confirmation surviving a collapse (it is owned by the card, not the details panel, precisely so it does) - pause vs archive routing to their own targets, and the persona card hiding lifecycle actions Verified non-vacuous: 17 source mutations, 17/17 caught. framer-motion is mocked out so collapse/expand is synchronous — its exit animation otherwise leaves the old subtree mounted for an indeterminate number of frames. Also gives the header's icon-only resume button an aria-label; it had no accessible name at all, so assistive tech (and role-based queries) could not reach it. * Address review: fix a false green and make the timing explicit The agentVisualState stub mapped `archiving` to "active", but the real mapper in hooks/use-agents.ts treats anything that is not running or creating as stopped. That made the `status !== "archiving"` half of both resume guards untestable — deleting it left the suite green while the UI would offer Resume on a card that is mid-teardown. The stub now mirrors production, and two new mutants cover both guards. Also from the review: - drive the 1.5s rename re-arm and the 2s copy confirmation with fake timers instead of racing the wall clock, and assert the re-arm rather than only the initial disable - install the jsdom globals through vi.stubGlobal / explicit teardown so they cannot leak if per-file isolation is ever turned off - spread the real framer-motion module into the mock, so a descendant importing anything else from it fails loudly instead of opaquely - drop a self-parenting persona fixture that silently tested the fallback branch it appeared to be setting up - scope the sub-agent count assertion to its own row - correct a comment claiming the setup phase has a generic fallback (it does not; the archive phase does, now asserted) The header's resume button is labelled "Resume session" (matching its tooltip) rather than "Resume", so it does not collide with the footer's Resume button on an expanded stopped card. Mutation battery re-run: 20/21 caught. The survivor is the unreachable job- guard in hasDefaultSessionName, called out in the test file.
This was referenced Aug 2, 2026
This was referenced Aug 10, 2026
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.
What
agent-card.tsxhad grown to 829 lines. Its render tree contained four logically independent regions, each with its own props, state, and concerns. This splits them into sibling files, leaving the card as a composition shell.Why it was a candidate
New file structure
agent-card.tsxagent-card-header.tsxagent-card-status.tsxagent-card-details.tsxuseCopyTextstate)agent-card-actions.tsxBehavior
Purely structural. Markup, class names,
data-testids, and handler wiring are unchanged. The only dedupe is the latest-event summary row, which the original repeated verbatim across its expanded/collapsed branches — both call sites still pass their exact original class strings.Validation
pnpm run finalize:web— type check + production build passpnpm run test:e2e— 169 passed, 12 skippedNext run
Queued:
apps/web/src/components/app/jobs-pane.tsx(746 lines) — extract job list items, job detail panel, and data-fetching hooks.🤖 Generated with Claude Code