Files
arah2/.planning/phases/07-hardening-private-launch/07-VALIDATION.md
T
araharah-executor a7d8dbf345 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.
2026-10-25 02:44:30 +08:00

8.7 KiB
Raw Blame History

phase, slug, status, nyquist_compliant, wave_0_complete, created
phase slug status nyquist_compliant wave_0_complete created
7 hardening-private-launch draft true false 2026-10-25

Phase 7 — Validation Strategy

Per-phase validation contract for feedback sampling during execution. Derived from 07-RESEARCH.md ## Validation Architecture.


Test Infrastructure

Property Value
Framework Repo-local Node test harnesses (node:test-style): bot/web/routing/search test/runner.mjs; Playwright for browser captures in web
Config file None global — each workspace has test/runner.mjs; web vite.config.ts
Quick run command npm run web:test && npm run bot:test
Full suite command npm run bot:test && npm run web:test && npm run routing:test && npm run search:test && npm run search:corpus && npm run routing:corpus && node routing/scripts/measure-route-cpu.mjs
Phase commands npm run privacy-audit && npm run budget-audit (new in this phase)
Estimated runtime ~60–90 seconds (full suite); audits < 15 s

Sampling Rate

  • After every task commit: Run the touched workspace's quick command (npm test -w web / npm test -w bot); run npm run privacy-audit when touching storage/log/network code
  • After every plan wave: Run the full suite command plus npm run privacy-audit && npm run budget-audit
  • Before /gsd-verify-work: Full suite must be green; both audits green; live probes green
  • Max feedback latency: 90 seconds

Per-task Verification Map

(Task IDs assigned at planning — 2026-10-25. The task ID column names the PLAN TASK that delivers the row; the Plan column names the plan file (07-01 … 07-06).)

