docs(07): revise phase 07 plans — wire the safe-area watch, fold the corpora into budget-audit, add the subrequests row, resolve the research open questions

Checker-issue round 1 on the Phase 7 plan set:

BLOCKER (07-01) — watchSafeAreaChanges and watchFullscreenEvents were created
and unit-tested but never called in production: main.ts:74 was the only
safe-area site and was not in files_modified, and the fullscreen events were
never registered. Insets never re-resolved at runtime on a real device while
every gate stayed green.

  - web/src/main.ts joins 07-01's files_modified; task 4 step 8 wires
    watchSafeAreaChanges(getWebApp()) directly after the boot site's
    applySafeArea(resolveSafeInsets(getWebApp())) line.
  - task 4 step 6 registers watchFullscreenEvents once at the guidance-start
    edge in route.ts, with a deliberately no-op callback (events are
    observability, never correctness).
  - New grep acceptance criteria pin BOTH production call sites; two new
    must_haves key_links name them; T-07-06b now names the boot-site call.

WARNING (07-04 / VALIDATION.md) — the golden corpora were attributed to 07-04
t3, which never ran them. Folded into the budget audit: runGoldenCorpusGate()
re-runs `npm run routing:corpus` and `npm run search:corpus` as child
processes (the same shape runCpuLadderGate already uses), so the ONE
budget-audit command enforces SC4.a/SC4.b. VALIDATION.md rows now name 07-04
t2 and the budget-audit command.

WARNING (07-02 t3) — the landscape-leg snippet omitted the required setup.
The action now says to copy the existing corridor guidance leg VERBATIM
(setup stubGuidanceRoute(page, corridorModel) + guideQuery carrying dest +
fixpair + waitMode/expectGuide) and change ONLY the name, the scheme, and the
viewport; two grep criteria pin the setup and the query.

WARNING (07-04) — D-06/SC4 name subrequests but nothing measured beside the
50/request ceiling. Added runSubrequestClassGate(): a per-request-class
inventory derived from the Worker's route table (engine-A /api/route = 0
external subrequests; the cron tick's Telegram send is the only recurring
class; KV ops tracked separately against their own ceiling). Unmeasurable
counts read "not measured", never 0. docs/BUDGETS.md gains a
"## Subrequests per request class" section and the record states that the
inventory is source-derived, not a live Workers Logs metric.

WARNING (07-RESEARCH.md) — "## Open Questions" is now
"## Open Questions (RESOLVED)" and each of the five items carries its adopted
disposition; Q2/Q3 resolve to "answered by measurement at the launch gate per
D-04/D-06".

INFO (07-VALIDATION.md) — nyquist_compliant flipped to true and the sign-off
is approved 2026-10-25 after the map-row correction.

