docs(08-05): the honest post-ALT record — KNOWN-LIMITATIONS + ROAD-GRAPH (escalation, no retirement)

Task 4, re-scoped per the plan's honest-FAIL branch: the c3 class is NOT
retired — every record now states the measured post-ALT truth.

- KNOWN-LIMITATIONS: the cross-metro section is the /cari-shaped record —
  WHAT CHANGED (ALT built, D-03 optimality green quoted) / what REMAINS
  (the CPU verdict FAIL lines quoted with date; the one-directional-
  Lipschitz wall named; the escalation open); the roadmap-pointer ALT row
  flips to Built (Phase 8) with the measured verdict — never 'not built'
  again
- ROAD-GRAPH: the ladder table gains the (c2) rung (EXECUTED, measured
  FAIL, the L=32 probe quoted); the decision paragraph states c2
  executed-verdict-fail and names the real remaining options; new 'The
  ARG2 binary layout' section (72-byte header, landmarkCount/
  landmarkQuantumS, u16 suffix + sentinels, the quantum knob's ≈6,553 s
  ceiling, the storage-name-vs-format-truth law); key facts carry the
  optimality gate and the ARG2 wording; the fork contract's build step
  teaches the landmark stage (no new commands)
- docs/CONFIGURATION.md: verify-only — all path/script claims still true,
  no edit needed
- staged as selective hunks; the tree's pre-existing doc-sync edits
  (battery paragraph, 'six maintainer scripts' intro) remain uncommitted

greps: 'Next-milestone item, not built' = 0; the measured p95 strings
quoted; (c2)/landmarkQuantumS/ARG2 all present; ARG1 appears only in
layout/router-pending contexts.
This commit is contained in:
araharah-executor
2026-10-25 20:08:57 +08:00
parent 79a302caf5
commit 720ad43765
2 changed files with 82 additions and 23 deletions
+32 -11
View File
@@ -30,15 +30,33 @@ arah² routes over a snapshot of OpenStreetMap, and inherits OSM's gaps honestly
Route computation runs inside Cloudflare Workers' free plan, whose per-request CPU Route computation runs inside Cloudflare Workers' free plan, whose per-request CPU
allowance is small. On the real KL road graph, short product routes (2–8 km — the allowance is small. On the real KL road graph, short product routes (2–8 km — the
common search-and-reroute trip) measure 2–8 ms of Worker CPU and resolve inside the common search-and-reroute trip) resolve inside the plan; cross-metro routes
plan. Cross-metro routes (20–30 km) measured p95 38–93 ms against the same graph (20–30 km) do not. Those trips therefore degrade honestly: the app shows the
(`routing/scripts/measure-route-cpu.mjs`, LADDER HISTORY; Phase 6 plan summary), which router-pending card — "the router is not ready for this trip" — instead of freezing
is beyond what the free plan permits. Those trips therefore degrade honestly: the app or drawing a wrong line. Workers Paid was rejected: it breaks the project's $0
shows the router-pending card — "the router is not ready for this trip" — instead of mandate.
freezing or drawing a wrong line. The committed upgrade lever is ALT landmark
preprocessing (a build-time graph layout that cuts A* steering cost); it is a WHAT CHANGED (Phase 8, shipped 2026-10-25): the promised ALT landmark
next-milestone item and is **not** in this release. Workers Paid was rejected: it preprocessing was built — the ARG2 graph layout carries build-time landmark
breaks the project's $0 mandate. tables (L=24, quantum 0.1 s, coverage 0.980), the search steers with them, and
optimality is verified: the D-03 gate reproduces the frozen pre-ALT record
exactly (53/53 routed pairs within ±0.1%, max |Δ| 0.005%, verdict classes
preserved — `node routing/scripts/measure-optimality-gate.mjs`).
What REMAINS — the CPU verdict measured over budget, so the degradation stands:
the 25-route gate printed `GATE FAIL: p95 152.788 ms exceeds the 8 ms budget`
and the 100-pair cross-metro verdict `GATE FAIL: p95 185.692 ms exceeds the
8 ms budget` (2026-10-25; the `--landmarks 32` probe measured worse:
182.725 / 204.499 ms). The faster steering that would help is provably
unsound here: the fromTable triangle bounds are one-directional Lipschitz
(their u-side term needs the reverse edge, which a oneway does not provide),
and the bidirectional search's shared potential is consistent only with
two-sided families — the D-03 gate caught the four-family variant returning
suboptimal routes (x038: 1234.6 s vs the 1214.8 s optimum) before it shipped.
The honest escalation — direction-split potentials with a re-proven meet rule,
Contraction Hierarchies, or Workers Paid — is open, documented in
`docs/BUDGETS.md`'s c3 section. Full-speed routing is NOT claimed; only that
the measurement is printed and the gate decides.
## The /cari command may be missing from the Telegram menu ## The /cari command may be missing from the Telegram menu
@@ -71,12 +89,15 @@ items on the roadmap.
## What is being worked on next ## What is being worked on next
Three tracks target the limits above; none of them are in this release. Three tracks target the limits above. One of them — the ALT landmark layout —
shipped in Phase 8; its measured outcome (optimality verified, CPU verdict
still over budget) is recorded in the section above. The other two are not in
this release.
| Track | What it fixes | Honest status | | Track | What it fixes | Honest status |
| --- | --- | --- | | --- | --- | --- |
| WASM-router | A client-side router compiled to WebAssembly — the static-hosted endgame where routing cost leaves the Worker entirely | Committed direction, not built | | WASM-router | A client-side router compiled to WebAssembly — the static-hosted endgame where routing cost leaves the Worker entirely | Committed direction, not built |
| ALT landmark preprocessing | The cross-metro CPU degradation (the section above) — build-time landmark layout cuts A* steering cost at $0 runtime | Next-milestone item, not built | | ALT landmark preprocessing | The cross-metro CPU degradation (the section above) — build-time landmark layout cuts A* steering cost at $0 runtime | Built (Phase 8, 2026-10-25): optimality verified; the CPU verdict measured over budget (p95 152.8/185.7 ms vs 8 ms) — the degradation stands |
| Engine B | A fully client-side webview router — routing runs in the browser, the Worker serves only data | Future track, not built | | Engine B | A fully client-side webview router — routing runs in the browser, the Worker serves only data | Future track, not built |
## Privacy in one paragraph ## Privacy in one paragraph
+50 -12
View File
@@ -27,8 +27,11 @@ instance, R2 free tier, Workers free plan).
``` ```
Computes the bbox from the committed corpus (gazetteer + golden pairs, Computes the bbox from the committed corpus (gazetteer + golden pairs,
± 0.05°), fetches ONE Overpass extract (drivable classes only), encodes ± 0.05°), fetches ONE Overpass extract (drivable classes only), runs the
the pinned CSR binary through `encodeGraph`, and writes ALT preprocessing stage through the ONE landmark module (the build prints
L, quantum, per-anchor coverage, table bytes — L=24 at KL's ~311k nodes
by the D-02 rule; `--landmarks <n>` overrides for measured retries),
encodes the pinned CSR binary through `encodeGraph`, and writes
`routing/data/kl-roadgraph.v1.bin` — **only** after the encode round-trip `routing/data/kl-roadgraph.v1.bin` — **only** after the encode round-trip
and the size gate pass. Exit 1 leaves any previous binary untouched. and the size gate pass. Exit 1 leaves any previous binary untouched.
@@ -74,7 +77,7 @@ the real binary; tests use the committed mini-graph fixture.
The binary lives in `routing/data/` and is gitignored (`*.bin`): it is The binary lives in `routing/data/` and is gitignored (`*.bin`): it is
ODbL-derived data, regenerated at will, never source. ODbL-derived data, regenerated at will, never source.
## The CPU gate (A1) — OPEN: measured over the free-plan budget ## The CPU gate (A1) — OPEN: measured over the free-plan budget, post-ALT
Workers free plan: **10 ms CPU per request** (Error 1102 beyond it). The A\* Workers free plan: **10 ms CPU per request** (Error 1102 beyond it). The A\*
cost over the REAL graph is measured, never hoped: cost over the REAL graph is measured, never hoped:
@@ -87,7 +90,7 @@ node routing/scripts/measure-route-cpu.mjs
dead-end probes reported separately) timed around `routeAstar` over the real dead-end probes reported separately) timed around `routeAstar` over the real
binary. **The gate is p95 ≤ 8 ms** (20% margin under the ceiling). binary. **The gate is p95 ≤ 8 ms** (20% margin under the ceiling).
**Measured state (2026-10-24, the 311k-node linked graph): GATE FAIL.** The **Measured state (2026-10-25, the 311k-node ARG2 graph): GATE FAIL.** The
mitigation ladder was executed in order: mitigation ladder was executed in order:
| Ladder step | Outcome | | Ladder step | Outcome |
@@ -95,15 +98,49 @@ mitigation ladder was executed in order:
| full graph, unidirectional A\* | p95 ≈ 38 ms — FAIL | | full graph, unidirectional A\* | p95 ≈ 38 ms — FAIL |
| (a) drop tertiary+residential, rebuild | p95 ≈ 18 ms — FAIL **and** 12/25 pairs became unreachable (the dropped classes are the fine mesh tying landmarks to arterials) — rejected on correctness, reverted | | (a) drop tertiary+residential, rebuild | p95 ≈ 18 ms — FAIL **and** 12/25 pairs became unreachable (the dropped classes are the fine mesh tying landmarks to arterials) — rejected on correctness, reverted |
| (b) bidirectional A\* (BH, Ikeda potentials) | p95 ≈ 38 ms — FAIL: the potential split halves each side's heuristic steering, cancelling the halved search radius. Kept: sound (A1's 625-pair Dijkstra equivalence still passes) and better on short product routes | | (b) bidirectional A\* (BH, Ikeda potentials) | p95 ≈ 38 ms — FAIL: the potential split halves each side's heuristic steering, cancelling the halved search radius. Kept: sound (A1's 625-pair Dijkstra equivalence still passes) and better on short product routes |
| (c2) ALT landmark preprocessing (Phase 8) | **EXECUTED 2026-10-25 — FAIL: p95 152.788 ms** (25-route; n=23) and **185.692 ms** (the D-04 extended 100-pair cross-metro verdict; n=53), both on the shipped L=24 build. The `--landmarks 32` probe measured **worse** (182.725 / 204.499 ms) — under the sound steering, more anchors buy no pruning and cost per-node work. Optimality verified separately: the D-03 gate reproduces the frozen pre-ALT record within ±0.1% (53/53 routed pairs). Kept: the steering is sound (A1 still passes; the A11/A12 pins forbid the unsound four-family variant) |
| (c) Workers Paid | **NOT applied — breaks the $0 law; needs a maintainer decision** | | (c) Workers Paid | **NOT applied — breaks the $0 law; needs a maintainer decision** |
The decision this gate now escalates: **(c1) Workers Paid ($5/mo — breaks The decision this gate now escalates: **(c1) Workers Paid ($5/mo — breaks
$0)**, **(c2) a graph-layout v2 with ALT landmark preprocessing (still $0 at $0)**, **direction-split potentials with a re-proven bidirectional meet rule
runtime, real build-time engineering)**, or **(c3) accept free-plan routing (the fromTable triangle bounds are one-directional Lipschitz — their u-side
with honest degradation** (long reroutes may hit 1102; the client's term needs the reverse edge, which a oneway does not provide — so the shared
`createHttpRoutingSource` then degrades to the router-pending state). Ikeda average p = (h_f − h_b)/2 cannot carry them; that search-skeleton work
Short product routes (2–8 km, the common reroute) measured 2–8 ms — inside is a new phase)**, **Contraction Hierarchies (the Phase-6 deferral)**, or
budget; the failures concentrate on 20–30 km cross-metro routes. **(c3) keep accepting free-plan routing with honest degradation** (long
reroutes may hit 1102; the client's `createHttpRoutingSource` then degrades
to the router-pending state). Short product routes (2–8 km, the common
reroute) resolve inside budget; the failures concentrate on 20–30 km
cross-metro routes. Measured numbers live in `docs/BUDGETS.md`'s c3 section.
## The ARG2 binary layout (Phase 8)
The binary's header says **version 2** ("ARG2"); all ARG1 node/edge/name
sections keep their absolute offsets, and the landmark tables ride as a
suffix:
- **Header, 72 bytes** (was 64): the extra fields are `landmarkCount` u32
(@60 — ≥ 1 REQUIRED; a landmark-less ARG2 refuses to decode, D-01's
no-silent-degradation law), `landmarkQuantumS` f32 (@64 — the ĉ unit in
seconds), and reserved padding to the 8-byte-aligned size.
- **Suffix**: two u16 tables of `landmarkCount × nodeCount` cells —
`landmarkTo` (d̂(v, ℓ): v → anchor) then `landmarkFrom` (d̂(ℓ, v)) — plus
`landmarkNodes` u32[L] (the anchors, for audits). A cell value 0xFFFF is
DATA (the unreachable sentinel), never validated away; the search reads
it raw as u16 before any float conversion.
- **The quantum knob**: distances are stored in 0.1 s quanta, so a u16 cell
expresses up to ≈ 6,553 s. The build fails loud past 65,000 quanta — a
larger-region fork raises `landmarkQuantumS` (e.g. 0.2 s ⇒ ≈ 3.6 h) and
rebuilds; never clamp.
- **Storage name vs format truth**: the R2 key stays
`kl-roadgraph.v1.bin` (the upload path is locked); the "v1" is a storage
NAME — the header's version field is the only format truth. Old ARG1
bytes decode to `null` → the designed router-pending state until the
rebuilt binary is uploaded once.
- The search consumes only the `landmarkTo` family (two-sided-Lipschitz —
see the CPU-gate section for why the `landmarkFrom` family is excluded
from steering); `landmarkFrom` remains in the layout for audits and
future search designs.
## Licensing (the ODbL attribution) ## Licensing (the ODbL attribution)
@@ -120,11 +157,12 @@ the hosted binary. Keep it intact in forks.
| What | Where | | What | Where |
|------|-------| |------|-------|
| Build tool (Overpass → CSR) | `routing/scripts/build-road-graph.mjs` | | Build tool (Overpass → CSR + ALT preprocessing) | `routing/scripts/build-road-graph.mjs` |
| Upload tool (wrangler shell) | `routing/scripts/upload-road-graph.mjs` | | Upload tool (wrangler shell) | `routing/scripts/upload-road-graph.mjs` |
| CPU measurement gate | `routing/scripts/measure-route-cpu.mjs` | | CPU measurement gate | `routing/scripts/measure-route-cpu.mjs` |
| Optimality gate (D-03) | `routing/scripts/measure-optimality-gate.mjs` |
| Binary (gitignored artifact) | `routing/data/kl-roadgraph.v1.bin` | | Binary (gitignored artifact) | `routing/data/kl-roadgraph.v1.bin` |
| R2 object key | `kl-roadgraph.v1.bin` (pinned in `worker-router.ts` as `GRAPH_KEY`) | | R2 object key | `kl-roadgraph.v1.bin` (pinned in `worker-router.ts` as `GRAPH_KEY`) |
| Binding | `ROAD_GRAPH` in `bot/wrangler.jsonc` (bucket, NEVER a KV namespace — GE5) | | Binding | `ROAD_GRAPH` in `bot/wrangler.jsonc` (bucket, NEVER a KV namespace — GE5) |
| Loader (isolate-memoized) | `bot/src/routing/worker-router.ts` → `loadGraph` | | Loader (isolate-memoized) | `bot/src/routing/worker-router.ts` → `loadGraph` |
| Binary layout authority | `routing/src/graph.ts` (`encodeGraph`/`decodeGraph`, pinned CSR v1) | | Binary layout authority | `routing/src/graph.ts` (`encodeGraph`/`decodeGraph`, pinned CSR — header version 2, the ARG2 layout above) |