diff --git a/README.md b/README.md index 9637f7c..3b5e182 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ A deterministic decision kernel with a field-enforced equivalence contract: the same C file runs live on a phone, as an MCU actuator, and in offline -replay — and all three must agree, bit for bit, on every decision. On the +replay, and all three must agree, bit for bit, on every decision. On the field corpus so far the contract holds over **11,300 shadow-compared real-world steps with zero divergences**, and 23/23 recorded ride traces replay exactly ([field results](docs/results.md); [why it's built this @@ -19,8 +19,8 @@ The demonstrator is a context-aware cycling safety cue. An iPhone + Apple Watch prototype combines map context, GPS, rider motion, and explicit rider feedback to warn a cyclist with one low-distraction haptic tap 5–20 seconds **before** entering a "squeeze zone" (narrow lane, no shoulder or bike lane, -high-speed mixed traffic). After the ride, the rider grades each cue — -useful, false alarm, too late, unrecognized — and replayable traces tune the +high-speed mixed traffic). After the ride, the rider grades each cue +(useful, false alarm, too late, unrecognized) and replayable traces tune the policy offline. The bike is the demonstrator. The reusable asset is the pipeline: @@ -30,15 +30,15 @@ sensor input → feature extraction → local decision → low-latency cue → field logging → replayable validation → MCU migration ``` -## Evidence +## Results | | | | --- | --- | | **Contribution** | Sole author: decision kernel and equivalence contract, replay harness, phone↔MCU shadow-comparison protocol, trace format, aggregation and ablation tooling, MCU ports. AI-assisted implementation gated by the tests, replay, and hardware-in-the-loop checks described below. Platform SDKs and map data are third-party. | | **Status** | Working demonstrator on private hardware. Not a product, not a safety device, no users but the author. | -| **Evidence** | 23/23 traces replay exactly; 11,301 steps logged, 11,300 compared, 0 divergences across 8 instrumented rides, over a 23-trace/88.1 km/57,783-step corpus recorded 2026-07-20 to 2026-08-08. Re-verified 2026-09-12 against a tree identical to `dd8a7db25522734de1dbec614f66113c69d80dcb`. [Field results](docs/results.md) · [re-verification](docs/field-reverification.md) · [case study](https://www.jasoneplumb.com/case-studies/cue-equivalence-contract.html) | +| **Results** | 23/23 traces replay exactly; 11,301 steps logged, 11,300 compared, 0 divergences across 8 instrumented rides, over a 23-trace/88.1 km/57,783-step corpus recorded 2026-07-20 to 2026-08-08. Re-verified 2026-09-12 against a tree identical to `dd8a7db25522734de1dbec614f66113c69d80dcb`. [Field results](docs/results.md) · [re-verification](docs/field-reverification.md) · [case study](https://www.jasoneplumb.com/case-studies/cue-equivalence-contract.html) | | **Reproduction** | The ride corpus is private (NFR-005), so a fresh clone cannot reproduce the field figures. It can run the machinery: `make test`, `make demo-corpus`, then `python3 tools/cue-results/aggregate.py demo-rides` and `python3 tools/cue-ablation/ablate.py demo-rides` over a synthetic, coordinate-free corpus. | -| **Limitations** | Agreement is consistency, not correctness — three runtimes share one kernel and therefore share its defects. One logged step was never compared. 22 of 49 watch dispatches have no recorded live delivery. Rider grades cover 33 cues from one rider. Ablations are counterfactual replays over fixed trajectories, not measured rider responses. Nothing here measures safety. | +| **Limitations** | Agreement is consistency, not correctness: three runtimes share one kernel and therefore share its defects. One logged step was never compared. 22 of 49 watch dispatches have no recorded live delivery. Rider grades cover 33 cues from one rider. Ablations are counterfactual replays over fixed trajectories, not measured rider responses. Nothing here measures safety. | ## Overview @@ -50,7 +50,7 @@ event. Missed coverage is preferable to noisy cueing. The system starts phone + wearable so the live cue loop can be field-tested quickly. The decision layer is a deterministic, allocation-free C kernel that -replays recorded traces first and migrates to an MCU evaluation board later — +replays recorded traces first and migrates to an MCU evaluation board later, making the demo a vendor-facing decision-layer reference architecture, not just a consumer app. There is no learned model anywhere in the pipeline: the cue policy is a hand-written, integer-only rule gate, which is what makes its @@ -85,7 +85,7 @@ python3 tools/cue-results/aggregate.py demo-rides # the results tables python3 tools/cue-ablation/ablate.py demo-rides # the ablation sweep ``` -Embedding the kernel is two files — `kernel/cue_policy.h` and +Embedding the kernel is two files: `kernel/cue_policy.h` and `kernel/cue_policy.c` (C99, integer-only, no allocation, no OS calls). [`examples/minimal`](examples/minimal/main.c) is the whole API in ~40 lines; [`PORTING.md`](PORTING.md) covers taking it to an MCU, and @@ -106,11 +106,11 @@ Embedding the kernel is two files — `kernel/cue_policy.h` and ## Roadmap -- **Phase 0 — Design record.** Establish the design record (kept in the private working archive); adopt repo conventions. _(done)_ -- **Phase 1 — Vertical slice.** Ride logging, composite squeeze-zone events, cue policy, watch haptic, after-ride review, trace export (FR-001…FR-009). _(code complete — all nine RFC 0003 deliverables merged)_ -- **Phase 2 — Replay loop.** Portable kernel + replay harness reproduce recorded cue decisions deterministically (FR-010, NFR-003). _(done — and verified against the first field trace)_ -- **Phase 3 — Field proof.** Three-ride engineering proof, then ten-ride case study with before/after policy comparison. _(in progress — 23-trace / 88 km corpus, 13 graded rides; see [docs/results.md](docs/results.md))_ -- **Phase 4 — MCU migration.** Board-neutral migration matrix _(done)_; on-target certification live on two silicon families — Pico W (RP2040) and ESP32-S2 (Xtensa) — with committed pass certificates in `mcu/hiltest-runs/` _(done; further ports tracked as issues)_. +- **Phase 0 - Design record.** Establish the design record (kept in the private working archive); adopt repo conventions. _(done)_ +- **Phase 1 - Vertical slice.** Ride logging, composite squeeze-zone events, cue policy, watch haptic, after-ride review, trace export (FR-001…FR-009). _(code complete: all nine RFC 0003 deliverables merged)_ +- **Phase 2 - Replay loop.** Portable kernel + replay harness reproduce recorded cue decisions deterministically (FR-010, NFR-003). _(done, and verified against the first field trace)_ +- **Phase 3 - Field proof.** Three-ride engineering proof, then ten-ride case study with before/after policy comparison. _(in progress: 23-trace / 88 km corpus, 13 graded rides; see [docs/results.md](docs/results.md))_ +- **Phase 4 - MCU migration.** Board-neutral migration matrix _(done)_; on-target certification live on two silicon families: Pico W (RP2040) and ESP32-S2 (Xtensa), with committed pass certificates in `mcu/hiltest-runs/` _(done; further ports tracked as issues)_. ## Documentation @@ -118,14 +118,14 @@ See [docs/README.md](docs/README.md) for the full documentation index, [docs/results.md](docs/results.md) for the aggregated field results (reproducible via `tools/cue-results/aggregate.py`), and [docs/design-aspects.md](docs/design-aspects.md) for the decision-layer -design walkthrough — seven design decisions, each with reasoning, value, and +design walkthrough: seven design decisions, each with reasoning, value, and tradeoff. The authoritative requirements live in the project's design record, which stays in the private working archive; its requirement IDs (FR-xxx / NFR-xxx) are the shared vocabulary used throughout this repo and its RFCs. -To view exported rides on a map — squeeze zones plus per-ride cue events on -webmap.dev's overlay pair — see +To view exported rides on a map (squeeze zones plus per-ride cue events on +webmap.dev's overlay pair), see [docs/webmap-overlays.md](docs/webmap-overlays.md). To grade the cues a ride fired and merge the grades back into its trace, see [docs/grading-guide.md](docs/grading-guide.md). @@ -144,7 +144,7 @@ Licensed under the [Apache License 2.0](LICENSE). [BTstack](https://github.com/bluekitchen/btstack) via the pico-sdk, which is free for open-source use but requires a commercial license from BlueKitchen for commercial products. This repository vendors only its own -`btstack_config.h` (Apache-2.0), so the repo's license is unaffected — but a +`btstack_config.h` (Apache-2.0), so the repo's license is unaffected, but a commercial firmware build inherits BTstack's terms. ## Status @@ -152,7 +152,7 @@ commercial firmware build inherits BTstack's terms. The live loop runs end to end: the iPhone app imports a real OSM region, scores composite squeeze zones, matches GPS to segments, and runs the same C kernel live that `replay_cli` runs offline. Cues deliver via the watch -haptic and — since RFC 0006 — a Pico W buzzer that executes the kernel +haptic and (since RFC 0006) a Pico W buzzer that executes the kernel on-board while the phone shadow-compares every step. Rides export schema-v2 traces, graded after the ride and fed back into the spec §13 tuning loop. @@ -160,8 +160,8 @@ Field record so far ([docs/results.md](docs/results.md)): 23 traces, 88.1 km, 57,783 kernel steps; 11,300 phone↔Pico shadow-compared steps with **zero divergences**; 23/23 traces replay bit-exact. The replay harness doubles as a research instrument ([docs/ablations.md](docs/ablations.md)). -The kernel is hiltest-certified on two silicon families — Pico W (RP2040) -and ESP32-S2 (Xtensa LX7) — with committed pass certificates, and CI proves +The kernel is hiltest-certified on two silicon families: Pico W (RP2040) +and ESP32-S2 (Xtensa LX7), with committed pass certificates, and CI proves byte-identical decisions across x86-64, ARM32, and RISC-V on every push. Repo conventions adapted from diff --git a/docs/results.md b/docs/results.md index 353f911..ed0374a 100644 --- a/docs/results.md +++ b/docs/results.md @@ -2,10 +2,10 @@ Every figure on this page is aggregated from the operator's local ride corpus by -[`tools/cue-results/aggregate.py`](../tools/cue-results/aggregate.py) — run +[`tools/cue-results/aggregate.py`](../tools/cue-results/aggregate.py); run `python3 tools/cue-results/aggregate.py` from the repo root to reproduce it. The corpus itself (`rides/`) is field data and stays out of the repo -(NFR-005 — it is gitignored), so this page is a dated snapshot, and the +(NFR-005: it is gitignored), so this page is a dated snapshot, and the command reproduces it wherever the corpus lives, not on a fresh clone. For a corpus a fresh clone *can* reproduce, `make demo-corpus` generates a synthetic, coordinate-free ride set that the same tools consume @@ -20,14 +20,14 @@ Raw GPS exports remain private. ## The equivalence contract -The same `kernel/cue_policy.c` runs in three places — live on the phone, as -the MCU actuator (Pico W, RFC 0006), and offline in the replay harness — and +The same `kernel/cue_policy.c` runs in three places: live on the phone, as +the MCU actuator (Pico W, RFC 0006), and offline in the replay harness; and the contract is that all three agree on the recorded logical decision fields. Shared code can also share defects. | Contract check | Result | | --- | --- | -| Offline replay of every corpus ride trace (`replay_cli`, NFR-003) | **23/23 traces exit 0** — every recorded decision reproduced exactly | +| Offline replay of every corpus ride trace (`replay_cli`, NFR-003) | **23/23 traces exit 0**: every recorded decision reproduced exactly | | Phone ↔ Pico shadow comparison, per-step, live during rides (RFC 0006 D5) | **11,301 steps logged, 11,300 compared, 0 divergences, 0 orphan reports** across 8 instrumented rides | | Pico state-size tripwire (SESSION_ACK `state_size` vs. `static_assert`) | Implemented session-start guard; same-size behavioral drift can pass it | @@ -50,8 +50,8 @@ missing report is not independently established by this re-verification. | Grade | Count | Reading | | --- | --- | --- | | `useful` | 17 | | -| `too_late` | 7 | Drove the §13 `max_notice_s` 15 → 20 widening — which then failed and is on the record in `kernel/cue_policy.h` | -| `unrecognized` | 7 | A delivery/perceptibility outcome, not a policy one (see [grading-guide.md](grading-guide.md)) — moves no policy lever | +| `too_late` | 7 | Drove the §13 `max_notice_s` 15 → 20 widening, which then failed and is on the record in `kernel/cue_policy.h` | +| `unrecognized` | 7 | A delivery/perceptibility outcome, not a policy one (see [grading-guide.md](grading-guide.md)); moves no policy lever | | `too_early` | 2 | | | `false_alarm` | 0 | |