Skip to content

TRACKER — Device architecture refactor: progress, gates, and next work #1448

Description

@timohueser

Last reviewed: 2026-08-30 — Gate 3 item 3 is COMPLETE: part 2 merged (#1553 / PR #1567 — sample assembly and running statistics live in RecorderMachine, TrackSink deleted; the one-round review caught a silent staged-tail discard at Save before merge). #1398 R1 and R2 are closed. A CI-speed PR (#1564, issue #1565 carries the cost table and two owner decisions) lands the required ci gate at ~4.5 min from ~14. The D-epic on #1515 is complete through PR #1562: D1 #1537, D2 #1547, D3 #1555, D4a #1561, the board backlight #1560 (closes #1558), and the region/frozen-base slice #1562 (closes #1559). Gate 3 items 1, 2, 3a and 6 are merged (#1545 / #1550 / #1554 / #1551); #1549 keeps four owed on-glass checks and #1557 carries the recorder follow-ups. The verification budget for agents now lives in CLAUDE.md (PR #1563) — read it there, not in an orchestration brief. On-glass work is consolidated: one curated list on #1515 (comment 5445859898) replaces every per-epic checklist, and the epics that carried nothing else are closed. The #1400 Navigator route-following cutover is complete via #1571 / PR #1572: Navigator now owns active-route identity and route-following state, ride_engine.rs is deleted, and the target App and resident RAM remain exact. V4 is complete via #1573 / PR #1574: ActionRows has three production adopters, final resources are exact, and the measured production cost is +59 lines. V5 is complete via #1575 / PR #1576: every full-screen card action list uses ActionRows, only four intentional panel callers remain, and the port is net −6 production lines with exact memory. V6 and optional V7 are closed without code after refinement disproved both proposed abstractions. Weather Hourly already shares list chrome and has different read-only semantics; a gesture-default table marker would duplicate typed handler policy without deleting exhaustive match arms. #1396 is complete through docs-only V8 child #1577 / PR #1578. W2 is complete via #1579 / PR #1580: board and simulator now share request-context assembly, the simulator uses the typed weather-effect path, and the review removed a mirrored scheduler state before merge. #1557 items 2–3 have owner policy. Recorder has no timeout/replay; damaged logical recovery uses one rider-confirmed exact removal of the RECORDING entry, preserving the map and every other object. Whole-card FORMAT and ride-kind purge are rejected. D4b is complete via #1581 / PR #1583 (merge 8ae896d6): the weather context sheet (Refresh now + Interval) replaced the Weather settings screen, the central Settings list has five rows, settings VERSION is unchanged, and the App allocation table matched exactly. D4c is complete via #1585 / PR #1586 (merge 6b507e11): the Map's own five-row sheet with three in-place display switches, settings/display.rs down to the idle-return row, VERSION unchanged, App allocations exact. D4d is complete via #1587 / PR #1588 (merge 388b9f1b): bike type has one home on the create-route sheet, the Bike-type screen is deleted, the refuted "route options" row was never built, and the cross-slice ContextValue widenings landed with exact App allocations. The D4 family (a–d) is complete. D5 is complete via #1589 / PR #1590 (merge 1d35ea17): the refuted ScreenTick::region premise was closed without code, and the slice fixed a live defect — a press landing on a slide's settling frame stole the sheet's owed base draw; that draw is now a debt only a rendered frame clears. The #1515 D1–D5 production slice map is COMPLETE (D4b #1583, D4c #1586, D4d #1588, D5 #1590, all 2026-08-30, adversarial review + green CI, no on-device work per the ruling); the epic's remaining half is the curated on-glass list (items 1–37) and is the owner's. The #1398 recovery child is IN FLIGHT as #1591 / PR #1592, paused at the final gate (2026-08-30). The owner ruled the no-on-device waiver does not extend to storage-recovery work (#1557 comment 5469819084): merge needs review + green CI + one on-device acceptance run. All software gates are green at head 9e67241d — adversarial review APPROVE plus a delta APPROVE after the owner folded the review's M1 finding in (a failed rider-confirmed Discard of a healthy recovered ride now latches one-attempt-per-action too, card copy "Discard failed"; the collapsed state model also closed a second phantom-session hole). CI green, threads resolved. The on-device run was attempted and is BLOCKED by the J-Link VCOM injection wedge (telemetry out, injected writes swallowed; survives probe-rs reset and one power-cycle; the board carries TWO USB cables so a true power-cycle must remove both). Scenarios A/B/C not started; the card untouched; no damage fabricated. The board currently runs the debug-uart acceptance image — reflash the release build before trail use. The implementer worktree /Users/timo/Documents/OSM-agents/rr1 is kept until the verified merge. Resume: full power-cycle → attach RTT → liveness-probe the link (K t 0 must echo an input: line) → run #1591 scenarios A/B/C → merge → reflash release. Related follow-ups: #1593 (pre-existing recovery-card copy overflow), the owner-started OUT/ gitignore side task. Parallel refinement-ready: #1399 T4's line-C re-measure (unblocked now that the post-D4 screen set is final) and #1400 N2–N5 refinement; TS4b (web) remains implementation-ready from the #1449 outline. The owner waived on-device, flashing, HIL, and on-glass verification for the next batch; use adversarial review plus green CI, and ask only for a subjective product choice that prior decisions and current code cannot answer.

Purpose

This issue is the single entry point for the current device architecture refactor.

It owns the global order, current frontier, cross-epic gates, and progress summary.

The linked workstream issues own architecture and acceptance criteria. Their child issues own implementation details.

GitHub lists these workstreams as formal sub-issues of this tracker.

Fresh agents must read this tracker first. They must then read the selected child issue and its parent epic.

1. Status at a glance

Current stage: Gate 0 (except FS1), DeviceCore Phase 1 (DC1–DC7, gate closed via PR #1484), the test-system delivery steps 1–3, and the #1397 slices S1/S2/S3/S5/S6a are complete — 19 merged PRs; per-slice evidence lives on the closed child issues. S5's CoreMode passed its on-glass soak 2026-08-24 (record on #1487). The board's drain_host_commands in ride.rs is the last legacy drain in any runtime host.

Current frontier: Gate 2 is closed. S4 #1447 merged via PR #1536: every screen row declares an exact RenderKeyKind, App::pass compares stack-local keys, six hand-written repaint mirrors are gone, and a four-replay differential harness (175 passes) proves parity with lower repaint counts. Its two review rounds found and fixed three real missed redraws (the map low-battery cue, the Up-ahead timeline, the rain step declared on the wrong key) and a backward replay-clock defect; 18 surviving field mutants have named masking reasons in the PR. size_of::<App>() fell 16 B, resident fell 24 B, the poll frame is unchanged. Follow-ups: #1538 (StatsKey does not name the NextAhead cache), #1539 (checkout persist-credentials sweep). Next frontier work: S6c #1516 is merged (PR #1529, f7ec1b18): −5,179 lines, the legacy host protocol, compat.rs/migration.rs, LegacyLoop and the DC1 legacy baseline all gone; 974 obc-app tests, conformance 25, 270/270 snapshot frames byte-identical, board flash −6,848 B and resident −8 B. Its review round is worth remembering: six tautological assertions were introduced while porting suites off the deleted protocol, and fixing them uncovered three lost coverage gates (the 44-row DC1 checklist left ungated, the feeder-exercise loop the issue had asked be re-homed, and three feeders that had silently stopped being recorded). All restored, each fix demonstrated against a mutant the old form passed. S6b #1494 is closed on its recorded A–K soak. S6b #1494 is closed on its recorded on-glass A–K soak (2026-08-26): A, B, C, D, E, G, H, J, K PASS; F and I partial with named reasons (F's same-id replace needs a linked-route rename+update, now known reachable; I's DFU third needs UPDATE.BIN and there is no MSC mode, #983). The soak found and closed a rider-visible UI lockout — the map-transfer card could never be dismissed (PR #1519, confirmed on glass) — and raised #1522 (no timeout bounds a stalled transfer, so a wedged peer refuses every plan by name; PR #1523 in review) plus companion bugs #1520 and #1521. S6c's start gate is met; S4 #1447 ends Gate 2 after it.

Assurance: TS1–TS3 complete (one selection engine; PR #1482). The delivery-step-3 precondition for the Gate 3 ownership cutovers is met. Strict-align defect #1171 closed with on-glass evidence.

FS10 iOS cutover (PRs #1430/#1456/#1457) is merged with physical-iPhone acceptance; Builder and simulator work remain in #1392.

Workstream Epic Current state Next gate
Flat store #1256 FS2 through FS8 complete with FS6/FS7 on-device acceptance; FS10 iOS cutover merged FS1 remains deferred; FS9 through FS11 return at Gate 5
Test system #1449 TS1–TS3 complete via merged PRs #1452, #1453, and #1482 (one selection engine; delivery step 3 done) Delivery step 4 (hot spots) can start; steps 5–6 before Gate 5 evidence
DeviceCore #1433 Phase 1 complete (DC1–DC7; gate = PR #1484) Consumed by the #1397 S-slices; S6b next
App core #1397 Complete: S1–S6c and S4 all merged; Gate 2 closed 2026-08-26 (PR #1536) Epic closeout audit
Screen vocabulary #1396 Complete: V0–V5 and V8 merged; V6 and optional V7 closed without code after current-code refinement refuted both abstractions Closed 2026-08-28 via #1577 / PR #1578
Ride domain #1398 R1 AND R2 complete; #1557 policy complete: executor-totality contract plus one-shot exact damaged-recording removal, with map and all other objects preserved Future children: bounded firmware terminal recovery, then typed store recovery for valid-catalog/rollover-blocked state; R3–R5 remain
Settings #1399 T1–T3b complete (PRs #1472, #1507, #1514, #1546 — the alert marks are their own record; v17 is the first live tail-defaulting exercise, anchors survive the upgrade) Re-measure line C against the post-#1515-D4 screen set before committing T4
Navigation #1400 #1571 / PR #1572 complete N0 guidance evidence, residual N1 route-following ownership, and the mechanical ride_engine.rs deletion; N2–N5 remain separate Refine N2–N5 after the ordered #1396 and weather work
Weather #1401 W0 absorbed; W1 complete via #1549 / PR #1551; W2 complete via #1579 / PR #1580 with one shared request-context constructor and host-specific bundle-evidence adapters preserved W3/W4 remain later slices
Map read path #1402 C6 #1467 complete via merged PR #1470 (read-counter golden gate) Re-measure epic tables (see #1402 comment) before refining C1a
Task messaging #1257 Supporting dependency DeviceCore types before migration
Board runtime #1262 Accepted executor shape Complete its close gate before platform conversion

2. Work next

2.1 Critical path

  1. Gate 3 items 1 (Catalog refresh and deletion are ordered by CatalogMachine, not composed by executors #1541/PR feat(catalog): the re-read is ordered by the domain, not composed by executors #1545) and 2 (Retention's expiry is retired by the catalog's verdict, not by a timer waiting for a rescan #1548/PR Retention's expiry is retired by the catalog's verdict, not by a timer #1550: App −8 B, one attempt where the old tree dispatched two, a live double-dispatch defect proven by a failing test first) are complete. Item 6 (Visible weather policy is decided by WeatherDomain, not assembled by each host's render call #1549/PR refactor(weather): the domain decides, and the hosts stop assembling #1551) is in review — it found WeatherDomain had ZERO production writers and the four weather corpus requirements were tautologies. Item 3 is split The ride close is a Recorder verdict, not a legacy command and a catalog re-feed #1552/One live ride state: sample assembly and running statistics move into Recorder #1553 with The ride close is a Recorder verdict, not a legacy command and a catalog re-feed #1552 in implementation; its step 0 decides whether the finalize verdict needs a connection at all. EPIC — Screen vocabulary: one ActionRows primitive, one drawing vocabulary #1396 is complete: V4 via V4 — Add ActionRows and port three card decisions #1573 / PR V4: add ActionRows and port three card decisions #1574, V5 via V5 — Complete ActionRows adoption on full-screen cards #1575 / PR V5: Complete ActionRows adoption on full-screen cards #1576, V6/V7 closed without code, and V8 via V8 — Document the landed screen vocabulary and close #1396 #1577 / PR V8: Document the current screen vocabulary #1578.
  2. The S6b/S6c follow-ups are closed: iOS: renaming a trip while unlinked duplicates it, same as #1521 for routes #1527 via PR fix(ios): a trip renamed while unlinked re-adopts its device copy #1532, iOS: 12-24 s stall between the v4 channel coming up and the first command write #1528 via PR perf(ios): one STATUS answers a head revision, not a catalog walk #1531 (a head revision is one STATUS, never a catalog walk; the connect-time walk remains as v4 LIST paging makes the connect reload O(catalog): ~90 ms per two entries #1533), and Board: 21 cfg(feature = "ble") guards provision for a configuration that cannot be built #1530 via PR refactor(board): the radio is not optional, so the guards go #1534 (the ble feature is retired — 58 guards, two CI legs, and the duplicate resource profile deleted; the sweep also repaired the obc flash ble path it first broke, and review proved the deleted CI leg byte-identical to the default leg).

2.2 Implementation-ready parallel work

2.3 Planning-ready work

Do not implement a planning-only row directly. First add files, tests, deletions, resource limits, and a formal parent relationship.

2.4 Supporting work

3. Agent start protocol

  1. Read sections 1 and 2 of this tracker.
  2. Select an implementation-ready issue whose start gate is complete.
  3. Read the child issue and its parent epic.
  4. Confirm the dependency state on GitHub.
  5. Implement one child issue.
  6. Run the proportional checks from CONTRIBUTING.md.
  7. Report exact checks, deletions, resource changes, and remaining compatibility work.
  8. Close the child only when all acceptance criteria are complete.
  9. Update this tracker after the child closes.

If texts conflict, use this precedence:

  1. This tracker controls global order and the current frontier.
  2. The parent epic controls architecture and domain acceptance.
  3. The child issue controls its implementation scope.

4. Global gates

The gates below are not exclusive time blocks. Work can run in parallel when its child issue permits it.

Cross-cutting test-system lane

#1449 supplies assurance for every global gate. It does not replace an architecture gate.

Use this order:

  1. Delivery steps 1 through 3 are complete via TS1 TS1 — Add the test-suite registry and measured inventory #1450 / PR Add the measured test-suite registry #1452, TS2 TS2 — Make CI test selection correct before it becomes smaller #1451 / PR Make CI suite selection fail closed #1453, and TS3 TS3 — One selection engine for local and CI test selection #1465 / PR ci: one selection engine for local and CI test selection #1482.
  2. Continue Gate 0 and DeviceCore Phase 1 with that assurance in place.
  3. DC7 DC7 — Close the DeviceCore Phase 1 conformance gate #1440, not TS2, is now the blocking gate before the EPIC — App core: one mode machine, one card scheduler, one frame pass #1397 protocol replacement starts.
  4. Delivery step 3 (TS3 TS3 — One selection engine for local and CI test selection #1465) is complete via PR ci: one selection engine for local and CI test selection #1482; the Gate 3 ownership-cutover precondition is met.
  5. Start delivery step 4 after the registry exists. This work can continue through Gates 1 to 4.
  6. Complete delivery steps 5 and 6 before final evidence work in Gate 5 starts.
  7. Complete delivery step 7 before Gate 5 closes.

The current work does not wait for #1449.

Gate 0: flat-store and verification foundations

Gate 0 does not require FS1 before host work. FS1 remains the final hardware fault-model proof.

Gate 1: DeviceCore foundation

DeviceCore Phase 1 can continue during Gate 0. DC7 must close before the #1397 protocol replacement starts.

Gate 2: app pass and UI ownership

Complete these local slices in #1397:

  1. Complete S1 and S3.
  2. Complete S2 after DC7.
  3. Complete S5 after S2.
  4. Complete S6 after S5 and FS7.
  5. Complete S4 S4 — Replace manual dirty mirrors with declared render keys #1447 after S6 and V0. Complete via PR S4 #1447: the screens declare what they draw, and the pass compares it #1536, 2026-08-26.

Complete V4 through V8 in #1396 after their local gates. S1 must close before the full card-family port.

Gate 2 is closed (2026-08-26): all runtime hosts use the final pass, and S4 proved its render keys at that boundary via PR #1536's differential harness.

Gate 3: domain ownership cutovers

Apply this order to ownership cutovers:

  1. Move catalog refresh and deletion into CatalogMachine. Complete via Catalog refresh and deletion are ordered by CatalogMachine, not composed by executors #1541 / PR feat(catalog): the re-read is ordered by the domain, not composed by executors #1545, 2026-08-27.
  2. Move retention policy into RetentionMachine. Complete via Retention's expiry is retired by the catalog's verdict, not by a timer waiting for a rescan #1548 / PR Retention's expiry is retired by the catalog's verdict, not by a timer #1550, 2026-08-27.
  3. Recorder cutover COMPLETE: part 1 The ride close is a Recorder verdict, not a legacy command and a catalog re-feed #1552 / PR The ride close is a Recorder verdict, not a legacy command and a catalog re-feed #1554 (2026-08-27), part 2 One live ride state: sample assembly and running statistics move into Recorder #1553 / PR Recorder assembles the ride's samples and keeps the ride's numbers #1567 (2026-08-28).
  4. Move route-following ownership into Navigator and delete ride_engine.rs. Complete via Navigator owns route following; delete Activity navigation state and RideEngine #1571 / PR Move route following into Navigator #1572, 2026-08-28. N2–N5 remain later slices.
  5. Complete the SettingsMachine persistence cutover in EPIC — Settings & stat fields: one table, one codec that migrates, one formatting vocabulary #1399.
  6. Move visible weather policy into WeatherDomain. Complete via Visible weather policy is decided by WeatherDomain, not assembled by each host's render call #1549 / PR refactor(weather): the domain decides, and the hosts stop assembling #1551, 2026-08-27 (issue open for on-glass only).

Independent baselines, codecs, formatters, and pure algorithms can start earlier when their local gate permits them.

The Recorder cutover must remove its fields before Navigator deletes ride_engine.rs.

Gate 4: platform convergence

  1. Convert HostLoop into a policy-free effect executor.
  2. Use the RideRuntime shape from AR4 — Firmware runtime: explicit RideRuntime state machine and a glanceable board hardware module #1262 and convert board HostPass into typed effect staging.
  3. Use the flat store in the simulator.
  4. Use the flat store in the web demo.
  5. Complete board detour planning and commit.
  6. Delete HostLoop policy and obsolete repository traits.

Gate 5: dependent cleanup and closure

  1. Complete the applicable EPIC — Map read path: one cache primitive, one name per concept, a catalog without filenames #1402 map-read slices.
  2. Complete the remaining EPIC — Screen vocabulary: one ActionRows primitive, one drawing vocabulary #1396 and EPIC — Settings & stat fields: one table, one codec that migrates, one formatting vocabulary #1399 work.
  3. Complete the AUDIT — Device weather: one freshness law holds; the A/B store is the removable part, and FS7 already owns it #1401 weather cleanup.
  4. Complete FS9 through FS11.
  5. Update architecture and protocol documents.
  6. Remove all compatibility interfaces.
  7. Run the required final resource and hardware gates.

5. Start gates for future slice maps

The planning-only tables remain in their domain epics:

Before work starts, create formal child issues for the next eligible row. Do not refine all later rows at one time.

6. Tracker maintenance

Update this issue when one of these events occurs:

  • A child issue closes.
  • A start gate changes.
  • A blocker changes the critical path.
  • A future row becomes an implementation issue.
  • Resource evidence changes an architecture decision.

For each update:

  1. Change the current frontier.
  2. Update the applicable checkbox.
  3. Update the workstream table.
  4. Change cross-epic gates only here.
  5. Add local technical details only to the owning epic or child.

Do not copy architecture specifications into this tracker.

7. Program acceptance

The program closes when all of these statements are true:

  • The board, simulator, and web demo use one DeviceCore product policy.
  • All runtime hosts use the flat store.
  • Each product lifecycle has one domain owner.
  • Platform executors contain no product policy.
  • Old FAT, v1 storage, host-policy, and compatibility paths are gone.
  • Board and simulator conformance traces match.
  • Required resource, fault, transport, and on-glass gates pass.
  • The test system in EPIC — Test system: one taxonomy, proportional gates, measured coverage and cost #1449 is complete.
  • Architecture and protocol documents describe the final system.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions