diff --git a/docs/RCP-ARCHITECTURE.md b/docs/RCP-ARCHITECTURE.md index 011e9fb..2508da5 100644 --- a/docs/RCP-ARCHITECTURE.md +++ b/docs/RCP-ARCHITECTURE.md @@ -22,6 +22,23 @@ Every choice below was derived by comparing the four repos' actual code, not invented from scratch — each is attributed to the repo(s) whose existing pattern it's drawn from. +**cpp-RCP v3.0.0 (2026-08-22):** cpp-RCP shipped a full ground-up rewrite, +ported module-by-module from c-RCP's current RC5-conformant +implementation (cpp-RCP issue #129, ROADMAP.md Phase 17 — "first release +where cpp-RCP *is* the OPEN Alliance TC18 Remote Control Protocol"). +Several cpp-RCP conformance gaps this document previously tracked as open +(Table 30 Row-2 wiring across all 8 endpoint types, the §13.5.1 +compound-wait comparison primitive, and the request.hpp field-level gaps +below) are now closed as a direct result — corrected in place below +rather than left as stale findings. Where a cpp-RCP file is cited below +as the reference shape for some canonical choice, that citation now also +reflects cpp-RCP's substantially larger/more-conformant post-rewrite +content (e.g. its `.fusa-reqs.json` requirement catalog grew from 412 to +1133 entries during the rewrite, and it gained real MC/DC coverage and +TLA+ CI automation it previously lacked entirely) — not re-verified +line-by-line against every canonical choice in this document as part of +this update, only the specific items called out below. + ## Module lexicon One name per protocol concern, used consistently in this document and @@ -85,16 +102,14 @@ This table covers all three of Table 30's endpoint-type rows: SPI's own channel-select row, the GPIO/PWM_OUT write-combining row, and the shared "Row 2" plain-request rule (`{ADC, PWM_IN, I2C, LIN, CAN, UART, ISELED, MDIO}`, `evt[2:0]` must be `000b`). A repo can be conformant for the first -two rows while having no implementation at all for Row 2 — that is exactly -cpp-RCP's and rust-RCP's current state, corrected below (previously this -table wrongly marked both "conformant"). +two rows while having no implementation at all for Row 2. | Repo | SPI row | GPIO/PWM_OUT row | Row 2 (8 endpoint types) | |---|---|---|---| -| c-RCP | conformant (`rcp_ep_spi_channel_valid()`) | conformant (`rcp_ep_gpio_write_semantics_valid()`) | **conformant (reference implementation, fixed this pass) — `rcp_acf_evt_row2_is_plain()`, called consistently from all 8 endpoint files** | +| c-RCP | conformant (`rcp_ep_spi_channel_valid()`) | conformant (`rcp_ep_gpio_write_semantics_valid()`) | conformant (reference implementation) — `rcp_acf_evt_row2_is_plain()`, called consistently from all 8 endpoint files | | go-RCP | conformant | conformant | conformant (`acf/evt.go`) | -| cpp-RCP | conformant (`spi::channel_of`) | conformant (`endpoint::WriteSemantics`, called into by e.g. `gpio.hpp`'s `apply_gpio_write`) | **not implemented — none of the 8 Row-2 endpoint types (`can.hpp`, `lin.hpp`, `adc.hpp`, `i2c.hpp`, `uart.hpp`, `iseled.hpp`, `mdio.hpp`, plus PWM_IN) have any ACF-header evt decode or dispatch wiring yet; `mock::Server::dispatch()` only routes EP0/GPIO/SPI. Greenfield work, not a dedup refactor.** | -| rust-RCP | conformant (`SpiChannelSelect::from_sub_opcode`) | conformant (`GpioWriteSemantics::from_sub_opcode`) | **not implemented — `evtgroup.rs`'s `classify_evt_sub_opcode` is a stub that always returns `None` by design (its own doc comment says so); none of `can.rs`/`lin.rs`/`adc.rs`/`i2c.rs`/`uart.rs`/`iseled.rs`/`mdio.rs`/`pwm.rs` (PWM_IN) read `evt` at all. Greenfield work, not a dedup refactor.** | +| cpp-RCP | conformant (`spi::channel_of`) | conformant (`endpoint::WriteSemantics`, called into by e.g. `gpio.hpp`'s `apply_gpio_write`) | **conformant (2026-08-22, cpp-RCP v3.0.0's ground-up rewrite from c-RCP)** — all 8 Row-2 endpoint types (`can.hpp`, `lin.hpp`, `adc.hpp`, `i2c.hpp`, `uart.hpp`, `iseled.hpp`, `mdio.hpp`, `pwm.hpp`'s PWM_IN path) now have real ACF-header evt decode and dispatch wiring, verified directly against the current codebase (this table previously said "not implemented" here, correct as of the prior audit but now stale). | +| rust-RCP | conformant (`SpiChannelSelect::from_sub_opcode`) | conformant (`GpioWriteSemantics::from_sub_opcode`) | conformant (`evtgroup.rs`, wired into all 8 endpoint modules) | **c-RCP finding, resolved.** Table 30's endpoint-type row `{ADC, PWM_IN, I2C, LIN, CAN, UART, ISELED, MDIO}` allows `evt[2:0] = @@ -185,10 +200,10 @@ Current status per repo: |---|---| | c-RCP | **conformant (reference implementation, c-RCP#156/#157)** | | go-RCP | not yet implemented | -| cpp-RCP | not yet implemented | +| cpp-RCP | **conformant (2026-08-22, cpp-RCP v3.0.0's ground-up rewrite from c-RCP)** — `compound_wait_evt_valid()`/`compound_wait_match()` in `acf.hpp`, the same 8-mode primitive shape as c-RCP's reference, with `evt` threaded through `request.hpp`'s compound-wait encode/decode and real per-request dispatch (this table previously said "not yet implemented" here, correct as of the prior audit but now stale). | | rust-RCP | not yet implemented | -Porting this to the other three repos is the next item of work: each +Porting this to the other two repos is the next item of work: each needs (a) the generic 8-mode primitive in its own wire/ACF layer, (b) `evt` threaded through that repo's own compound-wait encode/decode surface, and (c) real per-request dispatch wiring in whatever module @@ -251,26 +266,34 @@ it is not staged in a `.fusa-reqs-pending.json` entry — it needs a direct fix (new type or width correction) in a future session. **cpp-RCP and rust-RCP field-level gaps beneath their correct module -shape (found 2026-08-07):** both repos are correctly cited above as the -*reference shape* for module unification — that assessment stands. But a -closer, field-by-field read against TC18 §11.2.2 found both have real -gaps underneath that good architecture, now staged in each repo's -`.fusa-reqs-pending.json` (see the schema-6 pending-reqs mechanism -above): - -- **cpp-RCP**: the opcode/routing/state-machine layer - (`RequestTypeOpcode`'s 8 real TC18 opcodes including 0x06 - ClearNonSafestate, `mtv=false` repurposing, `expected_start_state`) is - correctly designed — not the same class of defect as go-RCP's - conditional-envelope layer. But three field-level behaviors are - genuinely absent (the real TC18 field names appear only in comments, - never as real fields/variables/consumed values anywhere in `include/` - or `src/`): Compound's `cmp_exec_delay`/`cmp_repetitions`, Triggered's - `trigger_source_ep`/`trigger_signal_nr`/`trigger_threshold`, and - Timed's `presentation_time` (no scheduling/dispatch logic exists - anywhere — a Timed request today has no distinguishing runtime - behavior from a standard one). -- **rust-RCP**: notably more complete than cpp-RCP — `cmp_exec_delay`/ +shape (found 2026-08-07; cpp-RCP re-verified 2026-08-22 after its +ground-up v3.0.0 rewrite from c-RCP — the original finding below is now +stale for cpp-RCP, corrected in place):** both repos are correctly cited +above as the *reference shape* for module unification — that assessment +stands. + +- **cpp-RCP (resolved, 2026-08-22)**: the specific field-level gaps this + section previously described — Compound's `cmp_exec_delay`/ + `cmp_repetitions`, Triggered's `trigger_source_ep`/`trigger_signal_nr`/ + `trigger_threshold`, and Timed's `presentation_time` — are no longer + absent; all are real fields with real scheduling/dispatch logic in the + current `request.hpp` (`CompoundStep::exec_delay`/`repeat_count`, + `TriggeredStep::trigger_source_ep`/`trigger_signal_nr`/ + `trigger_threshold` plus real occurrence-count matching, and + `TimedRequest::presentation_time` with real TSCF-admission gating), + verified directly against the codebase, not just its comments. A + smaller, different set of real gaps remains, honestly staged in + cpp-RCP's own `.fusa-reqs-pending.json` as of 2026-08-22 — + `REQ-CMP-008`/`REQ-CMP-009` (encode functions take already-decided + values as plain parameters/forwarded payload rather than deriving them + from a richer request-state type), `REQ-TRIG-003` (same class, for + Triggered), `REQ-CHAIN-003`/`REQ-CHAIN-008` (payload forwarding; + `chained_predecessor` typed as `std::optional` rather than a + richer link type), and `REQ-TIMED-012`/`REQ-TIMED-013` (TSCF-admission + primitives exist but a specific dispatch-wiring path is incomplete) — + narrower shape/wiring items, not the field-presence absence this + section originally found. +- **rust-RCP**: notably more complete than cpp-RCP was — `cmp_exec_delay`/ `cmpw_exec_delay`, `trigger_exec_delay`, and `trigger_repetitions` (`TriggerRepeatCount`/`is_trigger_repeat_exhausted`) are all real, well-tested implementations already. Two gaps remain: Compound/