Waves, dependencies, autonomous flags, and the other three plans are unchanged.
This commit is contained in:
araharah-executor
2026-10-25 02:44:30 +08:00
parent 27b340fa6b
commit a7d8dbf345
6 changed files with 1048 additions and 78 deletions
@@ -370,29 +370,56 @@ Extend `web/scripts/capture.mjs`:
2. Add ONE new landscape leg after the existing guidance legs, using the
`?drive=corridor-follow` replay knob (the committed fixture the 06-08
guidance legs already use) and the guidance wait mode:
guidance legs already use) and the guidance wait mode.
```javascript
/* ————— 07-02 — the landscape leg (PX-04.e) —————
The driving posture: the phone rotated. The cockpit geometry adapts via
the @media (orientation: landscape) block (07-02 task 1); the map stays
Rams-constant. A 844x390 viewport IS the landscape orientation the media
query matches (orientation: landscape + max-height: 560px). */
await captureLeg({
name: 'shell-guidance-landscape.png',
query: 'mock=android&scheme=light&drive=corridor-follow',
colorScheme: 'light',
grantGeo: true,
waitMode: 'guide',
expectGuide: 'on_route',
viewport: { width: 844, height: 390 },
});
```
**COPY THE EXISTING CORRIDOR GUIDANCE LEG VERBATIM.** The new leg is the
existing corridor guidance leg (the one that uses `corridorModel` +
`guideQuery` — e.g. `shell-guidance-active.png`) with ONLY THREE things
changed: the `name`, the `colorScheme`, and the `viewport`. Keep
EVERYTHING else byte-identical — in particular:
Match the exact `expectGuide` value the existing guidance legs use for the
corridor drive — READ the existing guidance legs in this file and copy
their `expectGuide`/`waitMode` pair verbatim rather than guessing. If the
existing corridor leg uses `waitMode: 'settle400'` instead, use that.
- the `setup:` — `setup: (page) => stubGuidanceRoute(page, corridorModel)` —
MUST be copied verbatim. WITHOUT this setup the `/api/route` stub is
never installed, the route never resolves, and the leg TIMES OUT at the
guide-state race with an `ARAHARAH-GUIDE state=… race timed out` error.
- the `query:` — `guideQuery` MUST be copied verbatim. `guideQuery` is
`mock=android&dest=${guidePair.destinationId}&fixpair=${guidePair.pairId}&drive=corridor-follow`
— it carries BOTH the `dest` (the destination id the route resolves to)
AND the `fixpair` (the fixture pair id the replay stream keys on).
Dropping `dest` gives the leg no destination; dropping `fixpair` gives
it no replay fixes. Both are required.
- the `waitMode:` / `expectGuide:` pair — copy the existing corridor leg's
pair verbatim (`waitMode: 'guide'`, `expectGuide: 'on_route'` — READ the
file and confirm; if the existing leg uses `waitMode: 'settle400'`
instead, use that).
So the leg is:
```javascript
/* ————— 07-02 — the landscape leg (PX-04.e) —————
The driving posture: the phone rotated. The cockpit geometry adapts via
the @media (orientation: landscape) block (07-02 task 1); the map stays
Rams-constant. A 844x390 viewport IS the landscape orientation the media
query matches (orientation: landscape + max-height: 560px).
The setup + query + waitMode/expectGuide are copied VERBATIM from the
existing corridor guidance leg — only the name, the scheme, and the
viewport differ. */
await captureLeg({
name: 'shell-guidance-landscape.png',
setup: (page) => stubGuidanceRoute(page, corridorModel),
query: guideQuery,
colorScheme: 'light',
grantGeo: true,
waitMode: 'guide',
expectGuide: 'on_route',
viewport: { width: 844, height: 390 },
});
```
The `expectText` array and the `interact:` block are OPTIONAL — copy them
from the source leg if you want the same DOM assertions, but the leg MUST
at minimum carry the `setup`, the `query` (with `dest` + `fixpair`), and
the `waitMode`/`expectGuide` pair.
3. Add ONE failure-state leg that photographs the designed pending card (the
empty/error route class) so the surface is on film, not only in a Node
@@ -433,6 +460,8 @@ Extend `web/scripts/capture.mjs`:
- `grep -c "shell-guidance-landscape.png" web/scripts/capture.mjs` returns ≥ 1
- `grep -c "shell-route-pending-landscape.png" web/scripts/capture.mjs` returns ≥ 1
- `grep -c "width: 844, height: 390" web/scripts/capture.mjs` returns ≥ 2 (both new legs)
- `grep -c "stubGuidanceRoute(page, corridorModel)" web/scripts/capture.mjs` returns ≥ 6 (the five existing corridor legs + the new landscape leg — the landscape leg MUST carry the route stub setup)
- `grep -c "query: guideQuery" web/scripts/capture.mjs` returns ≥ 5 (the four existing corridor legs + the new landscape leg — the landscape leg MUST carry the `dest` + `fixpair` query)
- `npm run capture -w web` exits 0 and the report lists BOTH new landscape shots as non-blank
</acceptance_criteria>
<verify>