chore(planning): phase 8 plans 08-03..05 (ALT potentials, build stage, campaign) + validation re-map; stale 08-02 bullet fixed
This commit is contained in:
@@ -0,0 +1,268 @@
|
||||
---
|
||||
phase: 08-alt-landmark-preprocessing-routing-backend-v2
|
||||
plan: 05
|
||||
type: execute
|
||||
wave: 5
|
||||
depends_on: ["08-04"]
|
||||
files_modified:
|
||||
- routing/scripts/measure-optimality-gate.mjs
|
||||
- scripts/lib/budget-gates.mjs
|
||||
- scripts/test/budget-audit.test.mjs
|
||||
- docs/BUDGETS.md
|
||||
- docs/KNOWN-LIMITATIONS.md
|
||||
- docs/ROAD-GRAPH.md
|
||||
autonomous: true
|
||||
requirements: [SC3, SC4]
|
||||
must_haves:
|
||||
truths:
|
||||
- "The D-03 optimality gate is a committed, re-runnable script that reads the FROZEN pre-ALT record (08-01), re-routes the SAME coordinate-pinned pairs on the current ARG2 binary, and gates on seconds-equality (± OPTIMALITY_EPSILON_PCT = 0.1) + verdict-class preservation — never on node paths (equal-cost ties are documented behavior, D-03)"
|
||||
- "The gate's epsilon constant is asserted EQUAL to the record's epsilon block — a record edit alone cannot fake a pass (constant-mirror law from 08-01)"
|
||||
- "The ALT verdict is MEASURED, never hoped: the 25-route CI gate AND the D-04 extended 100-pair verdict both print their p95 + GATE lines; the c3 retirement (D-05) happens ONLY on passing numbers, quoted verbatim into every record"
|
||||
- "The remediation ladder is pre-committed: FAIL → rebuild at --landmarks 32 → re-measure; at L=32 still FAIL → STOP and escalate honestly (retirement never fires on failing numbers); astar's stop rule is untouchable (Pitfall 3)"
|
||||
- "Every record that documented the accepted c3 degradation tells the post-ALT truth: budget-gates.mjs' route-cpu verdict law, docs/BUDGETS.md's CPU row + c3 section, docs/KNOWN-LIMITATIONS.md's c3 section + ALT pointer row, docs/ROAD-GRAPH.md's ladder table + ARG2 layout — no 'next-milestone item' wording survives (Pitfall 6, docs divorce)"
|
||||
artifacts:
|
||||
- path: "routing/scripts/measure-optimality-gate.mjs"
|
||||
provides: "the D-03 gate — exported core + CLI guard (route-corpus pattern); D03A seconds-equality + D03B verdict-class checks with per-pair violations"
|
||||
- path: "scripts/lib/budget-gates.mjs"
|
||||
provides: "the route-cpu verdict law re-anchored: ≤8 ms PASS; within the shared-host variance guard → loud re-run warning; beyond → uncharted-regression FAIL; all c3-ACCEPTED wording removed"
|
||||
- path: "docs/KNOWN-LIMITATIONS.md"
|
||||
provides: "the c3 section replaced by the retirement record (FIXED shape, /cari precedent); ALT roadmap-pointer row flipped to built"
|
||||
- path: "docs/ROAD-GRAPH.md"
|
||||
provides: "ladder table's (c2) rung with measured numbers; the ARG2 layout + landmarkQuantumS knob documented; storage-name-vs-format-truth note"
|
||||
key_links:
|
||||
- from: "routing/scripts/measure-optimality-gate.mjs"
|
||||
to: "routing/test/fixtures/alt-baseline.json"
|
||||
via: "reads pairs (origin/destination lat-lng + seconds + verdict) + epsilon.pct from the frozen record — never regenerates pairs"
|
||||
pattern: "alt-baseline\\.json"
|
||||
- from: "routing/scripts/measure-optimality-gate.mjs OPTIMALITY_EPSILON_PCT"
|
||||
to: "record.epsilon.pct"
|
||||
via: "mirror assert before any measurement (mismatch → fail)"
|
||||
pattern: "OPTIMALITY_EPSILON_PCT"
|
||||
- from: "docs/KNOWN-LIMITATIONS.md retirement record"
|
||||
to: "the campaign's printed gate lines (task 2's quoted numbers)"
|
||||
via: "D-05 evidence law: the record quotes the measured p95s + date, never rounds up or hopes"
|
||||
pattern: "FIXED 2026-"
|
||||
---
|
||||
|
||||
<objective>
|
||||
The measurement campaign that turns ALT from code into evidence, and the record retirement that evidence buys: the D-03 optimality gate against the frozen pre-ALT baseline, the SC-1/SC-1′ CPU verdicts (25-route CI + 100-pair extended), then every c3-accepting record — budget gate law, BUDGETS, KNOWN-LIMITATIONS, ROAD-GRAPH — re-written to the measured truth.
|
||||
|
||||
Purpose: this plan IS the phase's success criteria. SC-1 (p95 under the ceiling) and SC-2 (optimality unaffected) are measured here; SC-3 (the c3 class retires with evidence) is written here.
|
||||
Output: green optimality gate, green CPU verdicts (or the honest-FAIL escalation), and four documents + one gate law that no longer accept a degradation that no longer exists.
|
||||
</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/STATE.md
|
||||
@.planning/phases/08-alt-landmark-preprocessing-routing-backend-v2/08-CONTEXT.md
|
||||
@.planning/phases/08-alt-landmark-preprocessing-routing-backend-v2/08-RESEARCH.md
|
||||
@.planning/phases/08-alt-landmark-preprocessing-routing-backend-v2/08-PATTERNS.md
|
||||
@.planning/phases/08-alt-landmark-preprocessing-routing-backend-v2/08-VALIDATION.md
|
||||
|
||||
<interfaces>
|
||||
<!-- The instruments and records this plan operates on. Extracted 2026-10-25. -->
|
||||
|
||||
The frozen record (Plan 08-01, `routing/test/fixtures/alt-baseline.json`):
|
||||
```json
|
||||
{ "recordedAt": "<ISO>", "epsilon": { "name": "OPTIMALITY_EPSILON_PCT", "pct": 0.1 },
|
||||
"graph": { "path": "routing/data/kl-roadgraph.v1.bin", "byteLength": 15449343, "nodeCount": N, "edgeCount": E, "argVersion": 1 },
|
||||
"pairRules": { "seed": "0x08a1", "count": 100, "minPairKm": 12 },
|
||||
"pairs": [ { "pairId": "x000", "origin": {"lat": …, "lng": …}, "destination": {"lat": …, "lng": …}, "straightLineKm": …, "seconds": …, "verdict": "reachable|unreachable|unsnappable" } ] }
|
||||
```
|
||||
The record is IMMUTABLE (the recorder refuses overwrite; delete by explicit git revert only). Pairs are pinned by COORDINATES (never node indices — Pitfall 2).
|
||||
|
||||
`routing/scripts/route-corpus.mjs` — the gate-script architecture to copy: exported measurement core + CLI guard (`const invoked = process.argv[1] ? pathToFileURL(...) : ""; if (invoked === import.meta.url) main();`, lines 329–334), the checks-registry + violations pattern (lines 74–92), named-constant bands (lines 41–53), the report/exit law (0 only when every check has zero violations).
|
||||
|
||||
`routing/scripts/measure-route-cpu.mjs` — the two verdict modes: default (zero args, 25-route CI gate, `P95_BUDGET_MS = 8`, prints `p95: <n> ms (…)` + `GATE PASS|FAIL: …`) and `--extended` (Plan 08-01: ~100 cross-metro coordinate-pinned pairs via generateCrossMetroPairs, seed 0x08a1, its own p95 + gate line naming the D-04 extended verdict). The pre-ALT extended run measured an HONEST GATE FAIL (08-01) — post-ALT PASS is the arc this plan closes.
|
||||
|
||||
`scripts/lib/budget-gates.mjs` — the route-cpu verdict law going stale (lines 24–33 doc, 58–61 `ROUTE_CPU_DRIFT_GUARD_MS = 200`, 121–133 verdict strings): current strings call an 8 ms overshoot "the DOCUMENTED, ACCEPTED c3 class" and call ALT "a next-milestone item". `runCpuLadderGate` (lines 78–119) runs measure-route-cpu.mjs with ZERO args and regex-parses `^p95:` / `^GATE (?:FAIL|PASS):` — that CLI contract is pinned (budget-audit 19/19 vectors; scripts/test/budget-audit.test.mjs also source-token-checks the gates). Read that test IN FULL before editing either file — vectors pinning the stale strings co-update in the same task.
|
||||
|
||||
docs state to rewrite: `docs/KNOWN-LIMITATIONS.md` c3 section (lines 29–41, ending "…it is a next-milestone item and is **not** in this release."), the /cari FIXED-record precedent (lines 43–57: ROOT CAUSE / what changed / verified date / what REMAINS), ALT pointer row (line 80: "Next-milestone item, not built"). `docs/ROAD-GRAPH.md` CPU-gate section (lines 77–106: ladder table + the open c1/c2/c3 decision paragraph), key-facts row "pinned CSR v1" (line 130). `docs/BUDGETS.md` route-cpu row (line 58) + "Cross-metro CPU degradation (the c3 class)" section (lines 162–186, including the 200 ms DRIFT GUARD paragraph). `docs/CONFIGURATION.md` — verify-only.
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>task 1: The D-03 optimality gate script + green run against the frozen record</name>
|
||||
<files>routing/scripts/measure-optimality-gate.mjs</files>
|
||||
<read_first>
|
||||
- routing/test/fixtures/alt-baseline.json (the committed record — its exact schema is the gate's input contract)
|
||||
- routing/scripts/route-corpus.mjs lines 41–92 + 283–334 (checks/violations pattern, exported-core + CLI-guard, report/exit law — copy this architecture)
|
||||
- routing/scripts/measure-route-cpu.mjs lines 47–84 (existsSync guard, toArrayBuffer, decodeGraph-null fail, graph print shape)
|
||||
- .planning/phases/08-alt-landmark-preprocessing-routing-backend-v2/08-RESEARCH.md (D-03 verbatim; Pitfall 1 — the record is frozen, drift escalates, never re-records; Pitfall 2 — coordinates are the only pin)
|
||||
- routing/scripts/measure-optimality-baseline.mjs (Plan 08-01 — the immutable-record law and the fail() shape it established)
|
||||
</read_first>
|
||||
<behavior>
|
||||
- epsilon mirror: the script's OPTIMALITY_EPSILON_PCT ≠ record.epsilon.pct → fail() BEFORE any measurement (constant-mirror law; a record edit alone cannot fake equality)
|
||||
- record.graph.argVersion !== 1 → fail() ("the baseline must be the pre-ALT record")
|
||||
- current binary decodes null (still ARG1 / corrupt) → fail() with the rebuild hint — never a partial comparison
|
||||
- D03B verdict class: record reachable + post-ALT null (or the reverse) → violation naming the pairId; record unreachable + post unreachable → pass
|
||||
- D03A seconds: both routed and |post − pre| > pre × 0.1/100 → violation; within → pass (equal seconds, ties allowed — node paths are NEVER compared)
|
||||
- record "unsnappable" pairs (seconds null): post also unsnappable → pass; post now snaps and routes → an INFO row ("re-snapped") with its seconds printed, NOT a violation — counted and WARNING-printed in the summary if > 0 (D-03's letter gates the reachable/unreachable classes)
|
||||
- a tie-path difference (different equal-cost node path, same seconds) CANNOT produce a violation — the gate structurally never looks at paths
|
||||
</behavior>
|
||||
<action>
|
||||
Create `routing/scripts/measure-optimality-gate.mjs` (#!/usr/bin/env node; header contract doc-comment in the route-corpus style: purpose, inputs — the COMMITTED record + the LOCAL rebuilt binary — echoes pair ids + measurements only, exit law).
|
||||
|
||||
Constants (named, doc-commented): `OPTIMALITY_EPSILON_PCT = 0.1` (D-03; the mirror of the record's epsilon block), `RECORD_PATH = resolve(here, "..", "test", "fixtures", "alt-baseline.json")`, `GRAPH_PATH = resolve(here, "..", "data", "kl-roadgraph.v1.bin")` (the same path law as measure-route-cpu).
|
||||
|
||||
Exported core (the route-corpus split — one measurement, two reporters):
|
||||
`export function measureOptimality(graph, record, { snap, astar })` → `{ checks: { D03A, D03B }, rows, reSnapped, pass }` — for each record pair: snap both endpoints (snap-miss on the NEW graph → row class "unsnapped", handled per the unsnappable rules above); route with `astar`; compare per the <behavior> rules; per-pair row `{ pairId, pre, post, deltaPct, verdictPre, verdictPost, class: "pass|violation|re-snapped|unsnapped" }`.
|
||||
|
||||
CLI main(): existsSync guards (absent record → fail "run measure-optimality-baseline first — the record is the D-03 anchor"; absent binary → fail with the build hint); parse + validate the record; the epsilon + argVersion mirror asserts; decodeGraph (null → fail honest); INFO print comparing record.graph counts vs current (nodeCount/edgeCount drift → WARNING line: "extract drift vs the frozen record — the seconds gate still applies"; NOT a violation, and NEVER a reason to re-record — Pitfall 1); run the core; print per-pair rows (` xNNN: pre 5123.4s post 5123.4s (Δ 0.000%) pass` shape), the summary (violations per check, re-snapped count, max |Δ%|, the epsilon used), and exit 1 on any violation else `GATE PASS: D-03 optimality — N/N pairs equal within ±0.1%, verdict classes preserved`.
|
||||
|
||||
Then RUN it — the rebuilt ARG2 binary from 08-04 is on disk: `node routing/scripts/measure-optimality-gate.mjs`. Expected: GATE PASS (ALT is steering-only; A1-class change). A FAIL here is honest and STOPS the plan: report the violating pairs, suspect extract drift first (compare the WARNING counts), and NEVER edit the record — escalation to the user is the only next step (Pitfall 1's immutable law).
|
||||
</action>
|
||||
<verify>
|
||||
<automated>export PATH="$HOME/.nvm/versions/node/v24.18.0/bin:$PATH" && node routing/scripts/measure-optimality-gate.mjs 2>&1 | tail -3 && echo "D03-GATE-GREEN"</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- The script is committed; grep gates: `OPTIMALITY_EPSILON_PCT` ≥ 3 (const + mirror assert + report line); the mirror assert (`record.epsilon`) present; `alt-baseline.json` referenced as RECORD_PATH.
|
||||
- The real run exits 0 printing per-pair rows for the record's full pair count (100), 0 violations, and the `GATE PASS: D-03 optimality …` line; the run's tail is quoted in the summary.
|
||||
- Seconds/verdict-only law: the script contains NO node-path comparison (`grep -c "nodes\[0\]\|nodes.length" routing/scripts/measure-optimality-gate.mjs` = 0).
|
||||
- Honest-refusal structure verified by reading main(): the epsilon + argVersion mirror asserts and the decodeGraph-null branch ALL precede any measurement call (code-order check, quoted in the summary).
|
||||
</acceptance_criteria>
|
||||
<done>D-03 is a machine gate and it is GREEN: post-ALT seconds equal the frozen pre-ALT record within ±0.1% with verdict classes preserved.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>task 2: The CPU verdict campaign (SC-1 + SC-1′) with the pre-committed ladder</name>
|
||||
<files></files>
|
||||
<read_first>
|
||||
- routing/scripts/measure-route-cpu.mjs IN FULL (185 lines — the two modes whose output you will quote; the GATE lines' exact shapes)
|
||||
- .planning/phases/08-alt-landmark-preprocessing-routing-backend-v2/08-RESEARCH.md (D-04; Pitfall 3 — the remediation ladder and the temptation it forecloses; A6 — the verdict is expected but the gate decides)
|
||||
- .planning/phases/08-alt-landmark-preprocessing-routing-backend-v2/08-01-PLAN.md (the pre-ALT extended FAIL — the honest before-number this verdict answers)
|
||||
</read_first>
|
||||
<action>
|
||||
Run BOTH verdict modes over the ARG2 binary and quote every gate line in the summary. These numbers are the phase's SC-1 evidence and the raw material for tasks 3–4's records.
|
||||
|
||||
1. `node routing/scripts/measure-route-cpu.mjs` — the 25-route CI gate. Expected: `GATE PASS: p95 <X> ms <= 8 ms budget`. Quote the p95 line, the worst 3 per-pair lines, and the routed/unreachable split.
|
||||
2. `node routing/scripts/measure-route-cpu.mjs --extended` — the D-04 ALT verdict on ~100 coordinate-pinned cross-metro pairs. Expected: its own p95 + `GATE PASS` line naming the D-04 extended verdict. Quote the p95 line + the slowest pairs.
|
||||
3. THE PRE-COMMITTED LADDER (Pitfall 3) — apply ONLY in this order, only on FAIL:
|
||||
a. `node routing/scripts/build-road-graph.mjs --landmarks 32` (the measured D-02 knob, top of the rule) → re-run BOTH gates.
|
||||
b. At L=32 still FAIL → STOP. Record the honest numbers; do NOT proceed to tasks 3–4 as retirements (they re-scope to an honest escalation record instead — D-05's evidence law forbids retiring on failing numbers); report to the user.
|
||||
NEVER: edit P95_BUDGET_MS, touch routeAstar's stop rule/reductions, drop sample pairs, reseed, or re-run until a lucky box moment and quote only that one (print-the-measurement law gates even a PASS — quote the run you got; a suspiciously loaded box gets a NOTE in the summary, not a re-roll).
|
||||
</action>
|
||||
<verify>
|
||||
<automated>export PATH="$HOME/.nvm/versions/node/v24.18.0/bin:$PATH" && node routing/scripts/measure-route-cpu.mjs 2>&1 | tail -1 && node routing/scripts/measure-route-cpu.mjs --extended 2>&1 | tail -1 && echo "CPU-VERDICTS-RECORDED"</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- The 25-route gate exits 0 with `GATE PASS: p95 … <= 8 ms budget` (or the ladder was exercised to its documented stop).
|
||||
- The extended verdict exits 0 with its `GATE PASS … D-04 extended verdict` line (or the ladder/escalation path is documented).
|
||||
- The summary quotes BOTH p95 lines + n values + date, and (if used) the `--landmarks 32` rebuild command and both re-measurements.
|
||||
- `grep -c "P95_BUDGET_MS = 8" routing/scripts/measure-route-cpu.mjs` = 1 (the budget was never touched).
|
||||
</acceptance_criteria>
|
||||
<done>SC-1/SC-1′ are measured with ALT live; the numbers that retire (or honestly keep) the c3 class exist, printed and quoted.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>task 3: Budget-record truth-out — the route-cpu gate law + docs/BUDGETS.md</name>
|
||||
<files>scripts/lib/budget-gates.mjs, scripts/test/budget-audit.test.mjs, docs/BUDGETS.md</files>
|
||||
<read_first>
|
||||
- scripts/lib/budget-gates.mjs lines 20–135 IN FULL (the runCpuLadderGate law, ROUTE_CPU_DRIFT_GUARD_MS, the verdict strings citing the ACCEPTED c3 class + "next-milestone item")
|
||||
- scripts/test/budget-audit.test.mjs IN FULL (the 19/19 vectors — identify which pin the stale strings/exit laws; they co-update here)
|
||||
- docs/BUDGETS.md lines 50–70 (the route-cpu row) + 155–190 (the c3 section + the DRIFT GUARD paragraph)
|
||||
- .planning/phases/08-alt-landmark-preprocessing-routing-backend-v2/08-CONTEXT.md (D-05 — the record retires WITH evidence)
|
||||
- Task 2's quoted numbers (the new measured p95s)
|
||||
</read_first>
|
||||
<action>
|
||||
Retire the c3 acceptance in the gate law and the budget record — the audit must stop DOCUMENTING a degradation that no longer exists (Pitfall 6):
|
||||
|
||||
1. `scripts/lib/budget-gates.mjs` — re-anchor the route-cpu verdict law (the zero-arg CLI contract with measure-route-cpu.mjs and the `^p95:` / `^GATE` regex parsing stay BYTE-COMPATIBLE — that is pinned by budget-audit):
|
||||
- ≤ P95_BUDGET_MS (8): unchanged PASS path.
|
||||
- 8 < p95 ≤ ROUTE_CPU_DRIFT_GUARD_MS (200 — the constant STAYS, re-documented): exit 0 with a loud WARNING line: over the product budget within the shared-host variance guard (documented ≈2x box variance; the 06-04 band history cites 38–93 ms on IDENTICAL pre-ALT code) — "re-run on a quiet box before treating as regression; the c3 class was RETIRED in Phase 8 (ALT preprocessing)".
|
||||
- p95 > 200: exit 1 "UNCHARTED REGRESSION — the c3 degradation class was retired in Phase 8; a p95 here means the ALT binary/graph or the search regressed".
|
||||
- DELETE the stale strings: "DOCUMENTED, ACCEPTED c3 class", "the ALT landmark lever is a next-milestone item", and the doc-comment lines 24–33's c3-acceptance framing — replaced by the retirement framing with the Phase 8 citation.
|
||||
2. `scripts/test/budget-audit.test.mjs` — co-update ONLY the vectors that pinned the stale strings/exit law (the suite must return to 19/19 green with the NEW law; the count stays 19 unless a vector was solely a stale-string pin, in which case it becomes the new-law equivalent — never silently dropped; the final line still reports `BUDGET-AUDIT SUITE: 19/19 vectors ok`).
|
||||
3. `docs/BUDGETS.md` — the route-cpu row: new measured value (task 2's quoted p95 + date + n; keep the "not statically pinnable / re-run the audit" honesty and the shared-host variance note), the headroom cell flips positive, the "accepted c3 class" disposition cell becomes "RETIRED 2026-10-25 (Phase 8, ALT)". The c3 section becomes the retirement record in the same shape (what changed: ALT preprocessing + ARG2; the measured numbers that retired it; the DECIDED posture now: p95 ≤ 8 is the gate, the variance guard is measurement hygiene, NOT an accepted class; the ladder history stays as history). The DRIFT GUARD paragraph re-anchors to the new law (variance guard ≠ accepted degradation).
|
||||
</action>
|
||||
<verify>
|
||||
<automated>export PATH="$HOME/.nvm/versions/node/v24.18.0/bin:$PATH" && node scripts/test/budget-audit.test.mjs 2>&1 | tail -1 && grep -rn "next-milestone item" scripts/lib/budget-gates.mjs docs/BUDGETS.md | wc -l && echo "C3-GATE-LAW-REANCHORED"</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- `node scripts/test/budget-audit.test.mjs` → final line `BUDGET-AUDIT SUITE: 19/19 vectors ok` (co-updated vectors included).
|
||||
- grep law: zero hits for "next-milestone item" in scripts/lib/budget-gates.mjs and docs/BUDGETS.md; zero hits for "ACCEPTED c3" in budget-gates.mjs.
|
||||
- ROUTE_CPU_DRIFT_GUARD_MS still exported and used (the constant survives with its new documented meaning).
|
||||
- docs/BUDGETS.md's route-cpu row carries task 2's measured p95 + date; the c3 section leads with the retirement (grep "RETIRED" ≥ 1 in the file).
|
||||
- The zero-arg child-process contract is untouched: `runCpuLadderGate` still executes measure-route-cpu.mjs with no args and the same regexes (the audit suite's own pins prove it).
|
||||
</acceptance_criteria>
|
||||
<done>The budget record and its gate law state the post-ALT truth: ≤8 ms is the gate, the variance guard is hygiene, c3 is retired with quoted numbers.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>task 4: Docs retirement (D-05) — KNOWN-LIMITATIONS + ROAD-GRAPH (+ CONFIGURATION verify)</name>
|
||||
<files>docs/KNOWN-LIMITATIONS.md, docs/ROAD-GRAPH.md</files>
|
||||
<read_first>
|
||||
- docs/KNOWN-LIMITATIONS.md IN FULL (104 lines — the c3 section 29–41; the /cari FIXED-record precedent 43–57, the exact shape to copy; the roadmap-pointer table 77–81)
|
||||
- docs/ROAD-GRAPH.md IN FULL (130 lines — the CPU-gate section 77–106 incl. the open c1/c2/c3 decision paragraph; the fork contract's build/check steps; the key-facts table 119–130)
|
||||
- docs/CONFIGURATION.md lines ~24, ~248, ~294 (verify-only: path/script-name claims that could have gone false)
|
||||
- .planning/phases/08-alt-landmark-preprocessing-routing-backend-v2/08-RESEARCH.md (D-05; Pitfall 6 — docs divorce; the ROAD-GRAPH.md section of PATTERNS)
|
||||
- Tasks 1–3's quoted numbers (the retirement record's evidence)
|
||||
</read_first>
|
||||
<action>
|
||||
1. `docs/KNOWN-LIMITATIONS.md`:
|
||||
- Replace the "Cross-metro routes may not resolve" c3 section with the retirement record, in the /cari record's shape: ROOT CAUSE (BH's weak geographic/max-speed potentials on 20–30 km cross-metro routes — the survey-predicted weak spot), FIXED 2026-10-25 (Phase 8): ALT landmark preprocessing — build-time ĉ-metric distance tables in the ARG2 graph layout + max-combined ALT/haversine A\* steering; the measured numbers that retired it (25-route p95 X ms; extended 100-pair p95 Y ms — quoted from task 2's printed lines; the D-03 optimality gate green vs the frozen pre-ALT record); what REMAINS: equal-cost tie-paths may differ (documented behavior, never a failure), and an old ARG1 binary is router-pending until ONE re-upload — the designed degradation, now the only one. Workers Paid stays rejected ($0 law).
|
||||
- Flip the roadmap-pointer ALT row: "Next-milestone item, not built" → built (Phase 8) with the measured p95; adjust the surrounding "none in this release" framing accordingly (the WASM-router and Engine-B rows stay as they are).
|
||||
2. `docs/ROAD-GRAPH.md`:
|
||||
- CPU-gate section: the ladder table gains the (c2) rung — executed, with the measured p95s + date; the decision paragraph flips from OPEN (c1/c2/c3) to DECIDED: c2 built (this phase), c1 and c3 rejected (c3 retired by measurement). Note the extended 100-pair verdict as the cross-metro evidence.
|
||||
- New short section "The ARG2 layout": 72-byte header (landmarkCount / landmarkQuantumS / reserved), the u16 dual-family table suffix + u32 anchors, the sentinel 0xFFFF law, and the `landmarkQuantumS` fork knob — 0.1 s default ⇒ ≈6,553 s expressible ceiling, raise-at-rebuild instructions for larger forks (Pitfall 5). The storage-name-vs-format-truth note: the R2 key stays `kl-roadgraph.v1.bin` (D-01 lock); the HEADER version is the format truth — never rename the key.
|
||||
- Key-facts table: "pinned CSR v1" → ARG2 wording; add the optimality-gate script to the tools list.
|
||||
- The fork contract's build step text gains the landmark facts (the stage prints them; no new commands — the contract's commands are unchanged).
|
||||
3. `docs/CONFIGURATION.md`: READ-verify — edit ONLY if a statement became false (paths and script names are unchanged; expected no-op). Note the check in the summary either way.
|
||||
TONE LAW: honest-engineering voice throughout — quote measured numbers with their date, name what remains, never overpromise ("routes in budget" only as far as the gates measured).
|
||||
</action>
|
||||
<verify>
|
||||
<automated>export PATH="$HOME/.nvm/versions/node/v24.18.0/bin:$PATH" && grep -c "Next-milestone item, not built" docs/KNOWN-LIMITATIONS.md; grep -c "FIXED 2026-10-25" docs/KNOWN-LIMITATIONS.md docs/ROAD-GRAPH.md; grep -c "landmarkQuantumS" docs/ROAD-GRAPH.md && echo "DOCS-RETIRED"</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- KNOWN-LIMITATIONS: `grep -c "Next-milestone item, not built"` = 0; the retirement record present with `FIXED 2026-10-25` + the measured p95 strings from task 2 (grep the exact quoted number ≥ 1); the tie-path and router-pending remainders named.
|
||||
- ROAD-GRAPH: the (c2) ladder rung present with numbers (`grep -c "(c2)" ≥ 1` in the ladder table region); `landmarkQuantumS` ≥ 2; "ARG2" ≥ 3; the decision paragraph states c2 executed and c1/c3 rejected; the storage-name note present.
|
||||
- No doc claims ARG1 binaries remain decodeable (grep -ci "arg1" in both docs shows only retirement/router-pending contexts — read the hits).
|
||||
- CONFIGURATION.md untouched OR the touched lines quoted in the summary.
|
||||
- Both docs keep the honest tone: no "always"/"never" claims beyond what the gates measured.
|
||||
</acceptance_criteria>
|
||||
<done>SC-3 is written: the c3 class is retired with quoted evidence in every record that documented it, and the fork contract teaches ARG2.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<threat_model>
|
||||
## Trust Boundaries
|
||||
|
||||
| Boundary | Description |
|
||||
|----------|-------------|
|
||||
| frozen record → optimality gate | the record is the phase's comparison anchor; editing it must never be able to fake a pass |
|
||||
| campaign verdicts → public docs | the retirement records quote measurements; unmeasured claims are the failure mode D-05 exists to prevent |
|
||||
|
||||
## STRIDE Threat Register
|
||||
|
||||
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|
||||
|-----------|----------|-----------|-------------|-----------------|
|
||||
| T-08-13 | Tampering | gaming the optimality gate by editing the record | mitigate | the epsilon constant-mirror assert + the record's refuse-overwrite immutability (08-01) + committed git history make any edit visible; the gate re-snaps the record's COORDINATES and re-measures live, so only a genuine equal-seconds run passes |
|
||||
| T-08-14 | Repudiation | retirement docs citing numbers never measured | mitigate | D-05's evidence law: tasks 3–4 quote task 2's printed gate lines verbatim; the review leg cross-checks the quotes against the summary |
|
||||
| T-08-15 | Tampering | extract drift faking a pass/fail | mitigate | the gate prints the counts-diff WARNING; the seconds epsilon + verdict classes are the gates; a mass-failure escalates to the user — the record is never silently re-recorded (Pitfall 1) |
|
||||
| T-08-16 | DoS | campaign runtime (100 routes + rebuild retries) | accept | maintainer-time; seconds-class measurements; the ladder is capped at one rebuild (L=32) |
|
||||
</threat_model>
|
||||
|
||||
<verification>
|
||||
- `node routing/scripts/measure-optimality-gate.mjs` → GATE PASS (D-03).
|
||||
- Both measure-route-cpu modes → GATE PASS (SC-1/SC-1′) or the documented honest-FAIL escalation.
|
||||
- `node scripts/test/budget-audit.test.mjs` → `BUDGET-AUDIT SUITE: 19/19 vectors ok`.
|
||||
- `npm run routing:test && npm test -w bot && npm run routing:typecheck && npm run bot:typecheck` — the full battery green one final time at the phase's last code-touching commit (only the new gate script + doc/gate-law edits since 08-04).
|
||||
- Docs greps (task 4's acceptance) all green; the summary quotes every gate line the records cite.
|
||||
- MANUAL (maintainer, after this plan): `node routing/scripts/upload-road-graph.mjs` + the roundtrip `--check` — the R2 upload is an account-level act (validation map, manual-only); the plan stops at the local evidence.
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
The D-03 optimality gate is green against the frozen pre-ALT record; the 25-route and extended CPU verdicts pass with ALT live (or the honest-FAIL escalation is recorded); every record that accepted the c3 degradation — budget gate law, BUDGETS, KNOWN-LIMITATIONS, ROAD-GRAPH — now states the measured post-ALT truth with dates and quoted numbers; the fork contract teaches ARG2; nothing claims more than the gates measured.
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/08-alt-landmark-preprocessing-routing-backend-v2/08-05-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user