Skip to content

Route standalone rigctld through managed transmit - #3163

Open
morozsm wants to merge 1 commit into
mainfrom
codex/standalone-rigctld-managed-tx
Open

Route standalone rigctld through managed transmit#3163
morozsm wants to merge 1 commit into
mainfrom
codex/standalone-rigctld-managed-tx

Conversation

@morozsm

@morozsm morozsm commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Outcome

Standalone rigplane serve now installs and reuses the same production ManagedTxComposition as Web/station. Before the listener opens, the server seeds its single fallback observation generation, binds and validates the exact installed composition against that StateStore, then constructs one handler-local CommandService using the same store and injects the exact authority.

Managed non-PTT writes now enter ManagedTxAuthority.admit_managed_write before overlays/provider delivery. Observed RF no longer admits or blocks managed frequency/mode/VFO/split/relay writes. The compatible unmanaged SDK constructor retains the legacy interlock until its separate retirement; writable unmanaged startup emits one warning, while read-only startup stays silent.

Wire behavior is unchanged: T 1 is owner PTT down; same-owner T 0 is PTT up; foreign/stale T 0 remains RPRT 0 without a write. No ForceOff/TRANSMIT/TOT wire extension, second authority, fence, runner, watchdog, or timer was added. RigctldServer.stop() does not own composition/provider shutdown; the existing CLI session remains the sole ordered shutdown owner.

Search before write

Searched CLI composition branches, every RigctldServer construction, rigctld set_ptt ingress/release paths, managed-write classification/admission, external rigctld-client actuation, StateStore generation/bootstrap, and existing disconnect/wire tests before editing. The external client remains the canonical T 1/urgent T 0 actuator and is unchanged.

TDD and focused evidence

Clean test-only worktree at exact base 893af0f08230bb36a2b8d162dea4cba0e3171610 produced behavior-specific RED:

  • serve exact-composition node: installed composition was None;
  • standalone composition nodes: no composition constructor branch;
  • rejected managed write returned RPRT 0 and never called authority;
  • observed TX/UNKNOWN managed writes never called authority;
  • writable unmanaged warning was absent.

Current head focused non-socket GREEN: 20 passed, 2 deselected (the two deselected tests are real-loopback-socket tests reserved for natural Mini CI). Ruff check PASS; Ruff format check PASS. Strict mypy reports the same 9 pre-existing errors on base and head, with only shifted line numbers.

Mutation discriminators captured:

  • remove composition from serve -> test_serve_passes_the_exact_preconnect_composition_to_cmd_serve fails;
  • open listener early -> test_standalone_binds_exact_store_before_listener_and_uses_local_service fails with listener first;
  • bind before fallback seed -> same node fails provider-current validation;
  • remove admit_managed_write -> test_rejected_managed_write_never_reaches_overlay_or_provider fails OK vs ERJCTED;
  • restore observed-RF DEFER seat -> test_managed_defer_family_has_no_observed_rf_seat fails;
  • restore observed-RF BLOCK seat -> test_managed_authority_is_the_only_tuner_gate fails ERJCTED;
  • remove identity check -> test_composition_identity_mismatch_fails_before_listener fails (no RuntimeError);
  • remove warning -> writable case of test_unmanaged_warning_boundary fails.

The dangerous T0 -> ForceOff mutation was not reintroduced into production source after the safety guard rejected it; the existing discriminator is test_a_declined_unkey_reports_ok_and_writes_nothing. Disconnect release remains pinned by the existing six-path test_every_way_a_session_ends_hands_the_lease_back_exactly_once; both run in natural Mini CI.

Mechanism audit

Cardinality on this head: one production ManagedTxComposition constructor in CLI, one ManagedTxAuthority constructor inside composition, one managed-write policy owner and one rigctld admission call. The old rigctld key-down backstop and raw Radio.set_ptt remain reachable only through the explicitly compatible unmanaged branch. No managed path added a second timer, resolver, shutdown owner, or direct radio PTT call.

Scope and verification boundary

Exactly 6 files, 529 insertions / 20 deletions. No Web/frontend/composition/StateStore/reconnect/backend-client edits. No hardware or TX was used. Full/quick is not run locally; natural PR CI on the Mini is the required gate. Independent exact-head review and green exact-head CI remain required before merge.

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