Files

507 lines
28 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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. The Phase 7 entry already carries `**Plans**: 6 plans` — LEAVE that count
line as it is; do NOT replace it and do NOT introduce a `TBD` placeholder.
3. The six Phase 7 plan entries and their one-line objectives already exist in
the ROADMAP's plan list — mark each of the six `[x]` (they are done once
this task runs). Do NOT add a seventh entry and do NOT reword the six
objectives.
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>