# Proof audit, pass 1: fixture matrix

Target: [#33038](https://git.cafe/pingdotgg/t3code/pull/33038), head [b78ce3405f](https://git.cafe/pingdotgg/t3code/commit/b78ce3405f725938b6643a2543ae3be33dc3067d), merge-base [d1aeed2492](https://git.cafe/pingdotgg/t3code/commit/d1aeed249288585390dbac4fde5b54c35bd5fc06). Audited 2026-11-10 in `/home/user/wt/pr-33038`. Local HEAD and GitCafe `headOid` agree; checkout clean. Read-only source/evidence-provenance audit: no app, server, test, provider turn, code edit, push, or comment was run. Existing media were mapped using their published evidence manifests; this pass does not claim a new pixel or video-frame audit.

## Findings

1. **Three required rows remain unproved at this head:** F11 (restore transition), F18 (footer growth below a detached exact bottom), and C01 (GuestPage). F11 has an older recording, but its changed scheduling is precisely the behavior under audit. The other two have no capture. This is a proof-sufficiency finding, not a new implementation defect.
2. **Keep the existing evidence for unaffected scenarios.** F01 light/dark, F03/F04 boundary/navigation, F06 no overflow, W02 hover/focus rail, R01 detached viewport shrink, and C03 desktop bottom still apply to their stated settled paths. F13 still establishes settled followed/detached row growth, not current-head transient timing. Do not repeat an old claim that its observed 0.2–0.5 s disabled-state lag measures this head.
3. **Guest layout is producible as a labelled harness capture on this VM.** A genuine create/redeem flow is unavailable without T3 Connect. Rendering the actual GuestPage with a mocked session response and EventSource is already demonstrated by its browser test. Capture the successful guest timeline, not a connection error or a lookalike. This proves layout and local navigation, not production guest authentication, signing, networking, or expiry enforcement. First-party provider OAuth is unnecessary for all proposed fixtures.
4. **The PR body's “final head” sentence is stale.** It names [4a337eb0fc](https://git.cafe/pingdotgg/t3code/commit/4a337eb0fce6f4bfdbe84ca465a4982613c5d421) and says only viewport resize differs from the earlier capture. Footer metrics and committed-restore refresh were added afterward. Preserve truthful per-capture SHAs and describe retained media as applicable evidence for unchanged paths; do not relabel their capture SHA as the audited head.

## Derivation and freshness

The requested three-dot diff changes only [MessagesTimeline.tsx](https://git.cafe/pingdotgg/t3code/blob/b78ce3405f725938b6643a2543ae3be33dc3067d/apps/web/src/components/chat/MessagesTimeline.tsx), [TimelineMinimap.tsx](https://git.cafe/pingdotgg/t3code/blob/b78ce3405f725938b6643a2543ae3be33dc3067d/apps/web/src/components/chat/TimelineMinimap.tsx), and the former's browser tests. The added state reads `scrollHeight - scrollTop - clientHeight <= 1` from the real list scroll node; this is independent of the 40px follow zone. Next has no target when current is invalid, current is last, or `atEnd` is true. Previous is unchanged.

After the principal captures at [8e252d57cd](https://git.cafe/pingdotgg/t3code/commit/8e252d57cd524d2ed2beca9a55ca0b4a0252c21b):

- Viewport ResizeObserver refresh was added and separately captured at [4a337eb0fc](https://git.cafe/pingdotgg/t3code/commit/4a337eb0fce6f4bfdbe84ca465a4982613c5d421). R01's resize path is unchanged since then.
- [ddd1015009](https://git.cafe/pingdotgg/t3code/commit/ddd10150096d5ce6156c4a6153ad314e95f64aec) wires LegendList `onMetricsChange` to the refresh scheduler. The installed LegendList emits these metrics for header/footer size, not streamed row size or every scroll. Hence this creates a missing header/footer geometry path without invalidating the old scroll-boundary or row-growth endpoint evidence.
- [e9f6a92157](https://git.cafe/pingdotgg/t3code/commit/e9f6a92157a8a709c1c1e78dfaf0f08e1f5bfacf) moves restoration back to its original effect position and schedules minimap refresh in a separate layout effect after `restoringThreadPosition` commits false. F11's old callback-before-commit recording cannot prove this new ordering.
- The latest main merges do not change the minimap logic, guest caller, viewport/follow/restore helper, or LegendList patch/package version relative to the principal captures. Other web changes include prompt suggestions after steering and touch panel resize; neither path is exercised by the retained short Replay turns and stationary geometry. Do not generalize those captures to steering suggestions or touch resizing.

### Every production caller and render boundary

- ThreadRouteView renders ChatView for a draft, its promoted server thread, or an ordinary server thread, including a shell while detail loads. ChatView renders ThreadTimeline, the sole normal caller of MessagesTimeline. ThreadTimeline chooses optimistic draft entries or live server entries, then cached entries during switching/loading. Display identity may differ from route identity. Draft promotion keeps the same view slot. These partition into F07/F11/F12.
- RightPanelSurfaceContent renders SideChatPane, which embeds ChatView with its own parent/header, narrow width, and independent list. That reaches the same ThreadTimeline chain (C02).
- GuestPage -> GuestSession -> GuestThread directly renders MessagesTimeline: this is the only other production caller. It uses projected streamed entries, a guest-only identity, guest header/composer, no timeline anchor, zero composer inset, optional earlier-history header, and optional unplaced guest-message footer (C01).
- MessagesTimeline merges ThreadFindTimelineContext into props and suppresses live follow while find is open, then always renders its private memoized ConversationTimeline. ConversationTimeline either renders the visible empty placeholder, a blank loading placeholder, or LegendList plus TimelineMinimap. TimelineMinimap has exactly this one production caller; its navigation helper renders Previous and Next. Direct component renders elsewhere are tests.
- Electron wraps these web paths; native React Native mobile renders its own timeline and has no minimap. Narrow/coarse-pointer web is still relevant. No new transport, provider-adapter, RPC contract, MCP entry point, settings action, or keybinding is introduced. Existing rail/button keyboard and pointer entry points remain relevant.

### Layout inputs and conditional paths, collapsed by visible behavior

All MessagesTimeline prop families are accounted for here; callbacks affect layout only when they produce the state or interaction named:

- Entries/runs/latest and running run, `isWorking`, runless work, start time, turn diffs, rollback capability/checkpoint readiness/revert counts, worktree setup, and persisted expansion sets determine the row sequence and height. Work/approval state, tool visibility, revealed messages, citations and find can expose folds or add rows. Families rendered are user/assistant messages; assistant metadata; work/work-live/work-toggle/thinking inside standalone/group-header/group-content work blocks; turn and attempt folds; context compaction; proposed plan; HTML render; MCP app; working; worktree setup; and events/subagents. Grouped messages, assistant metadata and each row family have distinct padding. These are geometry equivalents for this diff: short rows (F01/F06), tall final turn (F05), mixed/disclosed/media rows (F08/F14), and growing rows (F13). System/non-message content does not add minimap user strips.
- `parentThreadLink` null/subagent/side-chat, optional remote environment label/open action, and `workflowOpening` choose header content. `historyControls` absent, exhausted, available, loading or error changes the history header. `footer`, unmatched pending approvals (excluding held requests), responding state/permissions, and composer inset add footer content. The ordinary footer can contain handoff, current work/status, guest requests and queued turns. Header/footer measurements now refresh the minimap (F18); parent/history render variants are F08/C01/C02.
- `anchorMessageId` and ready/size callbacks choose anchored end space; `contentInsetEndAdjustment` is then list inset rather than footer spacer. `emptyPlaceholderInset` centers an empty scene; `hideEmptyPlaceholder` selects visible vs blank placeholder. `liveFollowEnabled`, viewport attachment/follow release, footer-grow callback, working/settling/reduced-motion state, citation positioning, find, restoration and fullscreen app rows determine whether to follow and whether following animates (F07/F12/F13/F14/F18).
- `routeThreadKey`, `displayThreadKey`, listRef, environment/workspace identity, row cache, remembered row/offset/end and disclosures govern restoration. First mount/default end, reused thread, saved row or missing-row offset fallback, cancellation by navigation, citation ownership and find-open release are F11/F12. Restoration completion can happen without scrolling. Pending refreshes coalesce to one animation frame; cleanup cancels frames. Refresh skips restoration, stale list data, missing state, or zero user items (F09).
- Theme and timestamp format, markdown cwd/workspace/skills, attachment/HTML render sources, file/image actions, rollback/fork/diff/artifact/app-message/shell/thread actions and their availability change row content, wrapping or expansion. They do not add an independent at-bottom decision. Representative long text, media, controls and expanded content are F05/F08/F14/F15. Announced run, detail-behind-shell, awaiting request and status-announcement flags affect accessibility/activity context; no separate visible minimap state is introduced. Top fade changes decoration, not scroll distance.
- Width is measured on the actual timeline and content lane. With side gutter `g=(viewportWidth-min(viewportWidth,contentWidth))/2`, persistent is `g>=48`, hit width is `max(0,min(40,floor(g)-12))`, and navigation accepts pointer events only at hit width >=14 with no pass-through drag. W01–W04 cover these intervals, fine/coarse pointer, width settings/font scale and narrow padding.
- Minimap item count below 2 returns null. Null/invalid current disables both; first current disables Previous; last current disables Next regardless of bottom; interior current enables both unless at bottom. Visible strips are marked imperatively from actual buffered-row geometry, falling back to state scroll when the DOM reference is unavailable. Counts set 8px natural spacing capped at `100vh - 18rem` (F01–F09).
- Active preview is absent or first/interior/last aligned. Empty/attachment-only user text falls back to “User message”; long user text ellipsizes; assistant text is absent or flattened/clamped to three lines. Hover distance scales strips. Hover/leave, focus/blur, arrows/Home/End/Enter/Space, strip click, preview selection, button click, wheel forwarding and cross-rail drag/release are F15–F17. Disabled buttons lose enabled focus/hover styling; W02 records that transition.

## Reproducible fixture recipes

These are instructions for a capture lead, not actions executed in this audit. Use only isolated development state and synthetic content. No production database writes or paid provider turns are needed.

- **A, short-history app fixture:** create two 9–16-turn threads using the dev server's free Replay (dev) provider and short prompts/replies. App CLI `project add`, `thread start`, and `thread send --wait` can seed them; select a short multi-turn replay scenario through its displayed UI name. Open `/<environmentId>/<threadId>`. Close details/sidebars for the 1440px wide scene. Retain actual timeline/lane measurements; do not infer gutter from browser width. Theme/font/chat-width settings are in Appearance.
- **B, empty/fit:** create a fresh draft, then one short turn and two short turns in a fresh thread. Verify `scrollHeight==clientHeight` for the two-turn scene. Loading/cached/draft promotion states come from normal navigation; deliberately invalid list internals require H.
- **D, positioning/restore driver:** record the real viewport while setting `scrollTop=scrollHeight-clientHeight-distance`; log actual clamped distance, button disabled state, current/in-view strips and scroll events. For F11 first leave B at an interior row, A at bottom; switch A -> B -> A via sidebar/command palette with no corrective scrolling. Keep the beginning of restoration and any queued frame in the recording, not only endpoints.
- **E, row and viewport geometry:** send a real Replay turn while following, repeat detached >40px away, expand/collapse work or a long user message, resize window/composer/panel, and optionally load a synthetic media attachment. A tall final user turn produces F05. At least ~80 short turns produces a capped rail. Reduced motion is an OS/browser media variant.
- **Q, footer-only growth:** on seeded A use Replay's displayed Question or Write approval scenario to keep work pending; existing recorded entries remain in place. Release follow at exact bottom with an upward wheel signal without changing scrollTop, as in R01's disclosed synthetic-wheel driver. Then queue a long prompt through the app RPC `thread.send` with `mode:"queue"` (or equivalent app queue action), avoiding the composer send path if it scrolls. Verify the queue grows ListFooter rather than adding timeline strips. Record distance 0 -> >1, no scroll events, unchanged scrollTop and row count, and disabled -> enabled Next. Multiple queued prompts can make growth unambiguous. Queue removal/shrink can supply the reverse. If a runner cannot keep this production fixture detached without scrolling, use H and label it; do not claim a regular growth recording proves this row.
- **G/H, guest harness:** follow [GuestPage.browser.test.tsx](https://git.cafe/pingdotgg/t3code/blob/b78ce3405f725938b6643a2543ae3be33dc3067d/apps/web/src/components/guest/GuestPage.browser.test.tsx): set `/guest?share=<synthetic-share>`, return 204 from the guest session fetch, feed schema-valid `view` then `thread` snapshot events from fake EventSource, and render the actual GuestPage. Use the existing projection fixture builder with 9–16 short turns. Set expiry safely in the future and use an innocuous displayed model label. Exercise no-footer bottom/away, then inject unplaced guest messages and optionally history controls. Record labels that identify mocked transport. No credential, real sharing link, OAuth or Connect is required. This is a harness recording, not end-to-end guest access. Generic H also covers direct TimelineMinimap invalid props and controlled missing-anchor states.

## Fixture matrix

`required` is the minimum gate for this PR; `inventory` documents unchanged alternatives and does not expand that gate. `needs-capture` on an inventory row means no linked capture proves the full named combination, not that the PR must now acquire it. All interaction- or time-dependent rows are marked **recording**, even where an endpoint still is retained separately. One recording may satisfy several rows with explicit timestamps.

| Row | Named fixture / necessary data | Diff impact | Minimum viewport × theme × format | Seed / route | Status at audited head and existing evidence |
|---|---|---|---|---|---|
| F01 | Overflowing short history; several final turns visible, current<last, distance=0; Next disabled | Direct atEnd override | required: 1440×900 × light + dark × before/after stills | A+D, stationary Next hover | **valid-existing** — F01 pairs in evidence-v2; static button branch unchanged |
| F02 | Interior current, distance=120; Next enabled | Negative override control | required coverage inside F03: 1440×900 × light × **recording** | A+D | **valid-existing** — F03 stop/click at 120px |
| F03 | Distances 0/1/2/30/40/120; enabled Next click returns bottom | Threshold and scroll refresh | required: 1440×900 × light × **recording** | A+D; log distances | **valid-existing** — F03-F04 paired videos; 0/1 disabled, >=2 enabled; exact scroll path unchanged |
| F04 | Overflowing thread at top; Previous disabled, Next enabled | Previous unchanged | required coverage inside F03: 1440×900 × light × **recording** | A+D, hover Previous | **valid-existing** — F03-F04 final top stop |
| F05 | Tall final turn, current=last while distance>1; Previous enabled and Next disabled | Existing last-neighbor branch | inventory: 1440×900 × light still | E, expanded long final user turn | **needs-capture** — no tall-final-turn capture; no extra gate |
| F06 | Exactly two user turns fit, no overflow; both directions disabled | Direct override with zero overflow | required: 1440×900 × light still | B; verify equal heights | **valid-existing** — F06 pair |
| F07 | Empty visible placeholder; blank loading/draft placeholder; one user item; footer/history-only list | Unchanged empty/under-two guards | inventory: 1440×900 × light × **recording** for transitions | B; H only for synthetic footer-only internals | **needs-capture** — no full named variants; no extra gate |
| F08 | Compact two strips vs capped ~80-strip rail; mixed row kinds, parent/workflow/history available/loading/error and expanded work/attempt/turn content | Height/visible-range equivalents | inventory: 1440×900 × light × **recording** for changes | B/E; replay fixtures, app Load earlier, side chat; H for unavailable arbitrary projections | **needs-capture** — F06 covers compact subcase, F01 nine strips; mixed/capped/header variants absent; no extra gate |
| F09 | Null/out-of-range current, invalid visible range, missing viewport/state, stale data and restore guard | New false fallback + existing skips | inventory: 1440×900 × light × labelled harness **recording** | H; loading navigation for genuine transient guard | **needs-capture** — intentionally invalid states cannot be seeded by ordinary valid app input; no extra gate |
| F10 | Remembered mid-history settled endpoint, correct strips, Next enabled | Post-restore path | required through F11: 1440×900 × light × **recording** | A+D | **needs-capture** — old F11 endpoint remains historical; new ordering is unproved |
| F11 | A bottom -> B remembered history -> A bottom; no corrective scroll; Next disabled -> enabled -> disabled | Direct committed-restore scheduler change | required NEW: 1440×900 × light × **recording** | A+D; record switches continuously | **needs-capture** — F11 at the older head predates changed effect ordering |
| F12 | Initial/default mount, reload saved row, missing row offset, citation-owned restore, find-open release/reveal, user navigation cancellation | Shared committed-restore completion | inventory: 1440×900 × light × **recording** | A+D; app find/citations, H for removed saved anchor | **needs-capture** — initial settled bottom covered by F01, alternative restore paths absent; no extra gate beyond F11 |
| F13 | Followed streamed row growth -> settled bottom; detached row growth remains away with Next enabled | Existing item/total-size refresh; metrics adds header/footer notifications | required: 1440×900 × light × **recording**; reduced-motion variant inventory | A+E, real Replay turns | **valid-existing** for the stated settled row-growth result — F13 paired videos. Old latency/transient footer samples are historical and do not prove new metrics timing or F18 |
| F14 | Disclosures/media/composer inset or rewrap change row/end geometry; fullscreen suppresses follow | Shared geometry refresh; viewport branch added | inventory: 1440×900 × light × **recording** | E; actual synthetic attachments/apps, H when unavailable | **needs-capture** for full family — R01 separately proves detached height shrink; no extra gate |
| R01 | Detached exact bottom -> viewport height 900→500; distance 0→400 with zero scroll events | Direct ResizeObserver refresh | required: 1440×900→1440×500 × light × **recording** | A+D/E, disclosed wheel-release signal | **valid-existing** — R01 final at later capture head; same observer refresh path, synthetic rather than hardware wheel limitation retained |
| F15 | Preview absent/first/middle/last; fallback/ellipsis user text; absent/clamped markdown assistant preview; hover/focus then dismiss | Unchanged preview and tooltip layout | inventory: 1440×900 × light × **recording** | A/E plus attachment-only text; H for deterministic preview data | **needs-capture** — navigation tooltip is not strip preview evidence; no extra gate |
| F16 | Rail ArrowUp/Down/Home/End/Enter/Space; Previous/Next activation, disabled focus skip | Shared selection; disabled Next changes focus | inventory: 1100×900 × light × **recording** | A, keyboard | **needs-capture** for full key set — W02 already proves focused Next Enter and focus loss at bottom; retain that subcase; no extra gate |
| F17 | Strip click, preview text selection, press origin/cross-rail drag/pass-through until release, wheel forwarding | Shared scroll/selection, handlers unchanged | inventory: 1440×900 × light × **recording** | A, real pointer/wheel driver | **needs-capture** for full interaction set — wheel/Next portions appear in existing videos; no extra gate |
| F18 | Header/footer metrics change while detached at exact bottom; queued footer grows below unchanged rows with no scroll; Next reenables, removal reverses geometry | Direct new onMetricsChange; footer excluded from row total | required NEW: 1440×900 × light × **recording**; footer growth required, header-only/reverse inventory | Q; optional history-header variation via app/H | **needs-capture** — explicitly omitted by PR; browser assertion is not a recording. R01 resize and F13 row growth do not substitute |
| W01 | Persistent g>=48, interactive rail | Changed button in default wide geometry | required inside F01/F03: 1440×900 × light + dark stills; light **recording** | A, Comfortable, actual width measurements | **valid-existing** — F01/F03, g352 in boundary scene |
| W02 | Nonpersistent 26<=g<48; fine-pointer hover/focus reveal, bottom/away, keyboard return | Alternate visibility branch around changed Next | required: 1100×900 × light × **recording** | A; 14px font, Wide, sidebar open; measured g42/hit30 | **valid-existing** — W02 paired videos; 1100px alone is insufficient without these recorded measurements/settings |
| W03 | 12<g<26 gives strip hit area without pointer navigation; g<=12 gives zero hit area | Unchanged hit gating | inventory: measured narrow/panel viewport × light × **recording** | A, Full/Wide and panel resizing | **needs-capture** — no full branch capture; no extra gate |
| W04 | Nonpersistent fine vs coarse pointer; <640px padding; coarse hides rail unless persistent | Unchanged CSS/platform branch | inventory: 390×844 × light × **recording** for pointer/width changes | A with browser device/media emulation | **needs-capture** — native mobile does not prove this web branch; no extra gate |
| C01 | Actual GuestPage: zero inset/header/composer; bottom/away; optional unplaced-message footer and history | Second direct caller of changed component | required NEW: 1440×900 × light × labelled harness **recording** | G/H successful synthetic guest session | **needs-capture** — harness is producible; no guest timeline capture exists |
| C01-real | Genuine guest share creation/redemption and authenticated stream | Production transport prerequisite, not extra rendering branch | no separate minimum if labelled C01 harness is delivered | Enable guest beta + active managed Connect, then normal share/redeem | **cannot-produce** on this VM — Connect unavailable; error-page capture proves no timeline geometry |
| C02 | SideChatPane embedded ChatView; parent context/header, two independent scroll nodes, narrow width | Same changed component; width/restore equivalent | inventory: 1440×900 outer viewport × light × **recording** | App side-chat action with >=2 own turns, then pane navigation | **needs-capture** — W02 covers narrow gutter equivalence, not an actual embedded caller; no extra gate |
| C03 | Electron exact bottom, nine turns, default scale | Same web component, desktop geometry | existing additional coverage: 1440×900 × light still | Isolated Electron client, A | **valid-existing** — D01 pair at later capture head, DPR1, Linux/Xvfb; no claim of desktop away-state coverage |
| C04 | Local/hosted/remote/relay/tunnel, multiple environment identities | No changed transport/provider condition | collapsed into A; no extra capture product | Same synthetic entries in environment-scoped route | **valid-existing** for local-web representative only; remote execution is not claimed |

## Existing evidence to retain

The [full web evidence](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ba8261725713bf19/evidence-v2.md) supplies F01 light/dark and F06 still pairs with differences, and the following paired videos:

- [F03/F04 before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4945c20553b8e183/F03-F04-before.mp4), [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/3c71ed74e9b8631d/F03-F04-after.mp4).
- [F13 before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/875b574527f71a8b/F13-before.mp4), [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/be4d29fa5bbcfb0c/F13-after.mp4), limited to settled row-growth assertions.
- [W02 before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/bf40b4b255f9f2d7/W02-before.mp4), [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/2b0ec550d5146d8f/W02-after.mp4).
- [R01 manifest, measurements and three-build comparison](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f3e739c1983f2aa1/r01.md), including the later-head resize recording.
- [D01 desktop manifest and still pair](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/16866389b217160f/d01.md).

Keep [F11 before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/067c149391778184/F11-before.mp4) as the historical regression baseline. [F11 old after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4d2954fc20fb8760/F11-after.mp4) is historical, not proof of the audited effect ordering.

## Only the missing minimum

1. **F11:** new head recording at 1440×900 light, A bottom -> B history -> A bottom without corrective scrolling; include actual distances, strip state and disabled-state transitions. The existing historical before can remain with its original SHA.
2. **F18:** new head recording at 1440×900 light with queued footer growth below a detached bottom, unchanged scrollTop, no scroll event, and Next disabled -> enabled. For a new causal comparison, use the audited merge-base or the pre-metrics head and label it truthfully. Do not silently substitute row growth or viewport resize.
3. **C01:** new head labelled GuestPage harness recording at 1440×900 light, bottom/away and preferably unplaced-footer growth in the same run. Keep the production Connect limitation explicit. This closes visual caller coverage only.

No repeat of all themes/viewports or paid provider run is needed. Correct the PR's stale final-head prose when the lead updates its evidence. This auditor did not change the PR or rerun tests.

FRICTION:
infra | The VM has no T3 Connect, so a genuine guest create/redeem session cannot be seeded. | Supply an isolated active connector for production-flow proof, or explicitly accept the labelled GuestPage harness for this visual audit.
VERDICT: INSUFFICIENT F11, F18, C01
