Skip to content

Testing plan: a pull request appears once on the board

Derived from the locked requirements.md and design.md, before tasks.md. Authored at test-planning, completed at verification.

Test matrix

#TypeApplies?Scope / what it provesWhere it runs
T1Unit — the joinyesa claimed PR with its own portable record yields one view, not two; an unclaimed PR keeps its top-level row; a treeless owner's claim and a claim on a ref with its own session are not honoured; a self-claim and a two-level claim leave every row standingcd ui && bun run test -- src/api/model.test.ts
T2Unit — the foldyesthe nested row carries the PR's record and falls back to poll.lastPolledAt for its age; the PR's attention and open question reach the inbox on the owner's card, named for the PR; the owner's row raises needs input; no other chip is promotedcd ui && bun run test -- src/api/model.test.ts
T3Component / Reactyesthe sidebar draws the PR once — one nested row, no top-level row for the same ref — against a fixture holding both identitiescd ui && bun run test -- src/App.test.tsx
T4Unit — the serviceyeslist_attention reports no armed-without-session for an armed ref whose live session is a nested PR endpoint, and still reports one when that endpoint is closedcd cli && uv run pytest tests/test_core_attention.py
T5Contract (OpenAPI)n/a — no route, request or response shape is touched (R4.1); GET /work-items keeps serving every record and GET /attention keeps its item shape
T6Integration / end-to-endn/a — no routing, dispatch or registry write path changes; the poller and link_pull_request are untouched
T7UI / visualyesthe rendered sidebar against a demo fixture carrying both identities: one row for the PR, nested, with an age. design.uiArtifacts.screenshotEvidence requires the screenshot for a UI changeChromium via Playwright over the production build, demo mode
T8Accessibilityyesthe nested list keeps its accessible name and the row count drops by one — asserted through roles, not classescd ui && bun run test -- src/App.test.tsx
T9Regressionyesissue-300's nesting behaviour is unchanged for every item that had no duplicate: labels, treeless loops, deep links, the trace tabscd ui && bun run test (full suite)
T10Lint / typecheck / buildyesthe commands CI runs, at the versions the lockfiles pin, on both sidescd ui && bun run lint && bun run build; cd cli && uv run ruff check . && uv run pytest
T11Security / abuse caseyesA1 — a session claiming another work item, and a two-level claim, cannot remove a row (both covered by T1's hostile-record cases); A3 — a closed nested endpoint does not suppress armed-without-session (T4)T1, T4
T12Performancen/a — one extra pass over the sessions array the join already maps, no fetch; the service adds one nested loop over the same list it already walks

Scenarios & requirement trace

RowRequirement(s)Scenario / case
T1R1.1a labeled PR with a portable record and an endpoint under its issue renders once
T1R1.2a PR no session claims (linked to no issue) keeps its top-level row
T1R1.3an ad-hoc / contribution / review owner draws no nested rows, so its claimed PR stays top-level
T1R1.4a PR with a session record of its own keeps its row, and keeps reaching its own tmux target
T1R1.5, A1a session listing itself, and a claim by a ref that is itself claimed, leave both rows
T2R2.1the nested row's age falls back to the PR record's poll.lastPolledAt
T2R2.2a recent-error on the PR's ref appears on the owner's card as recent error · PR, with the PR's short ref
T2R2.3an open question on the PR's ref gives the owner a needs input chip and a Reply entry keyed to the PR
T2R2.4a PR's human gate does not become a chip on the owner's row
T2R2.5a treeless owner's PR keeps its own row and its own card; the owner reports nothing
T3, T8R1.1the sidebar shows one row for the PR, inside its item's list
T4R3.1an armed ref whose only live session is a nested endpoint is not "armed without a session"
T4R3.2, A3a closed nested endpoint still reports it; nothing else in the attention list changes
T7R1.1, R2.1the rendered board: one row, nested, with an age
T9, T10R4.1, R4.2the rest of the suite is unchanged; both sides lint, type, test and build

Verification results

Recorded at verification in evidence/verification.md, with the T7 screenshot beside it.

Released under the MIT License.