Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions docs/automation-bridge.md
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,15 @@ used by the stacked trace renderer.
- `kiwiFftTraceFloorDbm` versus `kiwiDisplayFloorDbm` — distinguishes the FFT
trace floor used by 3D placement from the waterfall color floor.

`get meters` additionally reports `temperature` and `voltage` observations with
`status`, `value`, `unit` (when declared), and `ageMs`. Unsupported, never-fed, and stale vitals
have a null value; a fresh zero is still a real reading. The legacy `paTemp` and
`supplyVolts` scalars use those same qualified values. `alc` retains the native
unit and age; `swAlc` is a legacy conversion and must not be labeled physical
Icom dBFS. `txtest twotone` refuses Icom: its current TUNE backend generates one
sine wave and has no two-tone selection route. Ordinary TUNE remains available
in supported modes.

### `radiocert persist`

`radiocert persist` returns a **read-only persistence snapshot**, also allowed in
Expand All @@ -1061,6 +1070,22 @@ average (with its known flag), waterfall rate (legacy name
`waterfallLineDuration`, **1..100, not milliseconds**, -1 unknown), center-known,
WNB and available RX antennas.

For Icom, `backendDiagnostics.result` also includes the read-only `civ scheduler`
payload. Its `stateFreshness` separates `transportConnected`, CI-V `identified`,
and `trackedStateReady`. The six tracked fields are selected-VFO frequency,
mode/DATA/filter tuple (decimal wire codes), squelch percent, AGC code, RF power
percent, and PTT. Each has a last decoded value, age, semantic key and status:
`never-confirmed`, `pending`, `previous-context`, `stale`, or `confirmed`.
Only validated receive publications refresh these fields, including unchanged
replies. A setter or generic ACK cannot confirm them. Frequency/mode/filter
changes and outgoing VFO select/exchange invalidate the prior context; session
changes invalidate old observations. The diagnostic age budget is 5000 ms and
does not change polling or authorize TX. Fields outside this list, including
filter width and AGC threshold/off level, carry no freshness claim. CI-V has no
transaction identifiers, so delayed unsolicited data cannot prove physical
intent correlation or an unobserved front-panel VFO change with identical mode
and frequency.

