Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand All @@ -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

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -106,26 +106,26 @@ 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

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).
Expand All @@ -144,24 +144,24 @@ 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

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.

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
Expand Down
14 changes: 7 additions & 7 deletions docs/results.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 |

Expand All @@ -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 | |

Expand Down