# Issue 23950 — read-only proof audit, pass 1

Scope: [#23950](https://git.cafe/pingdotgg/t3code/issues/23950), branch `fix/issue-23950`, head [0593c8bc89](https://git.cafe/pingdotgg/t3code/commit/0593c8bc89712e399a758aaf4c3fb2c07a88a0cc), base [a46f80ee28](https://git.cafe/pingdotgg/t3code/commit/a46f80ee28d9b498bb8b407c8b60bd4e93bbe2e3). No PR. Source and fixture-script inspection only; no captures, browser, server, state writes, or execution tests in this pass.

The entire diff changes `!expanded && rotate-180` to `expanded && rotate-180` in CollapsibleSectionHeader. Expected endpoint: collapsed points DOWN, expanded points UP, matching the existing workflow outer toggle. Content visibility and aria-expanded must agree with orientation. Before behavior is the inverse. Shared size, spacing, labels, colors and click handling are unchanged.

## Capture contract

Every affected matrix row below requires **1440×900 and 390×844**, each in **light and dark**, each **collapsed and expanded**. Use responsive WEB at 390, with its sidebar drawer or actual details presentation open; this is not native mobile testing. Desktop shares the web component; no separate Electron/OS/provider matrix is warranted. Native mobile does not import this web component.

For EACH row: retain before and after static endpoint stills (collapsed + expanded), and an **interaction recording** of collapsed → expanded → collapsed showing the header, content and rotation together. Capture the four viewport/theme combinations; multiple rows may share a still or recording when clearly visible. Do not substitute a recording for endpoint stills. Capture before and after with identical seed, viewport, theme, scroll, panel/drawer, and header state. No need to multiply this by providers, connection modes, unrelated thread statuses, long titles, or pagination.

| ID / visually distinct fixture | Affected headers / branch | Real-app seed and reachability | State and required evidence |
|---|---|---|---|
| S — Three shelves | Working + Settled muted default header; Snoozed blue/info default header; collapsed count suffix on each | Isolated `.t3` snapshot with at least one unpinned visible thread per shelf. Enable `sidebarWorkingShelfEnabled`; Working must satisfy `isSidebarThreadWorking` (running/waiting without pending approval/input). Keep it unsettled and unsnoozed. Add a settled thread and a different thread with future snooze. Open sidebar (drawer at 390). Select a neutral thread outside these shelves so selected-row retention does not obscure hide/show. | Toggle all three independently, then show all collapsed and all expanded for packed endpoint stills. **Recording + endpoint stills**, full viewport/theme/state grid. |
| R0 — Previous agents, plain | Panel variant, muted; no failure accessory; collapsed `Previous agents (N)` versus expanded `Previous agents` | Seed a parent thread plus a child-thread-linked subagent in its V2 subagent projection with completed status; include the child shell and consistent lineage/project/run IDs. Open parent thread → details → Lineage → Previous agents (initially collapsed). | Toggle header both ways; child list hides/shows and count suffix changes. **Recording + endpoint stills**, full grid. |
| R1 — Previous agents, failed | Same panel header with `1 failed` accessory | Reuse R0 with one failed/error child edge instead of completed (or add one failed child). Terminal statuses route to Previous agents. Keep badge visible in both endpoints. | Count, failure badge, separator and chevron remain legible at 390. **Recording + endpoint stills**, full grid. R0/R1 are two small seed variants, not every terminal-status permutation. |
| W — Workflow phases | Indented panel headers: running/emphasized (default open), done/muted (default closed), failed/muted + Failed accessory; count and elapsed accessory present | Seed parent projection with a child-thread-linked coordinator carrying `workflow` metadata, phase definitions and nested agents assigned by phaseIndex/phaseTitle. Supply coordinator and member shells. Use one workflow with running, completed and failed nonempty phases; fixed timestamps give elapsed text, and one/multiple members cover agent/agents without extra fixtures. Open parent details → Lineage; if terminal coordinator, expand Previous agents; expand workflow outer row first (initially closed). | Show all three phase headers, toggle each independently; capture all collapsed and all expanded. Running defaults open; others closed before interaction. **Recording + endpoint stills**, full grid. The outer toggle is unchanged but provides an in-frame orientation reference. |
| D1 — Settled during drag, emphasized | `dragging=true`, `isDropTarget=false`; emphasized default header | Reuse S, drag a thread while pointer remains outside Settled drop target; actual Settled caller passes dragging when `from !== null`. Start with shelf collapsed, then repeat expanded. | **Drag interaction recording + static held-drag endpoint stills**, full grid. Can be included in S recording; no new data seed. |
| D2 — Settled drop target, accent | `isDropTarget=true` takes precedence over dragging; accent default header | Reuse S, hold thread over Settled drop target; do not release/mutate fixture. Repeat with collapsed and expanded shelf. Working/Snoozed callers do not currently pass dragging/isDropTarget. | **Drag interaction recording + static held-drag endpoint stills**, full grid. Can share D1 recording and S fixture. |

## Caller/branch accounting

- `SidebarListMarkers.tsx`: sole shelf wrapper. Working exists only with working rows; Snoozed only with snoozed rows; Settled exists whenever the overall sidebar list is nonempty. Working setting disabled / empty shelves remove affected headers: no separate visual fixture. S covers muted/info, D1 emphasized, D2 accent. Tone precedence is drop target → dragging → snoozed → muted. Selected route rows can remain under collapsed shelves, hence select a neutral thread.
- `ThreadRelationshipsControl.tsx`: ThreadLineageGroup returns null for no rows; label=null groups (related + active) never render this shared header. Only Previous agents has a label and starts collapsed. Previous includes completed/failed/error/cancelled/interrupted/idle subagents; failed/error alone produce failure accessory. R0/R1 cover the visually distinct branch. Parent/fork/transfer, missing child, pagination >6 and stop/merge actions do not alter this header and need no additional fixtures.
- `ThreadLineageWorkflowRow.tsx`: outer expand toggle is its own ChevronDownIcon, already rotates when expanded. Shared headers appear only after opening it, and only for phases with members. Running is emphasized and initially open; other visible phases are muted and initially closed. Failure label appears only when phase is not running and contains a failed member. Stopped/done/not-started status differences otherwise affect aria text, not a separate visible header label. Empty pending phases are filtered out; unphased members render without phase headers. W covers count/elapsed/failed accessories and all visual tone branches. A running phase with a failed member still follows running priority and has no Failed badge.
- Other exports: SectionHeaderStatus styling is unchanged. No other CollapsibleSectionHeader imports/callers were found under apps/web/src. No Settings, command palette, contract, server, provider adapter or native-mobile change follows from this CSS condition.

## Fixture readiness and proportionality

Existing `/tmp/issue-23950/seed.py` was read, NOT executed. It clones the first thread row and inserts Snoozed/Settled IDs into the isolated worktree database. It does not establish Working or relationships/workflows. It is not idempotent (plain INSERT, fixed IDs); it assumes at least one valid source thread; it copies unrelated fields (including runtime/lineage except rootThreadId) that can affect shelf eligibility. Validate resulting schemas/IDs and clear incompatible cloned fields before future execution; keep normalized columns consistent with payload_json. Do not rerun blindly.

`before-collapsed.png` and `before-expanded.png` exist. Their pixels were not opened in this no-capture audit, so viewport/theme/caller/state coverage is unverified. File existence is not proof that this matrix is covered.

All fixtures above are reachable through real-app isolated projection seeds; no harness is presently justified. Use the test-t3-app SQLite fixture reference: start isolated runtime once for migrations, stop it before direct writes, inspect current columns, copy valid app-written rows, use unique consistent IDs and schema-valid payloads, leave event log unchanged. Extend ephemeral projection state for parent/subagents/workflow rather than actually launching provider work. Resume only isolated `.t3` afterward. These seeds prove UI rendering, not orchestration/business behavior. This audit did not inspect or modify the database and does not certify a ready-to-run relationship fixture. If actual app hydration cannot accept a schema-valid fixture, document that concrete blocker before using an isolated harness importing the real caller/component and theme styles; do not default to a synthetic button demo.

Packing keeps scope modest: one shelf seed (also serves D1/D2), two previous-agent variants, one workflow seed. S contributes three headers in each image; W contributes three phase branches in each image. No backend tests or repo-wide checks are needed to prove this one-condition visual fix. Read-only audit establishes coverage requirements, not passing visual results.

## FRICTION

| category | issue | prevention |
|---|---|---|
| Proof coverage | Existing seed covers only Snoozed/Settled, while shared rotation reaches previous agents and workflow phases | Trace all imports/callers before capturing; use the four small seed scenes above |
| Fixture reliability | Fixed-ID inserts fail on rerun and copied fields may misclassify shelf rows | Inspect schema, create explicit unique IDs, sanitize runtime/lineage, and keep columns/payload consistent in stopped isolated state |
| Evidence provenance | Existing before filenames omit viewport/theme/caller metadata | Name evidence by revision, fixture, viewport, theme, state; retain matched endpoints and recordings |
| Scope control | Generic header props could trigger unnecessary provider/status permutations | Cover actual rendered branches only; pack shelves/phases; exclude no-header and empty-phase branches |
