Skip to content

rewrite(phase1): port request/sequencer/scheduler from c-RCP's RC5-conformant reference - #132

Merged
SoundMatt merged 1 commit into
rewrite/v3-from-c-rcpfrom
phase1/request-sequencer-scheduler
Aug 21, 2026
Merged

SoundMatt merged 1 commit into
rewrite/v3-from-c-rcpfrom
phase1/request-sequencer-scheduler

Conversation

@SoundMatt

Copy link
Copy Markdown
Owner

Part of the v3.0.0 ground-up rewrite (#129, ROADMAP.md Phase 17). Third and final Phase 1 module: the conditional-request layer (compound, compound-wait, triggered, chained, timed, cancellation) plus the shared sequencer/scheduler state c-RCP keeps as 3 separate modules — kept in cpp-RCP's existing single-module unification (request.hpp already did this better than c-RCP's own current split).

Real content deltas found and fixed

  • Fixed cpp-RCP issue cs-bit polarity inverted in compound_wait_check_of() and should_execute_chained() #58 (cs-bit polarity inverted) as part of this port, confirmed against c-RCP's rcp_chained_advance(): was cs || !predecessor_errored (cs=true never aborted anything regardless of outcome), now !cs || !predecessor_errored.
  • compound_wait_check_of()/CompoundWaitCheck had no basis in c-RCP — traced through rcp_compound_encode_request()/_decode_request(), cs is hardcoded to 0 and never surfaced for compound/compound-wait. Removed; the real comparison-mode selector is the ACF header's evt[2:0] (from the acf/avtp port), now exposed via CompoundRequest::evt_op.
  • cancel_single() collapsed two distinct c-RCP outcomes (NOT_FOUND vs NOT_CANCELLABLE) into one — split, added RequestErrc::request_not_cancellable.
  • SequencerTable::try_advance's '+1 wrapping' model was wrong — replaced with an explicit next_state + separate guard/start-condition predicates, matching c-RCP's rcp_compound_advance_guard()/rcp_compound_start_condition_met().

Also newly ported: structured wire sub-fields + encode/decode for every request kind, reserved-octet/evt/hs/cs wire validation, TriggeredRuntime, wraparound-safe timed admission, frame_timing_consistent.

Fixed-capacity

RequestLedger::records_: unconditional-push_back std::vector → BoundedVector<RequestRecord, 64>. c-RCP has no ledger to port a bound from (pure-function library) — this port's own decision. Chose 64, not 256 (the full transaction_num range): at 256/256 every id is already a collision, making the capacity check unreachable. Mutation-tested.

Not ported, by design

c-RCP's positional chain model — cpp-RCP's existing predecessor/successor graph is strictly more capable.

Left as TODO(phase1-followup)

REQ-SEQ-013/014's per-sequencer owner + access control (needs regmap.hpp storage, out of scope); two convenience-wrapper functions (composable today from existing primitives).

12 → 135 test cases, 610 assertions.

Verified

Full tree rebuilds clean (221/221 targets, incl. the merged fragment/respqueue), 55/55 ctest suites pass (100%) — independently re-verified from a fresh build. No call sites outside request.hpp/test_request.cpp required changes.

Tracked at #129 — completes Phase 1.

…nformant reference

Part of the v3.0.0 ground-up rewrite (cpp-RCP #129, ROADMAP.md Phase 17),
branch rewrite/v3-from-c-rcp. Third and final Phase 1 module: the
conditional-request layer (compound, compound-wait, triggered, chained,
timed, cancellation) plus the shared sequencer/scheduler state c-RCP
keeps as 3 separate modules -- kept in cpp-RCP's existing single-module
unification (request.hpp already did this better than c-RCP's own
current split).

Real content deltas found and fixed against c-RCP's request.c/
request_sequencer.c/scheduler.c:

- Fixed cpp-RCP issue #58 (cs-bit polarity inverted in
  compound_wait_check_of()/should_execute_chained()) as part of this
  port, confirmed against c-RCP's rcp_chained_advance(): was
  'cs || !predecessor_errored' (cs=true never aborted anything
  regardless of outcome), now '!cs || !predecessor_errored', matching
  RCP_CHAINED_CS_CONTINUE_ON_ERROR(0)/ABORT_ON_ERROR(1).
- compound_wait_check_of()/CompoundWaitCheck had no basis in c-RCP --
  traced through rcp_compound_encode_request()/_decode_request(), cs is
  hardcoded to 0 and never surfaced for compound/compound-wait. Removed;
  the real comparison-mode selector is the ACF header's evt[2:0]
  (acf::compound_wait_evt_valid/compound_wait_match, from the acf/avtp
  port), now exposed via CompoundRequest's evt_op field.
- cancel_single() collapsed two distinct c-RCP outcomes
  (NOT_FOUND vs NOT_CANCELLABLE) into one. Added
  RequestErrc::request_not_cancellable, split the cases.
- SequencerTable::try_advance's '+1 wrapping' model was wrong --
  replaced with CompoundStep + advance_guard()/start_condition_met()/
  apply_next_state()/tick()/wait_tick(), matching c-RCP's explicit
  next_state field and the guard/start-condition distinction
  (rcp_compound_advance_guard() vs rcp_compound_start_condition_met()).

Also newly ported (behavior c-RCP has that cpp-RCP never had):
structured wire sub-fields + encode/decode for every request kind,
reserved-octet and evt/hs/cs wire validation, TriggeredRuntime,
wraparound-safe timed admission mapped onto acf::WireErrorCode, and
frame_timing_consistent.

Fixed-capacity: RequestLedger::records_ (unconditional-push_back
std::vector) -> BoundedVector<RequestRecord, 64>. c-RCP has no ledger
to port a bound from (its request store is a pure-function library) --
this is this port's own decision. Chose 64, not 256 (the full
transaction_num range): at 256/256 every possible id is already a
collision, making the capacity check unreachable. Mutation-tested
(disabled the full() guard, confirmed the new overflow test failed,
restored).

Not ported, by design (noted in-header, not a follow-up TODO): c-RCP's
positional (has_predecessor/chain_position) chain model -- cpp-RCP's
existing predecessor/successor graph in RequestLedger is strictly more
capable and stays as the one chained-cascade model.

Left as // TODO(phase1-followup): REQ-SEQ-013/014's per-sequencer owner
+ fail-closed access control (needs regmap.hpp storage, out of this
pass's request.hpp-only scope); rcp_compound_peek_request_type()/
rcp_timed_encode_request_tscf() convenience wrappers (composable today
from existing acf/avtp primitives).

12 TEST_CASEs (REQ-SEQ-only) -> 135 TEST_CASEs / 610 assertions,
covering REQ-CMP/TRIG/CHAIN/TIMED/CANCEL/SEQ/SCHED.

Verified: full tree rebuilds clean (221/221 targets, incl. the just-
merged fragment/respqueue), 55/55 ctest suites pass (100%) --
independently re-verified from a fresh build, not just the porting
agent's own report. No call sites outside request.hpp/test_request.cpp
required changes (e2e.hpp/watchdog.hpp/authz.hpp all kept their exact
prior signatures against the new API).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Matt <47545907+SoundMatt@users.noreply.github.com>
@SoundMatt
SoundMatt merged commit e56fd7a into rewrite/v3-from-c-rcp Aug 21, 2026
22 checks passed
@SoundMatt
SoundMatt deleted the phase1/request-sequencer-scheduler branch August 21, 2026 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant