Summary
AE's TCI server sends ready; after only the capability block (8 messages), then continues with the full per-channel state dump — 29+ settings messages after ready;. Per the TCI spec, ready; marks the end of the init burst: a client may legitimately build its complete state model at that moment and treat everything after as runtime updates. A spec-faithful client connecting to AE therefore initializes with default samplerate / stream format / VFO / mode state and may misbehave in ways that look like client bugs.
Reported by Yuri Pavlov, UT4LW (author of SDC — Software Defined Connectors) in Discord #bug-reports (2026-06-09) with a wire capture; reproduced and quantified below.
Evidence
Reporter's capture (condensed) — ready; arrives 9th, before any channel state:
vfo_limits … modulations_list, protocol:ExpertSDR3,1.5;
ready; � end-of-init marker, sent here
drive … trx:0,false … audio_samplerate:48000 … iq_samplerate:48000;
audio_start; start;
Live reproduction against current main (2026-06-09, FLEX-6700, fresh connect):
- 40-message init burst (ending
iq_samplerate, audio_start, start)
ready; at index 8
- 31 messages / 29 settings after
ready; — vfo, modulation, rx_enable, rx_filter_band, rit/xit, split_enable, lock, sql, agc_mode, NB/NR/ANF/APF, tx_enable, drive, tune_drive, mic_level, volume, all audio/iq stream parameters…
Expected per spec: ready; after the last setting (i.e. after iq_samplerate;), before the audio_start;/start; lifecycle events.
Impact
- Clients that latch state at
ready; (the spec-sanctioned pattern) build their model from the 8 capability lines only: wrong/default audio samplerate, stream format, channel count, VFO, mode. Plausibly explains a family of "client X initializes weird against AE" reports.
- Clients that send their own commands immediately on
ready; (also legitimate) currently race the remainder of AE's dump — their early writes can be silently clobbered by the in-flight burst. The current ordering creates a write-race, not just a stale read.
- Source-confirmed synchronizing client — JTDX. Its
TCITransceiver maps ready to a tci_done1 signal that quits a blocking QEventLoop raced against a single-shot timer; its init "sleeps" (mysleep1/2/3) are these same wait-loops, and it latches pre-ready state (requested_rx_frequency_ while !tci_Ready). A misplaced ready; cuts those waits short, so JTDX's own init commands interleave with the server's still-in-flight dump, and trailing dump messages then arrive looking like fresh runtime updates (a plausible mechanism for the recurring "mode snaps back to DIGU/LSB after connect" class of reports). Server greeting order directly steers this client's init state machine.
- wsjt-x-improved ships TCI test builds (v2.7.1+, same ecosystem lineage) — recommend including it in the fix validation matrix.
- Survey of order-agnostic clients (apply-as-arrives, never latch): TCI Monitor, aether-pad, the Ulanzi Studio plugin, RF2K-S GUI — all unaffected today and unaffected by the fix. The ecosystem partly tolerates the bug, which is why it has survived; the cost lands on spec-faithful clients that honour
ready;.
Fix considerations (the devil is in the ordering and timers)
- Placement:
ready; belongs after the final setting (iq_samplerate;) and before audio_start;/start;, matching the ExpertSDR3 reference sequence.
- State-completeness gate: if any per-channel state in the dump is populated asynchronously from radio sync, "move the ready; line" is not enough — the send must be gated on the init dump actually being complete, or the bug just shrinks instead of dying.
- Behavioural validation, not just connects: clients that act on
ready; will now act ~30 messages later. Each major client's resulting state (samplerate, mode, VFO, TX state) should be compared pre/post-fix, not just "it still connects". Suggested matrix: WSJT-X-improved / JTDX TCI, SDC, TCI Monitor, plus the order-agnostic set above as controls.
Regression test already exists
connect-greeting-order — a scenario in G0JKN's tci-probe harness (Node-RED-based behavioural test rig) opens a fresh connection, captures the ordered burst (analysis window cut at start; so runtime telemetry is excluded), and asserts: exactly one ready;, nothing after it except stream-lifecycle events. It is deliberately red against current main (violations_count: 29) and will flip green when the ordering is fixed, guarding it from then on. Happy to run it against any candidate branch on request.
Reported via Discord #bug-reports by Yuri UT4LW; triage, reproduction, client-source audit and regression scenario by Nigel G0JKN (with Claude).
Summary
AE's TCI server sends
ready;after only the capability block (8 messages), then continues with the full per-channel state dump — 29+ settings messages afterready;. Per the TCI spec,ready;marks the end of the init burst: a client may legitimately build its complete state model at that moment and treat everything after as runtime updates. A spec-faithful client connecting to AE therefore initializes with default samplerate / stream format / VFO / mode state and may misbehave in ways that look like client bugs.Reported by Yuri Pavlov, UT4LW (author of SDC — Software Defined Connectors) in Discord #bug-reports (2026-06-09) with a wire capture; reproduced and quantified below.
Evidence
Reporter's capture (condensed) —
ready;arrives 9th, before any channel state:Live reproduction against current main (2026-06-09, FLEX-6700, fresh connect):
iq_samplerate, audio_start, start)ready;at index 8ready;— vfo, modulation, rx_enable, rx_filter_band, rit/xit, split_enable, lock, sql, agc_mode, NB/NR/ANF/APF, tx_enable, drive, tune_drive, mic_level, volume, all audio/iq stream parameters…Expected per spec:
ready;after the last setting (i.e. afteriq_samplerate;), before theaudio_start;/start;lifecycle events.Impact
ready;(the spec-sanctioned pattern) build their model from the 8 capability lines only: wrong/default audio samplerate, stream format, channel count, VFO, mode. Plausibly explains a family of "client X initializes weird against AE" reports.ready;(also legitimate) currently race the remainder of AE's dump — their early writes can be silently clobbered by the in-flight burst. The current ordering creates a write-race, not just a stale read.TCITransceivermapsreadyto atci_done1signal that quits a blockingQEventLoopraced against a single-shot timer; its init "sleeps" (mysleep1/2/3) are these same wait-loops, and it latches pre-ready state (requested_rx_frequency_while!tci_Ready). A misplacedready;cuts those waits short, so JTDX's own init commands interleave with the server's still-in-flight dump, and trailing dump messages then arrive looking like fresh runtime updates (a plausible mechanism for the recurring "mode snaps back to DIGU/LSB after connect" class of reports). Server greeting order directly steers this client's init state machine.ready;.Fix considerations (the devil is in the ordering and timers)
ready;belongs after the final setting (iq_samplerate;) and beforeaudio_start;/start;, matching the ExpertSDR3 reference sequence.ready;will now act ~30 messages later. Each major client's resulting state (samplerate, mode, VFO, TX state) should be compared pre/post-fix, not just "it still connects". Suggested matrix: WSJT-X-improved / JTDX TCI, SDC, TCI Monitor, plus the order-agnostic set above as controls.Regression test already exists
connect-greeting-order— a scenario in G0JKN's tci-probe harness (Node-RED-based behavioural test rig) opens a fresh connection, captures the ordered burst (analysis window cut atstart;so runtime telemetry is excluded), and asserts: exactly oneready;, nothing after it except stream-lifecycle events. It is deliberately red against current main (violations_count: 29) and will flip green when the ordering is fixed, guarding it from then on. Happy to run it against any candidate branch on request.Reported via Discord #bug-reports by Yuri UT4LW; triage, reproduction, client-source audit and regression scenario by Nigel G0JKN (with Claude).