docs(07): plan phase 07 — hardening + private launch (6 plans, 3 waves)

This commit is contained in:
araharah-executor
2026-10-25 02:31:50 +08:00
parent 0d437db10c
commit 27b340fa6b
7 changed files with 3106 additions and 0 deletions
@@ -0,0 +1,503 @@
---
phase: 07-hardening-private-launch
plan: 06
type: execute
wave: 3
depends_on:
- "07-01"
- "07-02"
- "07-03"
- "07-04"
- "07-05"
files_modified:
- .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md
- .planning/STATE.md
autonomous: false
requirements:
- PX-04
must_haves:
truths:
- "One consolidated walk covers Android, iOS, Telegram Desktop and a plain browser across seven interactions, and every leg carries a recorded PASS/FAIL/NOT RUN verdict — never a synthesized one."
- "The battery result is a RECORDED real measurement from one Android guidance run of at least 30 screen-on minutes — never extrapolated, never synthesized."
- "The launch checklist is signed only when every automated gate is green, the known-limitations doc is shipped, the privacy audit is signed, and the budget record is green."
- "The launch act itself is the user's — the workflow produces the evidence and the checklist, never the distribution."
artifacts:
- path: ".planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md"
provides: "The signed launch gate — the device matrix, the battery record, and the D-09 checklist"
contains: "FINAL VERDICT"
- path: ".planning/STATE.md"
provides: "The milestone completion record (D-09 — the milestone completes when the checklist is signed)"
contains: "milestone"
key_links:
- from: ".planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md"
to: ".planning/phases/07-hardening-private-launch/07-03-PLAN.md"
via: "the checklist's privacy-audit line references the signed record in docs/PRIVACY-AUDIT.md"
pattern: "PRIVACY-AUDIT"
- from: ".planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md"
to: "docs/KNOWN-LIMITATIONS.md"
via: "the checklist's known-limitations line names the shipped doc"
pattern: "KNOWN-LIMITATIONS"
---
<objective>
Close the phase honestly: one consolidated device-matrix walk, one recorded
Android battery run, the D-09 launch checklist — and the milestone's
completion record.
Purpose: D-05 — the QA pass is ONE walk (four clients × seven interactions),
not four separate sessions. D-04 — the battery target is a RECORDED real
measurement, never synthesized. D-09 — the private launch IS the checklist
being signed; the launch act itself is the user's. This plan produces the
gate FILE (the protocol + the record) and then blocks for the human.
Output: `.planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` (new
— the protocol, the empty result tables, and the signature block) and, after
the human signs, the `.planning/STATE.md` milestone completion record.
</objective>
<execution_context>
@$HOME/.config/opencode/get-shit-done/workflows/execute-plan.md
@$HOME/.config/opencode/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/07-hardening-private-launch/07-CONTEXT.md
@.planning/phases/07-hardening-private-launch/07-RESEARCH.md
@.planning/phases/07-hardening-private-launch/07-PATTERNS.md
<interfaces>
The gate-file structure to copy — `.planning/phases/06-turn-by-turn-guidance-live-driving/06-DEVICE-GATE.md`
(its blocking header at lines 3–8, its part tables at lines 32–43, its
executor notes at lines 59–68, and its FINAL VERDICT section at lines 72–82):
```markdown
**Status: BLOCKING — awaiting the human.** Everything automatable is green: …
Per the plan's law: **device results are never faked** — this file records the
protocol; the SUMMARY records the verdict verbatim once the drive runs.
A FAIL holds the phase open.
| # | Step | Verify |
|---|------|--------|
## Executor notes for the run
- **Never fake**: if a step cannot be executed (weather, road, time), mark it NOT RUN —
do not invent an outcome. The phase stays open on any FAIL or NOT RUN.
## FINAL VERDICT
| Part | Verdict |
|------|---------|
```
The battery record fields (from 07-RESEARCH.md §Pitfall 11 and D-04):
| Field | Requirement |
|-------|-------------|
| Device / model | required |
| OS + Telegram client version | required |
| Screen brightness | required |
| Network (Wi-Fi / cellular) | required |
| Screen-on interval | ≥ 30 minutes |
| Battery % at start | required |
| Battery % at end | required |
| Route / drive description | required |
| Elapsed minutes | required |
| Computed %/hr | (end − start) / (elapsed minutes / 60) |
| Caveats | required (background apps, signal loss, other load) |
The seven interactions (D-05) — each leg is tested against every client:
1. boot
2. search → route
3. guidance
4. minimize / resume
5. trip-end
6. theme flip
7. landscape / fullscreen
The D-09 launch checklist (six items):
- known-limitations shipped
- privacy audit signed
- budget record green
- full device matrix walked
- `/help` + `/privacy` accurate
- repo pushed public under GPL-3.0
</interfaces>
<tasks>
<task type="auto">
<name>task 1: write the launch gate file (the protocol, the empty result tables, the checklist, the signature block)</name>
<files>.planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md</files>
<read_first>
- .planning/phases/06-turn-by-turn-guidance-live-driving/06-DEVICE-GATE.md (the WHOLE file is the structural template)
- .planning/phases/03-mini-app-shell-geolocation/03-DEVICE-MATRIX.md (the six-leg table + the FINAL VERDICT table shape)
- .planning/phases/07-hardening-private-launch/07-CONTEXT.md (D-04, D-05, D-09 verbatim)
- .planning/phases/07-hardening-private-launch/07-RESEARCH.md §Pitfalls 11 and 12
</read_first>
<action>
Create `.planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` (NEW —
the whole file is new), copying `06-DEVICE-GATE.md`'s structure exactly. It
MUST contain, in this order:
**1. A blocking status header.** Name what is already green at the time of
writing — the suite counts and the exact commands (`npm run bot:test`,
`npm run web:test`, `npm run routing:test`, `npm run search:test`,
`npm run privacy-audit`, `npm run budget-audit`, `npm run capture -w web`) —
and include the never-fake law VERBATIM in the file's own voice:
"device results are never faked — this file records the protocol; the SUMMARY
records the verdict verbatim once the walk runs. A FAIL holds the phase open."
**2. `## Part A — the consolidated device-matrix walk (D-05)`.** A FOUR-CLIENT
× SEVEN-INTERACTION table. The four clients are: Android (real phone,
Telegram Android), iOS (real phone, Telegram iOS), Telegram Desktop, and a
plain browser. The seven interactions are: boot · search→route · guidance ·
minimize/resume · trip-end · theme flip · landscape/fullscreen. The table
shape is one row per CLIENT with a per-interaction verdict column set:
```markdown
| Client | boot | search→route | guidance | minimize/resume | trip-end | theme flip | landscape/fullscreen | Notes |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Android (real phone, Telegram Android) | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | |
| iOS (real phone, Telegram iOS) | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | |
| Telegram Desktop | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | |
| Plain browser | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | |
```
The verdict vocabulary is `PASS` / `FAIL` / `NOT RUN` — one word per cell,
plus the free-text Notes column. Define the vocabulary right above the table:
"PASS = the interaction completed as designed on this client · FAIL = it did
not (the phase stays open) · NOT RUN = the client or the step was unavailable
(NOT RUN is never PASS)."
Add a `### What to check per interaction` list — one short line per
interaction, stating the observable pass condition:
- boot: the app reaches LIVE (or the DESIGNED denied state on a client with
no geolocation — the denied state IS the pass condition there, a blank
screen is a FAIL).
- search→route: a destination resolves to a KL landmark, the route draws, the
route card shows time + distance.
- guidance: the maneuver banner shows distance + arrow + street; the ETA
advances without whiplash; the haptic fires at the maneuver (where the
client supports it).
- minimize/resume: minimizing the app mid-drive produces a chat turn-card
within ~3–4 minutes; re-opening resumes at the progressed position.
- trip-end: END TRIP → the confirm card → abandon shows the trip-ended card
and the envelope is deleted.
- theme flip: the chrome re-slots light↔dark mid-session, the strip stays
matte-black, and THE MAP IS UNCHANGED (same style, no flash, no camera jump).
- landscape/fullscreen: rotating the device (or the desktop window) keeps the
banner, the maneuver list, the guidance card and the map all usable with no
overlap and no clipping; on Telegram 8.0+ clients the Mini App enters
fullscreen at guidance start, and on older clients it simply stays
portrait/landscape-usable (that IS the pass condition there).
**3. `## Part B — the Android battery record (D-04)`.** A table with the
field list from the interfaces section above, all values left as `⬜` EXCEPT
the rows that name a REQUIREMENT (device, OS, client version, brightness,
network, screen-on interval ≥ 30 min, start %, end %, route, elapsed minutes,
computed %/hr, caveats). Below the table, the honest rule, in the file's
voice: "The <10%/hr target is RECORDED, never synthesized. If the run is
shorter than 30 screen-on minutes, or it is interrupted, mark the row NOT RUN
and keep this gate open. Do not extrapolate a percentage from a shorter run."
**4. `## Part C — the automated half (re-run at gate time)`.** A table of the
exact commands with a `⬜` result column, so the human can re-run them at
gate time and see the counts:
`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` · `npm run privacy-audit` ·
`npm run budget-audit` · `npm run capture -w web` ·
`npm run privacy-audit -- --live` · `npm run budget-audit -- --live`.
Note under the table: "A `--live` probe that reports NOT RUN (exit code 2)
means the credentials or the environment were absent — that is NOT a pass.
The launch checklist stays unsigned until the live probes are green."
**5. `## Part D — the D-09 launch checklist`.** Six checkbox rows, each with
the evidence that satisfies it:
- [ ] Known-limitations shipped — `docs/KNOWN-LIMITATIONS.md` is in the repo
and `/help` points at it (en + ms).
- [ ] Privacy audit signed — `docs/PRIVACY-AUDIT.md` carries the evidence and
a human signature; `npm run privacy-audit` exits 0.
- [ ] Budget record green — `docs/BUDGETS.md` is in the repo; `npm run
budget-audit` exits 0 and the c3 degradation class is stated honestly.
- [ ] Full device matrix walked — Part A has no FAIL and no NOT RUN.
- [ ] `/help` and `/privacy` accurate — the replies match the shipped
behaviour and the limitations pointer line resolves.
- [ ] Repo pushed public under GPL-3.0 — the remote is public, the root
`LICENSE` is GPL-3.0, and `docs/ROAD-GRAPH.md` + the audit commands are
the fork's onboarding path.
**6. `## Executor notes for the run`.** The known-open items: the `/cari`
menu defect (type the command — the doc says so); the cross-metro c3
degradation (a long cross-metro trip may land on the router-pending card);
the R2 / graph upload state (if the graph is absent, `/api/route` answers
honest nulls and long routes degrade); the live-probe credential caveat; and
the never-fake rule.
**7. `## FINAL VERDICT`.** A part-by-part table (`| Part | Verdict |` with
rows A, B, C, D), left EMPTY for the human to fill, followed by a dated
signature block:
```markdown
---
## FINAL VERDICT — ⬜ NOT YET SIGNED
| Part | Verdict |
| --- | --- |
| A. The consolidated device matrix | ⬜ |
| B. The Android battery record | ⬜ |
| C. The automated half | ⬜ |
| D. The launch checklist | ⬜ |
**Signed:** ______________________ **Date:** ____________
```
Do NOT fill any verdict in this task — the file records the PROTOCOL. The
human fills the verdicts.
</action>
<acceptance_criteria>
- `.planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` exists and contains the section headings `## Part A — the consolidated device-matrix walk (D-05)`, `## Part B — the Android battery record (D-04)`, `## Part C — the automated half (re-run at gate time)`, `## Part D — the D-09 launch checklist`, `## Executor notes for the run`, `## FINAL VERDICT`
- `grep -c "device results are never faked" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` returns ≥ 1
- `grep -c "NOT RUN" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` returns ≥ 3 (the verdict vocabulary, the battery rule, and the executor note)
- `grep -c "⬜" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` returns ≥ 20 (the empty result cells — nothing is pre-filled)
- `grep -c "Known-limitations shipped" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` returns 1 and `grep -c "Repo pushed public under GPL-3.0" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` returns 1 (the six D-09 checklist items)
- `grep -c "SIGNED" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` returns ≥ 1 and the file contains NO filled verdict (no `APPROVED` string)
</acceptance_criteria>
<verify>
<automated>export PATH="$HOME/.nvm/versions/node/v24.18.0/bin:$PATH"; cd /home/C-Fu/araharah && test -f .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md && grep -c "⬜" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md && ! grep -q "APPROVED" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md && echo "gate file is an empty protocol"</automated>
</verify>
<done>
The launch gate file exists with the full protocol — the 4×7 device
matrix, the battery record fields, the automated-half commands, the six
D-09 checklist items, and an unsigned FINAL VERDICT block.
</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<name>task 2: THE CONSOLIDATED WALK + THE BATTERY RUN (the blocking human gate)</name>
<files>.planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md</files>
<read_first>
- .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md (the protocol written in task 1 — the verdict vocabulary, the per-interaction pass conditions, the battery field list, and the six checklist items)
- .planning/phases/06-turn-by-turn-guidance-live-driving/06-DEVICE-GATE.md (the never-fake protocol precedent)
</read_first>
<action>
The human walks the four clients, runs the battery measurement, and fills
the verdict tables IN PLACE in `07-LAUNCH-GATE.md`. No automated step
replaces any of it.
</action>
<acceptance_criteria>
- `grep -c "⬜" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` returns 0 (every verdict cell is filled — no cell is left blank)
- `grep -c "NOT YET SIGNED" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` returns 0 (the FINAL VERDICT header was updated to the signed verdict)
- `grep -c "Signed:" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` returns 1 and the signature line is NOT blank (a name is written)
- `grep -c "Date:" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` returns ≥ 1 and the date line is NOT blank
- `grep -c "FAIL" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` returns 0 in the FINAL VERDICT table OR the gate is reported as NOT SIGNED (a FAIL keeps the phase open — the file must not claim a signed state with a failing part)
- the Part B table contains a start %, an end %, and an elapsed-minutes value (the battery record is measured, not blank)
</acceptance_criteria>
<what-built>
Everything automatable in Phase 7: the fullscreen capability layer and its
8.0 fallback (07-01), the landscape cockpit geometry and the failure-state
matrix (07-02), the consolidated privacy audit and its signed record
(07-03), the consolidated budget record and the static-asset cache policy
(07-04), and the paid debts plus the known-limitations document (07-05).
The launch gate file (07-06 task 1) holds the empty protocol: a 4×7
device matrix, the battery record fields, the automated-half command list,
and the six D-09 checklist items.
What is left is exactly what no tool can produce: the physical walk and
the measured battery number.
</what-built>
<how-to-verify>
**Part 0 — the automated half (re-run at gate time, ~2 minutes).** From
the repo root:
```
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
npm run privacy-audit
npm run budget-audit
npm run capture -w web
npm run privacy-audit -- --live
npm run budget-audit -- --live
```
Every command must exit 0. A `--live` probe that prints `NOT RUN` and
exits 2 is NOT a pass — the credentials must be present.
**Part A — the ONE consolidated walk (D-05).** Open the deployed Mini App
from the bot on each of the four clients, and work through all seven
interactions on EACH client: boot · search→route · guidance ·
minimize/resume · trip-end · theme flip · landscape/fullscreen. Fill one
verdict word per cell in Part A of
`.planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` — PASS,
FAIL, or NOT RUN — plus a note in the Notes column. The pass conditions
are listed in the file under "What to check per interaction"; read them
before starting. A NOT RUN cell (a device that was not available) keeps
the checklist unsigned — it is not a PASS.
**Part B — the battery run (D-04).** On the Android phone, start a
guidance run and keep the screen on for AT LEAST 30 MINUTES of real
driving (a real route, not a stationary app). Read the battery
percentage immediately before starting and immediately after ending, and
fill every field of Part B: device, OS, Telegram client version,
brightness, network, the screen-on interval, start %, end %, the route,
the elapsed minutes, the computed %/hr, and the caveats. If the run was
shorter than 30 minutes or was interrupted, mark it NOT RUN and leave the
gate open — do not extrapolate.
**Part C — the automated half table.** Fill the result column for each
command.
**Part D — the checklist.** Tick each of the six items only when its
evidence actually exists: the limitations doc is in the repo and `/help`
points at it; `docs/PRIVACY-AUDIT.md` is signed; `docs/BUDGETS.md` is
green and states the c3 class; Part A has no FAIL and no NOT RUN; `/help`
and `/privacy` read accurately against the shipped behaviour; and the
remote repository is public with the root `LICENSE` at GPL-3.0.
**The verdict.** Fill the FINAL VERDICT table (Parts A–D) and the
signature line with your name and the date.
**The launch itself is yours.** Once the checklist is signed, the
milestone completes — the workflow does NOT distribute the bot link. Give
it to your first KL drivers yourself.
</how-to-verify>
<resume-signal>
Type "signed" with the FINAL VERDICT filled (and paste the Part A matrix
and the Part B battery numbers), or describe what failed / which legs were
NOT RUN. On "signed", the executor writes the milestone completion record
into `.planning/STATE.md`. On a FAIL or a NOT RUN, the phase stays open —
open a `/gsd-debug` for the failing symptom and record the NOT RUN legs
honestly.
</resume-signal>
<verify>
<automated>export PATH="$HOME/.nvm/versions/node/v24.18.0/bin:$PATH"; cd /home/C-Fu/araharah && grep -c "SIGNED" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md && ! grep -q "⬜ NOT YET SIGNED" .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md && echo "the gate file is signed (the NOT YET SIGNED marker is gone)"</automated>
</verify>
<done>
Every Part A cell carries a PASS/FAIL/NOT RUN verdict with a note; Part B
carries a real ≥30-minute Android battery measurement (or an explicit NOT
RUN); Part C's command table is filled; Part D's six checklist items are
each backed by their named evidence; and the FINAL VERDICT table is
signed with a name and a date.
</done>
</task>
<task type="auto">
<name>task 3: record the milestone completion in STATE.md (after the checklist is signed)</name>
<files>.planning/STATE.md</files>
<read_first>
- .planning/STATE.md (the whole file — the frontmatter fields, the "Current Position" block, the "Accumulated Context" sections, and the "Progress" table)
- .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md (the signed FINAL VERDICT — the source of this record)
- .planning/ROADMAP.md (the Phase 7 entry — update its "Plans" count and its plan list)
</read_first>
<action>
ONLY run this task after the checkpoint returned "signed" and the gate file's
FINAL VERDICT table is filled.
In `.planning/STATE.md`:
1. Update the frontmatter `status:` to `complete` and `stopped_at:` to a
sentence naming the signed launch gate (e.g.
`Phase 7 complete — the launch gate is signed (private beta checklist)`).
Update `last_updated:` and `last_activity:` to today's date.
2. Update the `## Current Position` block: `Phase: 7` → `Phase: 7 (complete)`,
`Plan: Not started` → `Plan: Complete`, `Status: Ready to plan` →
`Status: Launch gate signed`.
3. Set the `Progress:` bar to `[░░░░░░░░░░] 100%`.
4. In `## Accumulated Context` → `### Decisions`, ADD a bullet recording the
Phase-7 decisions that bind future work:
- The private launch is a checklist-signed private beta; the launch act is
the maintainer's.
- v1 carries ZERO telemetry — the audit proves an absence; opt-in telemetry
is a post-validation milestone.
- The cross-metro CPU class (c3) is the standing degradation: cross-metro
routes land on the router-pending card; the ALT landmark preprocessing is
the committed next-milestone lever.
5. In `### Blockers/Concerns`, move the resolved entries into a short
"RESOLVED 2026-10-25" note and REMOVE the stale open ones — in particular
the `/cari` menu entry stays listed as a KNOWN Telegram-side defect (with
the workaround), and the Phase-4 "legs UNVERIFIED" entry is replaced by
the Phase-7 walk's recorded verdicts.
6. In `### Deferred Items`, ADD the rows that Phase 7 committed to the v1.x
milestone: ALT landmark preprocessing (c2), the WASM-router track, engine B
(the fully client-side webview router), and opt-in telemetry — each with
"Deferred to v1.x milestone" and "Deferred At: Phase 7 (2026-10-25)".
7. Update `## Session Continuity` — `Last session:` and `Stopped at:` and
`Resume file:` (point at the gate file, since it holds the signed record).
In `.planning/ROADMAP.md`:
1. Mark the Phase 7 entry `- [ ]` → `- [x]` and add `(completed 2026-10-25)`.
2. Replace `**Plans:** TBD` under Phase 7 with `**Plans:** 6 plans`.
3. Fill the Phase 7 plan list with the six plan files and their one-line
objectives, marking them `[x]`.
4. Update the `## Progress` table's Phase 7 row to `6/6 | Complete | 2026-10-25`.
5. Leave every other phase's rows untouched.
Do NOT rewrite the roadmap's success criteria, the goal, or any earlier
phase's text.
</action>
<acceptance_criteria>
- `.planning/STATE.md` frontmatter contains `status: complete`
- `.planning/STATE.md` contains the literal `ZERO telemetry` in the Decisions list
- `.planning/STATE.md` contains the literal `ALT landmark preprocessing` in the Deferred Items table
- `.planning/ROADMAP.md` contains `**Plans:** 6 plans` under Phase 7 and the phase line contains `- [x] **Phase 7:`
- `.planning/ROADMAP.md`'s Phase 7 progress row contains `6/6`
</acceptance_criteria>
<verify>
<automated>export PATH="$HOME/.nvm/versions/node/v24.18.0/bin:$PATH"; cd /home/C-Fu/araharah && grep -c "status: complete" .planning/STATE.md && grep -c "\*\*Plans:\*\* 6 plans" .planning/ROADMAP.md && grep -c "6/6" .planning/ROADMAP.md</automated>
</verify>
<done>
STATE.md records the completed milestone with the binding decisions and the
v1.x deferrals, and ROADMAP.md shows Phase 7 complete with its six plans.
</done>
</task>
</tasks>
<threat_model>
## Trust Boundaries
| Boundary | Description |
|----------|-------------|
| The human report → the milestone record | The launch gate's verdicts are human-supplied observations; they are the only evidence source for the physical properties. |
| The signed checklist → the public launch | Signing asserts the artifact set is honest and complete; a false signature is the worst failure mode in the phase. |
## STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-07-27 | Repudiation | `07-LAUNCH-GATE.md` — a synthesized device verdict or battery number | mitigate | Every cell starts as `⬜`; the vocabulary is PASS/FAIL/NOT RUN with NOT RUN explicitly never counting as PASS; the never-fake law is stated verbatim in the file; the battery rule forbids extrapolating a shorter run; the task's own acceptance criteria assert the file contains NO pre-filled verdict (`APPROVED` absent). A synthesized result is structurally impossible to write by accident. |
| T-07-28 | Tampering | the checklist — signing before the evidence exists | mitigate | The six D-09 items each name their own evidence (the shipped doc, the signed audit record, the budget record, a matrix with no FAIL/NOT RUN, the accurate `/help` and `/privacy` replies, the public GPL-3.0 remote). The `--live` probes reporting `NOT RUN` (exit 2) explicitly keep the checklist unsigned. |
| T-07-29 | Information Disclosure | `07-LAUNCH-GATE.md` — a device/OS/battery record leaking into a public repo | accept | The gate file records a device model, an OS version, a battery percentage and a route description — no identity, no account, no coordinate, no credential. The repo is published public under GPL-3.0 by design (D-09), and this data class is intentionally disclosed for the battery method's reproducibility. |
| T-07-30 | Elevation of Privilege | the milestone completion — the workflow acting as the launch act | mitigate | Task 3 runs only after the checkpoint returns "signed"; the gate file states that the launch act itself is the maintainer's — the workflow produces the evidence and the checklist, never the distribution. STATE.md records the SIGNED checklist, not a distribution. |
</threat_model>
<verification>
Run after all tasks:
```bash
export PATH="$HOME/.nvm/versions/node/v24.18.0/bin:$PATH"
cd /home/C-Fu/araharah
npm run bot:test && npm run web:test && npm run routing:test && npm run search:test
npm run privacy-audit && npm run budget-audit
```
All must exit 0. The gate file's FINAL VERDICT must be filled and signed, and
`.planning/STATE.md` must read `status: complete`.
</verification>
<success_criteria>
- `07-LAUNCH-GATE.md` exists as a complete, unsigned protocol: a 4×7 device matrix, the battery record fields, the automated-half command list, the six D-09 checklist items, the executor notes, and an empty FINAL VERDICT.
- The blocking checkpoint was walked by the human; every matrix cell carries a PASS/FAIL/NOT RUN verdict and the battery run is a recorded ≥30-minute real measurement.
- The six checklist items are each backed by their named evidence, and the FINAL VERDICT is signed with a name and a date.
- `STATE.md` records the milestone completion with the binding decisions and the v1.x deferrals; `ROADMAP.md` shows Phase 7 complete with six plans.
</success_criteria>
<output>
After completion, create `.planning/phases/07-hardening-private-launch/07-06-SUMMARY.md`
</output>