The snapshot explicitly identifies its evidence as **client model and
presentation**. Some model setters update optimistically. Equality here alone
is neither independent wire readback nor proof of a durable disk commit.
Expand Down Expand Up @@ -3578,6 +3603,16 @@ producer in isolation:
"pendingPttIntent":false}}
```

The scheduler also returns up to 128 `transactions`, `firstRetainedEventId`,
`lastRetainedEventId`, and `stateFreshness` (see Persist above). Deduplicate
completion events by `backendInstanceId` plus `eventId`, never by semantic
`key`/`generation`/`completion`: periodic polls reuse those three fields.
Event IDs increase across ring eviction, history clears and scheduler resets.
A timeout and its eventual late reply are separate completion events. A jump
past the previously collected ID is an evidence gap, not zero missing activity.
A new backend starts a new UUID `backendInstanceId`, also present inside
`stateFreshness`; use it even when a reconnect reuses the same process and radio.

While a PTT request is awaiting confirmation the reply also carries
`"pttIntent"` (the requested state) and `"pttIntentRemainingMs"` (how much of
the bounded window is left). Suppression applies only while `pttIntent` is
Expand Down
15 changes: 14 additions & 1 deletion docs/automation/TX_TEST_PROMPT.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,16 @@ subscription path.
- Begin with the lowest authorized Tune Power percentage.
- Sample forward power, SWR, ALC, compression, voltage, current, and thermal
data that the radio actually supports. Mark unsupported meters as such.
- Reject stale ages and rail-pinned values.
- Reject stale ages and rail-pinned values. Do not substitute scalar defaults
for unsupported temperature or voltage. Report ALC in its declared native unit.
- Start the freshness deadline at the key command, including command latency.
A sample predating that command cannot qualify as this burst's telemetry.
- In CW, a zero-carrier gap deliberately nulls the displayed SWR. It can continue
only after a qualified SWR was observed in this burst, with fresh zero-watt
power and fresh SWR receive timestamps. Missing/stale telemetry and a missing
ratio with positive power still stop the run; the timing budgets are unchanged.
- Icom's current TUNE producer is a single sine wave. `txtest twotone` refuses
that family; do not record ordinary TUNE output as two-tone or IMD proof.
- Verify the actual power gauge is live only while keyed.
- Unkey immediately, then verify the gauge is zero both at the edge and after a
late in-flight response could arrive.
Expand All @@ -106,6 +115,10 @@ bypass state. The sampling window repeats the context check and uses fresh
peak SWR and every sampled meter row. Missing/unknown link state, a missing or
stale calibrated power definition, and missing/stale SWR stop the run. Unkey
is confirmed before restoring power; unknown TX flags never count as unkeyed.
For Icom, model flags alone are insufficient: the harness additionally requires
`stateFreshness.fields.ptt` to report a confirmed false value received during
that unkey observation window and younger than 500 ms. Older app builds without
this diagnostic cannot satisfy that Icom confirmation gate.

### 4. Restart proof

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ controlled regression and live before/after prove causality.

## Guarded transmit and restoration

After the fourth retention restart, one 1.6-second USB two-tone window used
After the fourth retention restart, one 1.6-second USB window requested the
bridge two-tone action. Later source review established that Icom generated a
single tone; this is not two-tone/IMD proof. That window used
7.200 MHz, ANT1, RF 3% and Tune 2%. It obtained six fresh positive forward-power
samples, peak unsmoothed calibrated **2.098 W** and SWR **1.0**, with no stop
reason. The actual forward gauge was sampled while keyed; explicit unkey
Expand Down Expand Up @@ -156,3 +158,7 @@ TX safety checks passed in the publication worktree; bridge-doc generation and
whitespace validation passed. An initial `unittest` module invocation lacked the
tools import path; direct documented script entry points completed successfully.
These are tooling checks, not new native-build or hardware-fix evidence.

The subsequent [P1 follow-up](persist-icom7300mk2-p1-followup-2026-09-08.md)
implements bounded freshness diagnostics and corrects meter/TX-test reporting.
It preserves this earlier run and its unresolved observations.
13 changes: 10 additions & 3 deletions docs/research/persist-icom7300mk2-first-run-2026-09-08.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,11 @@ also observed the actual gauge rise from zero through approximately 1.05–2.27
while keyed. Earlier windows captured producer/model meters plus pre/post
widgets; they did not sample the actual widget throughout keying.

The Tune waveform selection can persist after two-tone, so later DIGL/RTTY
TUNE button results must not be labeled proven single-tone tests. They show
P1 source review corrected the waveform interpretation: Icom's `setTune()`
generates one sine wave; the Flex `tune_mode` command has no Icom route. The rows
labeled Two-tone above describe the requested bridge action, not a proven
waveform. Their RF observations remain valid, but none proves two-tone/IMD.
The updated bridge refuses that misleading Icom request. These windows show
the requested TUNE path produced reported RF in those radio modes.

Both DATA and non-DATA modulation sources already replied LAN (`1a 05 00 85 05`
Expand Down Expand Up @@ -205,7 +208,11 @@ are also retained. These are harness findings, not successful radio tests.
Diagnostic logging was reset, the final client exited normally, and the radio
lock was released. Final state: **one slice, transmitting false**.

## Concrete next work
## Concrete next work recorded at the first run

The [P1 follow-up](persist-icom7300mk2-p1-followup-2026-09-08.md) now implements
bounded freshness/event diagnostics and corrects the TX/meter harness. The list
below records the original findings; remaining limits are updated in that report.

1. Add a stable transaction event sequence and bounded export/coverage counters
so queue/response distributions can be measured without duplicate loss.
Expand Down
114 changes: 114 additions & 0 deletions docs/research/persist-icom7300mk2-p1-followup-2026-09-08.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# IC-7300MK2 Persist P1 follow-up

This follow-up to merged #5500 addresses the diagnostic and test-process P1
items from the [expanded run](persist-icom7300mk2-expanded-run-2026-09-08.md).
The four earlier persistence repairs belong to #5514. This change does not
claim to repair every intermittent radio symptom or complete the entire Icom
control matrix.

## Changes and observed outcomes

| Area | Repair / evidence | Remaining boundary |
|---|---|---|
| State freshness | Accepted frequency, mode/data/filter tuple, SQL, AGC, RF-power and PTT publications carry confirmation age and session/context identity. Pending writes and startup defaults cannot imply readiness. Unchanged valid replies refresh age. | Six tracked fields only. Filter width/PBT, unselected VFO, meters and other controls are not included in the readiness flag. Readiness is diagnostic, not permission to transmit. |
| Transaction history | Monotonic event IDs survive scheduler reset; a backend UUID separates different instances. The bounded export includes retained endpoints for collector gap detection. | Only 128 retained events. Deduplicate by backend UUID/event ID; initial history is not newly observed traffic. CI-V has no transaction IDs, so delayed unsolicited replies cannot prove physical-intent correlation. |
| TX safety/reporting | The first-sample deadline starts before the key command. Prior-burst samples cannot qualify. Fresh zero-carrier CW gaps may omit the SWR ratio only after a valid ratio in the same burst, with both power and SWR telemetry under 500 ms. Icom unkey requires a fresh accepted PTT-off reply as well as model flags. | The 0.9-second initial deadline, 500 ms safety freshness and measured-watt limit are unchanged. Missing replies, positive power without SWR, and bursts that never establish SWR still stop. |
| Waveform labeling | Icom `setTune()` feeds a single sine; Flex `tune_mode` has no Icom route. The bridge now refuses `txtest twotone` on Icom before keying. Earlier reports are corrected. | Actual Icom two-tone/IMD generation remains unsupported. Ordinary TUNE remains a single-tone path. |
| Meter provenance | Undefined or never-fed PA temperature is null, not zero. Low-rate vitals have status, unit and age. The TX harness reports native ALC units rather than substituting legacy `swAlc` dBFS. | Native radio meters and widget observations are not independent RF instrument measurements. |

No poll cadence, queue priority, retry count, audio pipeline or default radio
setting was changed. A mode/frequency publication change and an outgoing VFO
select/exchange invalidate tracked context; an unobserved physical VFO change
with identical reported values cannot be detected by this mechanism.

## Live evidence

The operator authorized an IC-7300MK2 on a dummy load at ANT1, 7.200 MHz, all
modes, maximum 10 W. The radio lock was acquired before connecting. Test clients
used an isolated profile, session-only credentials, a three-second TX watchdog
and a five-percent TX control ceiling. No ATU cycle or VOX enable was performed.
Percentages below are setpoints; watts are the radio's unsmoothed calibrated
forward-power readings.

| Trial | Outcome |
|---|---|
| CW text, 2% RF | Repeat established 2.797 W and SWR 1.0. One earlier follow-up stopped during a zero-carrier character gap: power and SWR telemetry were fresh, but the model intentionally hid the ratio at zero power. The corrected gap handling completed the repeat. |
| AM TUNE, 2% | Radio returned fresh zero forward-power data and no usable SWR; the guard stopped. This establishes a meter-reported zero, not an independent measurement of zero RF or receiver sensitivity. |
| AM TUNE, 5% | Fresh positive output: 1.748 W in the development repeat and 1.399 W in the final repeat, SWR 1.0. |
| DIGU TUNE, 5% | Two first-TX-after-process-start trials established 6.993 W and SWR 1.0. The older intermittent initial DIGU failure was not reproduced. |
| Unkey | Explicit unkey succeeded after each burst; actual forward-power gauges read zero immediately and 0.7 seconds later. Final CW/AM repeats also used the stricter accepted-PTT-off confirmation. |
| Actual meter surfaces | Forward power, SWR and ALC gauges were sampled. Visible supply voltage was 14.894737 V, displayed +14.89 V, matching its native observation (263 ms age). PA-temperature and fan widgets were hidden; temperature was null/unsupported. |
| Process persistence | Manual SQL 27 and AGC Fast agreed in model and actual RX controls after normal Quit/new-process startup. Tracked readiness arrived at 2.513 seconds initially and 2.319 seconds after restart. |
| Final RX reconnect | The final backend-UUID build reached readiness at 2.418 and 2.357 seconds across same-process reconnect. Session generation changed from 2 to 5; the same backend UUID remained, and retained event IDs advanced from 1–66 to 202–267. A socket-free test separately verifies distinct backend-instance UUIDs. |

These repeats establish the exercised paths, not a deterministic cause or fix
for the original missing-CW-power report or the original first-DIGU stop. Those
historical observations remain open. The unsupported two-tone label is a
confirmed client defect; the zero-carrier-gap stop is a confirmed harness defect.
No IC-705 or IC-9700 hardware was exercised.

## Freshness baseline

A no-action 12-second window retained 53 snapshots, all with the six tracked
fields ready. It collected 481 distinct transaction events: 128 initial history
entries plus 353 subsequent events, with no collector gaps.

| Accepted field age (ms) | Median | p95 | Maximum |
|---|---:|---:|---:|
| AGC | 1471 | 2976 | 3217 |
| Frequency | 1050 | 2233 | 2618 |
| Mode/data/filter tuple | 983 | 2166 | 2484 |
| PTT | 132 | 234 | 250 |
| RF power | 1567 | 2983 | 3352 |
| SQL | 1418 | 2983 | 3448 |

These are ages observed by the collector, not wire round-trip latency or
physical front-panel-to-display latency. They provide a baseline before any
scheduler optimization. Five seconds is the diagnostic readiness budget;
TX safety continues to require the tighter 500 ms meter/PTT evidence.

## Restoration and test-process lessons

The final comparison matched the settled original snapshot: 18 slice fields
and 12 transmit fields, including 7.224540 MHz LSB, Manual SQL 14 and AGC Med.
RF 100% and Tune 10% were restored only in a verified TX-disabled client.
ANT1 remained selected, tuner bypassed and VOX off. PTT-off was freshly
confirmed, the app quit normally, and the radio lock was released.

An early startup snapshot showed fallback filter edges -3300…-300 Hz, whereas
the settled original was -3000…0 Hz. No filter recall was used to overwrite that
settled state. Six-field readiness must not be presented as full filter-width
readiness. During cleanup, setting AGC before a mode change was superseded by
the radio's mode-specific recall; restoration was corrected after each mode
confirmation (AM Slow, DIGU Med, LSB Med). Intermediate mismatches were retained.
The earlier expanded run's uncaptured hidden filter-bank definitions remain a
restoration limitation; this follow-up does not recover those missing originals.

## Build and evidence attribution

Live TX evidence used local base `7e6c4805481c73ae814210c83c15edd4c8721e8e`
with the P1 changes, executable SHA-256
`d25c117c4716d013ba35bbe4c2da4532e5dd888a04345ae6dae008259d8361b3`.
The subsequent UUID addition was checked in RX-only reconnects using executable
SHA-256 `542df16d0fd6e1e2e724af31e5e114bd9df6fbe94eebc2cbaca14cfc79596176`.
The new PR is based on refreshed main after #5500 merged; integration build and
local test evidence are distinct: base `ac92489b`, modified tree, full macOS
build passed with `cmake --build build -j22`; eight selected headless CTests
passed in 1.97 seconds, including 17 TX safety cases. Integration executable
SHA-256 is `b1cdf9d88fbe6e46560a544ada6d324afaea6ec53484f4cb62e8b4f6674046bd`.
Engine-boundary, test-registration, bridge-doc, touchpoint-manifest and frozen
CI-gate checks passed locally. No post-transplant TX
or full Icom matrix is claimed. Publication review additionally tightened
aggregate sample qualification to the same post-key/500 ms rule; this has
socket-free coverage and was not a further live TX trial.

Eight focused headless CTest selections passed before the transplant. Mutation
checks demonstrated failures when event IDs were made constant, context
invalidation was disabled, and the Icom two-tone refusal was removed; guards
were restored before the passing run. The new bridge regression injects an
inert backend and invokes the real dispatcher without sockets or firmware peers.

Local evidence sets are `persist-p1-live`, `persist-p1-final` and
`persist-p1-identity`. Ordered observations, source scripts, snapshots, widget
samples, raw replies and hashes remain local. Credentials, network/session
identifiers, profiles and raw artifacts are not included in this report.
Loading
Loading