chore(planning): close phase 8 — verification decision recorded (CH as 08.1), direction-split research handoff written
This commit is contained in:
@@ -133,6 +133,14 @@ None - no external service configuration required. (The pending rebuild needs on
|
||||
*Phase: 08-alt-landmark-preprocessing-routing-backend-v2*
|
||||
*Completed: 2026-10-25 (task 1; task 2 pending Overpass availability)*
|
||||
|
||||
### Orchestrator addendum — task 2 COMPLETED (2026-10-25, same day)
|
||||
|
||||
The maintainer-time rebuild succeeded once Overpass recovered (HTTP 502 was transient):
|
||||
- `node routing/scripts/build-road-graph.mjs` → wrote `routing/data/kl-roadgraph.v1.bin` ARG2: 43.2 MB (45,341,620 B), 311,361 nodes / 677,126 edges / 21,469 names, maxSpeed 110
|
||||
- Landmark facts: L = 24 (D-02 rule, round(311361/13000) = 24), quantum 0.1 s, coverage min/mean 0.980/0.980 (gate ≥ 0.9), table bytes 28.5 MB, sentinels 150,986 to / 1,365,034 from
|
||||
- `--check routing/data/kl-roadgraph.v1.bin` → exit 0, facts decoded from the binary
|
||||
- The 08-05 BLOCKED note above is superseded: the ARG2 binary exists on the main tree — the campaign can run directly. R2 re-upload (`node routing/scripts/upload-road-graph.mjs`) remains a deploy-time user action, not an execution blocker.
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
- `routing/scripts/build-road-graph.mjs` exists with the stage (grep-verified counts above) — FOUND
|
||||
|
||||
@@ -130,6 +130,41 @@ No new network endpoints, auth paths, file access patterns, or schema changes
|
||||
- `grep -c "P95_BUDGET_MS = 8" routing/scripts/measure-route-cpu.mjs` = 1; `grep -c "next-milestone" scripts/lib/budget-gates.mjs docs/BUDGETS.md` = 0+0; `nodes[0]|nodes.length` in the gate = 0
|
||||
- The record file: untouched (verified by the gate's own mirror asserts + git)
|
||||
|
||||
## F1 Remediation Addendum (post-plan, 2026-10-25)
|
||||
|
||||
**Debug session:** `.planning/debug/alt-potential-4x-slowdown.md` — RC-1 (LIVE correctness bug) + RC-2 (the 4× CPU slowdown). D-03's green above was sampling luck: the fixed corpus never crosses a violating edge harmfully, while fresh random pairs caught the shipped `routeAstar` suboptimal on **1/194** (+0.278%, pair 141683→292552) vs a Dijkstra oracle. Root cause: `bound()`'s per-node sentinel skip varied the active landmark family set PER NODE across edges leaving the 6,285-node disconnected island (2.02% of cells).
|
||||
|
||||
**Fix (F1, exactly as the debug report specified):** `routing/src/astar.ts`
|
||||
- Per-graph WeakMap memo `cleanColumnsFor` — `clean[l]` = "to-column ℓ has zero 0xFFFF cells" (O(L·n) sequential rows once per graph/isolate; `reverseFor` precedent).
|
||||
- Per-search active list `activeL` = clean columns only; `bound()` loops the active list with NO per-node sentinel branch (constant-table goal/origin NaN checks retained as belt).
|
||||
- On the current binary (0/24 clean columns — island census confirmed) potentials degrade to EXACTLY haversine: the designed sound fallback; the pre-ALT CPU band returns.
|
||||
- ALT stays LIVE and tested: the committed mini-graph is 0/2 dirty columns and A12's ring is all-clean (both verified by table scan), so the ALT path keeps running in the suite.
|
||||
- BH stop rule, reductions, balanced alternation, meet probes, real-seconds reconstruction: untouched. F2 (transposed table) explicitly out of scope — future clean-column binaries only.
|
||||
|
||||
**Test work (re-specified per the debug report):**
|
||||
- A9: island fixture re-pinned as ALL-DIRTY (every to-column holds a B-node sentinel → the whole fixture runs haversine); the old "real ALT bounds live in A" claim (per-node-skip semantics) removed.
|
||||
- A10: mechanism comment updated to the containment law.
|
||||
- A11: structural pin rewritten to the F1 shape — `cleanColumnsFor`/`activeL` must exist in code, inline `=== 0xffff` sentinel compares BANNED (RC-1's exact shape), named-constant law pinned. Committed RED-first: failed on shipped code exactly as designed.
|
||||
- A12: re-sealed as the ALT-ACTIVE counterpart (all to-columns clean, pinned by table scan).
|
||||
- A13 (new): mixed clean/dirty columns via a one-way-bottleneck twin-ring fixture — the subset-active-list branch; 64-pair Dijkstra equivalence + 16 honest nulls.
|
||||
|
||||
**New committed gate:** `routing/scripts/measure-astar-oracle-sweep.mjs` — 200 COMPARED fresh seeded cross-metro pairs (seed `0x08f1`, NOT the D-03 corpus; `generateCrossMetroPairs` core reused; 3× oversample with snap-miss rejection printed; exported `sweepOracle` core + CLI guard; honest SKIP when the gitignored binary is absent). Gate: 0 suboptimal vs a brute-force label-setting Dijkstra oracle.
|
||||
|
||||
**Verification (all re-run post-fix, this host):**
|
||||
|
||||
| Gate | Result |
|
||||
| ---- | ------ |
|
||||
| `npm run routing:test` | 81 passed, 0 failed (A11 RED pins green, A13 new) |
|
||||
| `npm test -w bot` | 126 passed, 0 failed |
|
||||
| `routing:typecheck` + `bot:typecheck` | clean |
|
||||
| Oracle sweep (new) | GATE PASS: 0/200 suboptimal (182 routed, 18 unreachable, worst Δ +0.000%) |
|
||||
| `measure-route-cpu.mjs` | p95 136.562 ms / mean 54.081 ms — the pre-ALT band on this host (pre-fix today measured 1037.618 ms; ~7.6× back). Honest c3 record stands: still a FAIL vs the 8 ms budget |
|
||||
| `measure-optimality-gate.mjs` (D-03) | GATE PASS: 0 violations, max \|Δ\| 0.005%, verdict classes preserved |
|
||||
|
||||
**Commits:** `c071e20` (test RED), `2a5a0b5` (fix F1), `97d6e35` (oracle sweep). Bench/instrumentation harnesses remain in `/tmp/opencode/alt-bench/` (never committed).
|
||||
|
||||
**Impact on the plan's verdicts:** the D-03 gate green above is now backed by a fresh-pair pin that structurally can't pass on sampling luck; the CPU verdict is unchanged in kind (c3 escalation stands — ALT is inert on this binary until a clean-column rebuild exists, and a rebuilt clean-column binary re-arms ALT with no code change).
|
||||
|
||||
## User Setup Required
|
||||
|
||||
None new. The maintainer-time R2 upload (`node routing/scripts/upload-road-graph.mjs` + the `--check` roundtrip) remains the deploy-time act — manual by design (account-level validation). **Decision needed:** pick the escalation track (direction-split potentials / CH / Workers Paid reversal / keep c3).
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
---
|
||||
phase: 08-alt-landmark-preprocessing-routing-backend-v2
|
||||
verified: 2026-10-25T14:43:22Z
|
||||
status: gaps_found
|
||||
score: 1/3 roadmap success criteria (SC-2 ✓; SC-1 ✗; SC-3 ✗ as written — correctly not taken). All 5 plans' machinery must-haves verified.
|
||||
overrides_applied: 0
|
||||
re_verification:
|
||||
previous_status: none
|
||||
previous_score: n/a
|
||||
gaps_closed: []
|
||||
gaps_remaining:
|
||||
- "SC-1: longest KL-metro routes route within the free-plan CPU budget"
|
||||
- "SC-3: the c3 degradation class retires"
|
||||
regressions: []
|
||||
gaps:
|
||||
- truth: "Longest KL-metro routes route within the free-plan CPU budget (p95 under the 8 ms ceiling, measured by the existing CPU gate) — SC-1"
|
||||
status: failed
|
||||
reason: "The measured verdict is a FAIL and stayed a FAIL through the pre-committed ladder: p95 152.788 ms (25-route CI gate) / 185.692 ms (D-04 extended 100-pair verdict) vs the 8 ms budget on the campaign host; this verifier's own re-run measured p95 107.493 ms — same band, same honest FAIL. The L=32 ladder rung measured worse (182.725 / 204.499 ms). Post-F1, ALT is INERT on the current binary by design: 0/24 landmark toTable columns are sentinel-clean (the 6,285-node island, 2.02% of cells), so potentials degrade to exactly haversine and the pre-ALT CPU band returned. The theoretically sound fast configuration (direction-split potentials π_f/π_r with a re-proven bidirectional meet rule) is search-skeleton work that Phase 8's own untouchable lines (stop rule, reductions, alternation, meet probes, reconstruction) forbid. Every number is quoted verbatim into docs/BUDGETS.md, docs/KNOWN-LIMITATIONS.md, docs/ROAD-GRAPH.md, and scripts/lib/budget-gates.mjs (drift guard 400 ms; the 8 ms budget unchanged, its FAIL still printed)."
|
||||
artifacts:
|
||||
- path: "routing/scripts/measure-route-cpu.mjs"
|
||||
issue: "None — the gate is honest and healthy (P95_BUDGET_MS = 8 unchanged; prints GATE FAIL). The gap is the measured number, not the tool."
|
||||
- path: "routing/src/astar.ts"
|
||||
issue: "ALT potentials are sound-but-inert on this binary (clean-columns-only F1 law; 0/24 clean columns). Making them fast requires direction-split potentials — code outside this phase's sanctioned surface."
|
||||
missing:
|
||||
- "USER STRATEGIC DECISION (not a fix plan): pick the escalation track recorded in docs/BUDGETS.md §c3 and 08-05-SUMMARY — (1) direction-split potentials with a re-proven bidirectional meet rule (search-skeleton work; needs its own planned phase with the BH meet rule re-proven), (2) Contraction Hierarchies (the Phase-6 deferral, the Malaysia-scale tier), (3) Workers Paid (rejected by the $0 law — reversal needs explicit sign-off), or (4) keep c3 as the designed degradation (the current shipped posture: router-pending on long cross-metro reroutes). Option 4 is the only one requiring zero further code."
|
||||
- truth: "The budget record's c3 degradation class retires; KNOWN-LIMITATIONS updated — SC-3"
|
||||
status: failed
|
||||
reason: "The retirement half of the criterion did NOT happen — correctly: the pre-committed law (retirement never fires on failing numbers) forbids it, and SC-1 failed. The record-update half IS complete and honest: KNOWN-LIMITATIONS' cross-metro section is the /cari-shaped post-ALT record (WHAT CHANGED / what REMAINS, quoted gate lines), its ALT roadmap-pointer row reads 'Built (Phase 8, 2026-10-25): optimality verified; the CPU verdict measured over budget', BUDGETS and ROAD-GRAPH carry the same quoted numbers, and 'next-milestone' wording is purged everywhere (grep = 0 across all four records)."
|
||||
artifacts:
|
||||
- path: "docs/KNOWN-LIMITATIONS.md"
|
||||
issue: "None — the honest record is exactly what D-05's fail branch prescribes. Retirement is contingent on SC-1 and cannot honestly happen while it fails."
|
||||
missing:
|
||||
- "Contingent on the SC-1 decision above: only after a passing CPU verdict does a closure plan rewrite these records as a retirement."
|
||||
deferred: []
|
||||
human_verification:
|
||||
- test: "Decide the c3 escalation track (the gap above): direction-split potentials / CH / Workers Paid reversal / keep c3."
|
||||
expected: "A maintainer decision recorded against docs/BUDGETS.md §c3; if 'keep c3', Phase 9+ proceed with the current honest-degradation posture; if a code track, it becomes a planned phase of its own."
|
||||
why_human: "Strategic trade-off between $0 law, scope, and schedule — not verifiable from the codebase."
|
||||
- test: "Verify the R2 migration state: the shipped decode path is ARG2-ONLY (D-01), so if the R2 object kl-roadgraph.v1.bin still holds ARG1 bytes, the deployed Worker returns router-pending for EVERY route until the rebuilt binary is uploaded once. Run `node routing/scripts/upload-road-graph.mjs` then the `--check` roundtrip against R2 (maintainer-time, account-gated)."
|
||||
expected: "The R2 object decodes as ARG2 (version 2, L=24, coverage 0.980) and production /api/route serves real routes again."
|
||||
why_human: "R2 contents and deploy state are outside the repo; the upload is deliberately a manual, account-validated act."
|
||||
---
|
||||
|
||||
# Phase 8: ALT Landmark Preprocessing (Routing Backend v2) — Verification Report
|
||||
|
||||
**Phase Goal:** Cross-metro routes route in-budget on the free plan: ALT (A\*, Landmarks, Triangle-inequality) preprocessing over the CSR graph upgrades engine A's worst case while staying $0 — the c2 rung of the measured ladder, executed.
|
||||
**Verified:** 2026-10-25T14:43:22Z
|
||||
**Status:** gaps_found
|
||||
**Re-verification:** No — initial verification
|
||||
|
||||
## Goal Achievement — the honest verdict
|
||||
|
||||
The phase's **machinery landed completely and at high quality**: ARG2 codec, landmark preprocessing, ALT steering, build-stage integration, the D-03 optimality gate, and every record rewritten honestly. The phase's **core measurable deliverable did not land**: the CPU verdict is a FAIL (p95 107–186 ms across hosts/modes vs the 8 ms budget), the pre-committed ladder ran to its documented stop, and the debug session proved the wall is structural (ALT inert on this binary; the fast configuration is provably unsound under the shared-average BH; the fix is out-of-constraint skeleton work). SC-2 (optimality) is the one success criterion achieved — and it was hard-won: the phase's own gates caught and fixed two real suboptimality bugs (Rule-1 fromTable, RC-1 per-node sentinel skip → F1).
|
||||
|
||||
This is the honest-FAIL branch the plan pre-committed to, executed faithfully. The gap that remains is a **maintainer strategic decision**, not a defect a closure plan can silently fix.
|
||||
|
||||
### Observable Truths (roadmap contract)
|
||||
|
||||
| # | Truth | Status | Evidence |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | SC-1: Longest KL-metro routes route within the free-plan CPU budget (p95 under the ceiling, measured by the existing CPU gate) | ✗ FAILED | Campaign: `GATE FAIL: p95 152.788 ms exceeds the 8 ms budget (A1)` + extended `GATE FAIL: p95 185.692 ms` (n=53); L=32 probe worse (182.725 / 204.499). **This verifier re-ran the gate:** `GATE FAIL: p95 107.493 ms exceeds the 8 ms budget` — same honest band. Post-F1 ALT is inert on the current binary (0/24 clean toTable columns — the 6,285-node island), so the c2 rung bought no measured CPU improvement. |
|
||||
| 2 | SC-2: Route optimality unaffected (ALT admissible — corpus re-run green with identical tolerance verdicts) | ✓ VERIFIED | **Re-ran both gates this session:** D-03 gate `GATE PASS: 53/53 routed pairs equal within ±0.1%, verdict classes preserved (100/100 record pairs; 6 unreachable + 41 unsnappable preserved, 0 re-snapped)`, 0 violations, max \|Δ\| 0.005%, epsilon mirror intact; oracle sweep `GATE PASS: 0/200 \|Δ\| violations` (182 routed, 18 unreachable, worst \|Δ\| +0.000%) on fresh seed-0x08f1 pairs the fixed corpus structurally cannot cover. routing:test 82/82 (incl. A1 625-pair Dijkstra-equivalence, A11/A12/A13 pins). |
|
||||
| 3 | SC-3: The budget record's c3 degradation class retires; KNOWN-LIMITATIONS updated | ✗ FAILED (as written — correctly not taken) | Retirement never fires on failing numbers (the pre-committed law). The update half IS done: KNOWN-LIMITATIONS carries the quoted post-ALT record, the ALT row reads "Built (Phase 8, 2026-10-25): optimality verified; the CPU verdict measured over budget — the degradation stands"; "next-milestone" purged from all four records (grep = 0). |
|
||||
|
||||
**Score:** 1/3 roadmap success criteria. (All five plans' machinery must-haves — ARG2 codec laws, landmark module, ALT containment, build-stage integration, gates + records — verified; see below.)
|
||||
|
||||
**Score note:** SC-3's failure is *compliant* behavior, not neglect — the criterion is arithmetically unreachable while SC-1 fails, and faking it would have violated the phase's own honest-engineering law. It is nonetheless reported as not-achieved because the class did not retire.
|
||||
|
||||
### Plan-Level Machinery (must_haves from the 5 PLANs — all verified)
|
||||
|
||||
| Plan | Claimed machinery | Verified evidence |
|
||||
| --- | --- | --- |
|
||||
| 08-01 | Pre-ALT baseline frozen BEFORE the codec; ARG1 guard; --extended D-04 flag; default mode byte-compatible | `measure-optimality-baseline.mjs` refuses non-ARG1 binaries (version check at L153–155); `alt-baseline.json` is coordinate-pinned (origin/destination lat-lng, never node indices) with the epsilon block `{name: OPTIMALITY_EPSILON_PCT, pct: 0.1}`; `--extended` imports `generateCrossMetroPairs` from the baseline module (ONE pair-set definition, two consumers); `P95_BUDGET_MS = 8` grep = 1 |
|
||||
| 08-02 | ARG2 codec, exact-size-before-allocation, ARG1→null, fixture regenerated through the ONE encode path, landmark.ts the single table authority | `graph.ts`: magic `0x41524732`, version 2, `landmarkCount/landmarkQuantumS/landmarkTo/landmarkFrom` fields, `buffer.byteLength !== lay.total → null` at L228 (before view allocation); `graph.test.mjs:139` consumes `mini-graph-arg1.bin` as the rejection vector; `mini-graph.bin` regenerated (1668→1884 B); `landmark.ts` exports `farthestPointAnchors/landmarkTables/landmarkCoverage` + `LANDMARK_QUANTUM_S/MAX_QUANTA/I32_WEIGHT_CEILING` (WR-04 fix present) |
|
||||
| 08-03 | ALT inside the proven BH skeleton; clean-columns containment (F1); rollout locks | `astar.ts`: `cleanColumnsFor` (L233) + search-scoped `activeL` (L358–362), `LANDMARK_SENTINEL_U16` named constant, haversine max-fallback; **`landmarkFrom` appears ZERO times in astar.ts** (the A11 law — stronger than required); `rollout.test.mjs` RO1/RO2 structural pins ran green in the suite; worker-router.ts and upload-road-graph.mjs contain no version/format branches (grep = 0) |
|
||||
| 08-04 | Build preprocessing stage via the ONE landmark module; D-02 scaling rule; honest gates; --check | `build-road-graph.mjs`: imports the landmark module (never re-implements Dijkstra), `NODES_PER_LANDMARK = 13000` → clamp(round(N/13000),16,32), `LANDMARK_MIN_COVERAGE_FRACTION = 0.9` override-proof, `--landmarks` knob (cap 128); **live `--check` on the real binary:** nodeCount 311,361 / edgeCount 677,126 / landmarkCount 24 / quantum 0.100 / coverage min/mean 0.980/0.980 — the canonical L=24 build, upload-ready |
|
||||
| 08-05 | D-03 gate with constant-mirror; honest campaign; records tell the post-ALT truth | Gate asserts `record.epsilon.name === "OPTIMALITY_EPSILON_PCT" && pct === 0.1` BEFORE measuring (L258); reads the frozen record, never regenerates pairs; budget-gates drift guard `ROUTE_CPU_DRIFT_GUARD_MS = 400` with the quoted post-ALT band; BUDGETS/KNOWN-LIMITATIONS/ROAD-GRAPH all quote the same gate lines (53 routed / 152.788 / 185.692 / 182.725 / 204.499) — mutually consistent, verified against the REVIEW.md cross-check |
|
||||
|
||||
### Required Artifacts
|
||||
|
||||
| Artifact | Expected | Status | Details |
|
||||
| -------- | -------- | ------ | ------- |
|
||||
| `routing/src/graph.ts` | ARG2 single-authority codec | ✓ VERIFIED | Substantive + wired (decoded the real binary live via `--check`; consumed by bot tests 126/126) |
|
||||
| `routing/src/landmark.ts` | ONE landmark compute core | ✓ VERIFIED | All three exports + WR-04 i32 ceiling guard; consumed by build script + fixture builder + tests |
|
||||
| `routing/src/astar.ts` | ALT potentials, F1 containment | ✓ VERIFIED | cleanColumnsFor/activeL present; landmarkFrom absent; toTable-only (sound subset) |
|
||||
| `routing/scripts/measure-optimality-baseline.mjs` | Baseline recorder + shared pair core | ✓ VERIFIED | ARG1-version guard; exports consumed by measure-route-cpu |
|
||||
| `routing/test/fixtures/alt-baseline.json` | Frozen pre-ALT record | ✓ VERIFIED | 29.6 KB, coordinate-pinned, epsilon block; untouched (gate mirror proves per run) |
|
||||
| `routing/test/fixtures/mini-graph-arg1.bin` | Preserved ARG1 rejection vector | ✓ VERIFIED | 1668 B, byte-preserved; consumed by graph.test.mjs:139 |
|
||||
| `routing/test/fixtures/mini-graph.bin` | Regenerated ARG2 fixture | ✓ VERIFIED | 1884 B; suite-wide consumption green |
|
||||
| `routing/scripts/measure-route-cpu.mjs` | CPU gate + --extended | ✓ VERIFIED | Budget constant untouched; extended mode shares the pair core |
|
||||
| `routing/scripts/measure-optimality-gate.mjs` | D-03 gate | ✓ VERIFIED | Mirror assert; GATE PASS re-run this session |
|
||||
| `routing/scripts/measure-astar-oracle-sweep.mjs` | 200-pair fresh oracle sweep | ✓ VERIFIED | WR-01 symmetric \|Δ\| fix present (L244); GATE PASS re-run this session |
|
||||
| `routing/scripts/build-road-graph.mjs` | Preprocessing stage + knobs | ✓ VERIFIED | Scaling rule, coverage gate, --landmarks, --check landmark facts |
|
||||
| `routing/test/rollout.test.mjs` | D-01 rollout locks | ✓ VERIFIED | RO1/RO2 pins green in suite; targets verified format-unaware |
|
||||
| `scripts/lib/budget-gates.mjs` | Re-anchored route-cpu law | ✓ VERIFIED | Drift guard 400; quoted c3 record; no next-milestone |
|
||||
| `docs/BUDGETS.md` / `docs/KNOWN-LIMITATIONS.md` / `docs/ROAD-GRAPH.md` | Post-ALT honest records | ✓ VERIFIED | Quoted numbers mutually consistent; ALT row flipped; ARG2 layout section present |
|
||||
| `routing/data/kl-roadgraph.v1.bin` | Canonical L=24 ARG2 binary (gitignored) | ✓ VERIFIED | On disk, 45.3 MB; decodes ARG2 with L=24/quantum 0.1/coverage 0.980 |
|
||||
|
||||
### Key Link Verification
|
||||
|
||||
| From | To | Via | Status | Details |
|
||||
| ---- | -- | --- | ------ | ------- |
|
||||
| astar.ts potential() | ARG2 landmark tables | `graph.landmarkTo` reads via cleanColumnsFor/activeL | WIRED | L233–242, L358–402 |
|
||||
| measure-route-cpu --extended | measure-optimality-baseline | `import { generateCrossMetroPairs }` | WIRED | L60, L110 — one pair set, two consumers |
|
||||
| measure-optimality-gate | alt-baseline.json | reads frozen record + epsilon mirror | WIRED | RECORD_PATH L53; mirror assert L258 fires before measurement |
|
||||
| build-road-graph preprocessing | landmark.ts | dynamic import of the ONE module | WIRED | L202; no second Dijkstra exists (grep across scripts = 0) |
|
||||
| graph.test.mjs | mini-graph-arg1.bin | ARG1 decode-rejection vector | WIRED | L139 |
|
||||
| rollout.test.mjs | upload script + worker-router | structural grep pins | WIRED | RO1 pins the R2 key; RO2 pins no version branch — both targets verified clean |
|
||||
| mini-graph.bin / bot test builders | ARG2 encode path | same encodeGraph authority | WIRED | bot 126/126 green after fixture regen |
|
||||
|
||||
### Data-Flow Trace (Level 4)
|
||||
|
||||
Not applicable to dynamic-UI artifacts (this phase ships no UI). The data-flow analog — real graph bytes → decode → search → gates — was exercised end-to-end this session: the 45.3 MB binary decodes (311,361 nodes / 677,126 edges / L=24), routes (23/25 routed in the CPU sample), and feeds both optimality gates with real measured seconds (D-03: 53 pairs; oracle: 182 routed pairs). No static/hollow data paths found.
|
||||
|
||||
### Behavioral Spot-Checks (all run by this verifier, this host, 2026-10-25)
|
||||
|
||||
| Behavior | Command | Result | Status |
|
||||
| -------- | ------- | ------ | ------ |
|
||||
| Routing suite (A1–A13, G1–G11, L, S, RO suites) | `npm run routing:test` | 82 passed, 0 failed | ✓ PASS |
|
||||
| Bot suite (ARG2 fixture consumers) | `npm test -w bot` | 126 passed, 0 failed | ✓ PASS |
|
||||
| D-03 optimality gate (SC-2) | `node routing/scripts/measure-optimality-gate.mjs` | `GATE PASS`, exit 0 — 0 violations, max \|Δ\| 0.005% | ✓ PASS |
|
||||
| 200-pair fresh oracle sweep (SC-2 pin) | `node routing/scripts/measure-astar-oracle-sweep.mjs` | `GATE PASS: 0/200 \|Δ\| violations` (182 routed, worst +0.000%) | ✓ PASS |
|
||||
| CPU gate (SC-1) | `node routing/scripts/measure-route-cpu.mjs` | `GATE FAIL: p95 107.493 ms exceeds the 8 ms budget` | ✗ FAIL (honest — the SC-1 gap) |
|
||||
| Binary identity + landmark facts | `node routing/scripts/build-road-graph.mjs --check routing/data/kl-roadgraph.v1.bin` | ARG2; L=24; quantum 0.100; coverage 0.980; sentinels 150,986 to / 1,365,034 from | ✓ PASS |
|
||||
| Budget-audit vectors | `node scripts/test/budget-audit.test.mjs` | `19/19 vectors ok` | ✓ PASS |
|
||||
|
||||
(Overpass build NOT re-run per instructions; the on-disk binary is the canonical L=24 build.)
|
||||
|
||||
### Requirements Coverage
|
||||
|
||||
| Requirement | Source Plan | Description | Status | Evidence |
|
||||
| ----------- | ---------- | ----------- | ------ | -------- |
|
||||
| SC3 (carry-over) | 08-01..05 frontmatter | Phase-5 criterion: fixture backend ladder + designed router-pending state | ✓ SATISFIED (no regression) | routing 82/82, bot 126/126; rollout pins hold; router-pending law intact |
|
||||
| SC4 (carry-over) | 08-01..05 frontmatter | Phase-5 routing-class carry-over | ✓ SATISFIED (no regression) | Same suite evidence |
|
||||
| Phase-8 requirement ("the budget record's numbers improve") | ROADMAP §Phase 8 | No new REQ ids; the c3 numbers improve | ✗ BLOCKED | The measured numbers did NOT improve (p95 107–186 ms vs the pre-ALT ~38 ms campaign band); the record honestly documents the non-improvement. Covered by the SC-1 gap above. |
|
||||
| Orphaned requirements | — | none | — | REQUIREMENTS.md maps no additional ids to Phase 8 (grep: SC3/SC4 appear only as ROADMAP-level carry-overs) |
|
||||
|
||||
### Anti-Patterns Found
|
||||
|
||||
| File | Line | Pattern | Severity | Impact |
|
||||
| ---- | ---- | ------- | -------- | ------ |
|
||||
| — | — | No TODO/FIXME/placeholder/stub patterns in any phase file (grep clean across all 7 scripts + 3 src modules) | — | — |
|
||||
| routing/src/astar.ts | 315–316, 515, 598 | `return null` / `return []` | ℹ️ Info | Fail-honest designed degradation (input validation, unreachable miss, empty path) — not stubs |
|
||||
| measure-*.mjs | various | `= []` accumulators | ℹ️ Info | Local accumulator init, not hardcoded empty data |
|
||||
|
||||
Open code-review findings carried for the record (documented in 08-REVIEW.md, not re-litigated here): **WR-03** (baseline recorder lacks oversampling — the frozen evidence base is 53 measured pairs, not ~100; maintainer-deferred, record immutable) and **IN-01..IN-07** (doc-statement drift, defensive gaps in future-record paths). WR-01/02/04 verified applied: symmetric |Δ| compare at oracle L244, CPU3 honest-SKIP law, `LANDMARK_I32_WEIGHT_CEILING` guard at landmark.ts L131 — each with its fix commit (11e55c1, 95399ae, e77bbe9) present in history.
|
||||
|
||||
### Human Verification Required
|
||||
|
||||
1. **The c3 escalation decision (the gap itself — belongs to the USER).**
|
||||
**Test:** Choose the track: (1) direction-split potentials with a re-proven bidirectional meet rule (needs its own phase — skeleton work Phase 8's laws forbade), (2) Contraction Hierarchies (Phase-6 deferral), (3) Workers Paid reversal (needs explicit sign-off against the $0 law), (4) keep c3 as the designed degradation (current shipped posture; zero code).
|
||||
**Expected:** A recorded decision against docs/BUDGETS.md §c3 that unblocks either Phase 9 (option 4) or a new planned phase (options 1–2).
|
||||
**Why human:** Strategic trade-off across cost law, scope, and schedule — not decidable from code.
|
||||
2. **R2 migration state (D-01's one-time upload).**
|
||||
**Test:** `node routing/scripts/upload-road-graph.mjs` + `--check` roundtrip against R2 (maintainer-time, account-gated).
|
||||
**Expected:** The R2 object `kl-roadgraph.v1.bin` holds the ARG2 build (v2, L=24, coverage 0.980); production `/api/route` serves real routes. Until then, any deploy of the current Worker code is router-pending on every route (ARG1 bytes decode to null by design).
|
||||
**Why human:** R2 contents and deploy timing are outside the repo; the upload is deliberately manual.
|
||||
|
||||
### Gaps Summary
|
||||
|
||||
One root cause, two failed criteria. **The CPU win — the phase's core deliverable — did not land** (SC-1), and therefore **the c3 retirement correctly did not fire** (SC-3). What DID land, verified end-to-end this session: the ARG2 layout (single decode path, fail-honest, exact-size law), the landmark machinery (module, build-stage integration, D-02 scaling rule, honest coverage/quantum gates, the canonical L=24 binary), optimality hardening beyond the plan's bar (D-03 gate + 200-pair fresh oracle sweep, both green — after the phase's own gates caught two real suboptimality bugs), and four records rewritten to the quoted post-ALT truth with zero retirement theater.
|
||||
|
||||
The remaining work is not a bug fix: the debug session proved a perfectly implemented two-sided ALT cannot beat haversine in this bidirectional configuration on a graph with sentinel fringes (0/24 clean columns), and the sound fast path (direction-split potentials) requires re-proving the BH meet rule — work this phase's untouchable lines forbade. **This is the escalation decision recorded in docs/BUDGETS.md §c3 and 08-05-SUMMARY, and it belongs to the maintainer**, not to a closure plan. No later milestone phase covers it: Phase 9 builds on the current posture, Phase 10 is the battery record, and Phase 11 (Engine B) moves routing client-side without promising the Worker path in-budget — so nothing here is deferrable.
|
||||
|
||||
---
|
||||
|
||||
_Verified: 2026-10-25T14:43:22Z_
|
||||
_Verifier: OpenCode (gsd-verifier)_
|
||||
|
||||
### Decision addendum (2026-10-25, maintainer)
|
||||
|
||||
The SC-1 escalation decision was made: **Contraction Hierarchies, as Phase 08.1** (inserted, "Routing Backend v3") — the only lever the measured evidence supports reaching the 8 ms budget. Direction-split potentials are NOT closed: the measured prizes (0.59× expansions unidirectional control; −41% transposed table) and the full proof-obligation surface are handed off in `docs/ALT-DIRECTION-SPLIT.md` as a standalone experiment (explicitly open to being worked with a different LLM/harness). SC-1 and SC-3 transfer to Phase 08.1; this phase's debt is the honest record above plus that handoff. SC-2's hardening stands as the phase's optimality proof.
|
||||
Reference in New Issue
Block a user