Cover the agent-card split: header, status, details, and actions - #824
Merged
Conversation
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.
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.
Uh 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.
Recurring test-enforcer run for 2026-07-23.
Suite health
Green on the first pass, 5th consecutive run — nothing to fix.
pnpm run checkcleanpnpm run test:e2e: 169 pass / 12 skip (tmux-gated), 46s, zero stallspnpm run finalize:webcleanCI scan of the last 50 GitHub Actions runs found no test flakes. The one new failure (Release run 30041119104) is the
publish-releaseguard correctly refusing to tag afterorigin/mainadvanced mid-release — infra, not a test. The four pre-merge PR #808 failures were already classified in an earlier run. The Brain flakes list is empty and stays empty.Coverage added
PR #803 split
agent-card.tsxinto four presentational files, none of which had direct unit coverage — that was the queuednext_focus.agent-card.test.tsxrenders the realAgentCard(only@/lib/apiis mocked) and asserts the wiring a split like this is most likely to break:Verified non-vacuous by 21 source mutations, 20 caught. The survivor is the
startsWith("job-")guard inhasDefaultSessionName, which is unreachable — ajob-name can never equal theagent-<id suffix>default the same predicate requires. That is noted in the test file rather than papered over with a test that would pass for the wrong reason.Review round
One general review agent on this run's diff caught a real false green: the
agentVisualStatestub mappedarchivingto"active", while the real mapper inhooks/use-agents.tstreats anything not running or creating as stopped. That made thestatus !== "archiving"half of both resume guards untestable — deleting it kept the suite green while the UI would offer Resume on a card mid-teardown. Fixed, with two mutants covering it. Also fixed from that review: fake timers for the two source-defined windows, restorable jsdom globals, a framer-motion mock that spreads the real module, a self-parenting persona fixture, an unscoped count query, and a comment describing a fallback the component does not have.Source changes
Two lines, both in
agent-card-header.tsx: the icon-only resume button had no accessible name at all (lucide SVGs contribute none, and Radix tooltips only supplyaria-describedbywhen open), so it now carriesaria-label="Resume session"— distinct from the footer's"Resume"so an expanded stopped card has no ambiguous pair.🤖 Generated with Claude Code