task ID Plan Wave Requirement Threat Ref Secure Behavior Test Type Automated Command File Exists Status
07-01 t3 07-01-PLAN.md 1 PX-04.a T-07-06 Bot API <8.0 or absent method: guidance starts without fullscreen and remains usable unit npm test -w web ❌ W0 (web/test/fullscreen.test.mjs) ⬜ pending
07-01 t3 07-01-PLAN.md 1 PX-04.b T-07-06 Bot API 8.0: requestFullscreen() called once at guidance start; failure is non-error unit npm test -w web ❌ W0 ⬜ pending
07-01 t3 07-01-PLAN.md 1 PX-04.c T-07-06 fullscreenChanged / fullscreenFailed update state without throwing unit npm test -w web ❌ W0 ⬜ pending
07-01 t3 07-01-PLAN.md 1 PX-04.d T-07-06 Safe-area inset changes after fullscreen/rotation re-applied unit npm test -w web ❌ W0 ⬜ pending
07-02 t3 07-02-PLAN.md 1 PX-04.e — Landscape viewport keeps banner/list/card/map usable, no overlap/clipping browser capture npm run capture -w web Existing harness; ❌ new landscape legs ⬜ pending
07-06 t2 07-06-PLAN.md 3 PX-04.f — Fullscreen + landscape on Android/iOS/Desktop/browser manual device 07-LAUNCH-GATE.md device matrix ❌ W0 gate file ⬜ pending
07-06 t2 07-06-PLAN.md 3 PX-04.g — One Android guidance run ≥30 min records battery, drains <10%/hr manual measurement 07-LAUNCH-GATE.md battery record ❌ W0 gate file ⬜ pending
07-02 t2 07-02-PLAN.md 1 SC2.b T-07-05 Route source error/timeout renders designed pending/no-route state unit/integration npm test -w web ❌ W0 (web/test/failure-state-matrix.test.mjs) ⬜ pending
07-02 t2 07-02-PLAN.md 1 SC2.e T-07-06 Older Telegram client without 8.0 methods behaves sanely unit + manual npm test -w web; gate file ❌ W0 ⬜ pending
07-03 t1 07-03-PLAN.md 1 SC3.a T-07-02 No banned persistence API in any production src tree source gate npm run privacy-audit ❌ W0 (scripts/privacy-audit.mjs) ⬜ pending
07-03 t1 07-03-PLAN.md 1 SC3.b T-07-01 Every Worker KV write carries TTL; cron has zero writes source + runtime npm run privacy-audit ❌ W0 ⬜ pending
07-03 t2 07-03-PLAN.md 1 SC3.c T-07-01 Live KV keys TTL-expiring, only expected families exist live probe npm run privacy-audit -- --live ❌ W0 ⬜ pending
07-03 t1 07-03-PLAN.md 1 SC3.d T-07-03 Logs category-only; no coordinates/chat ids/payloads source + bundle npm run privacy-audit ❌ W0 ⬜ pending
07-03 t2 07-03-PLAN.md 1 SC3.e T-07-04 No analytics/beacon; only approved fetch hosts bundle gate npm run privacy-audit ❌ W0 ⬜ pending
07-04 t2 07-04-PLAN.md 2 SC4.a — Golden route corpus green (re-run by the budget audit's golden-corpus gate) CLI + suite npm run budget-audit (runs routing:corpus); npm run routing:corpus && npm test -w routing ✅ existing ⬜ pending
07-04 t2 07-04-PLAN.md 2 SC4.b — Search golden corpus green (re-run by the budget audit's golden-corpus gate) CLI + suite npm run budget-audit (runs search:corpus); npm run search:corpus && npm test -w search ✅ existing ⬜ pending
07-04 t2 07-04-PLAN.md 2 SC4.c — A* CPU p95 ≤8 ms local; live Worker CPU ≤10 ms measurement node routing/scripts/measure-route-cpu.mjs; live probe ✅ local; ❌ live probe ⬜ pending
07-04 t2 07-04-PLAN.md 2 SC4.d — Bundle/Worker sizes within recorded budgets measurement npm run budget-audit ❌ W0 (scripts/budget-audit.mjs) ⬜ pending
07-04 t2 07-04-PLAN.md 2 SC4.e T-07-18 KV writes by request class recorded; cron=0 source + runtime npm run budget-audit ❌ W0 ⬜ pending
07-04 t2 07-04-PLAN.md 2 SC4.i T-07-23b Subrequests per request class recorded; /api/route = 0 external; the cron tick's Telegram send is the only recurring class; unmeasurable rows read not measured source + record npm run budget-audit ❌ W0 ⬜ pending
07-04 t1 07-04-PLAN.md 2 SC4.f T-07-20 Static assets have intended cache headers live header probe npm run budget-audit -- --live ❌ W0 ⬜ pending
07-05 t2 07-05-PLAN.md 1 SC4.g — Known-limitations doc shipped, linked from /help en/ms unit/doc gate npm test -w bot ❌ W0 ⬜ pending
07-05 t1 07-05-PLAN.md 1 SC4.h T-07-08 INFO debts fixed; exact-900s boundary pinned unit npm test -w bot ❌ W0 (bot/test/initdata.test.mjs 900s vector) ⬜ pending

Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky


Wave 0 Requirements

(Assigned to plans at planning — 2026-10-25. Each item names the plan task that creates it.)

  • web/test/fullscreen.test.mjs — covers PX-04.a–d and old-client fallback → 07-01 t3 (FS1–FS9)
  • web/test/failure-state-matrix.test.mjs — covers SC2 named vectors and DOM state tokens → 07-02 t2 (FM1–FM7)
  • scripts/privacy-audit.mjs + scripts/lib/* — consolidated source/bundle/live audit → 07-03 t1–t3
  • scripts/budget-audit.mjs + scripts/lib/* — consolidated budget record (CPU ladder, bundle bytes, KV write classes, subrequest inventory, golden corpora) and live probes → 07-04 t2–t3
  • web/public/_headers — hashed-asset immutable caching + HTML revalidation policy, if verified by audit → 07-04 t1
  • bot/test/initdata.test.mjs exact-900s vector — D-07 IN-03 → 07-05 t1 (T4b)
  • docs/KNOWN-LIMITATIONS.md — D-08 → 07-05 t2
  • .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md — device matrix, battery method/result, checklist signature → 07-06 t1 (protocol) + 07-06 t2 (the human walk)
  • Framework install: none — use the existing custom runners

Manual-Only Verifications

Behavior Requirement Why Manual Test Instructions
Fullscreen + landscape usable on Android/iOS/Desktop real clients PX-04 (SC1) No simulated hardware results — honesty protocol One consolidated walk in 07-LAUNCH-GATE.md: Android + iOS + Desktop + browser × (boot, search→route, guidance, minimize/resume, trip-end, theme flip, landscape/fullscreen); NOT-RUN legs recorded honestly
Battery drain <10%/hr during guidance PX-04 (SC1) Real measurement, never synthesized (D-04) One Android guidance run ≥30 min screen-on; battery % read at start/end; method + caveats written into the gate file

Validation Sign-Off

  • All tasks have <automated> verify or Wave 0 dependencies
  • Sampling continuity: no 3 consecutive tasks without automated verify
  • Wave 0 covers all MISSING references
  • No watch-mode flags
  • Feedback latency < 90 s
  • nyquist_compliant: true set in frontmatter

Approval: approved 2026-10-25