Skip to content

fix(dvk): a later licensed status clears a refusal, Import re-checks admission when it starts, and transfers stay honest across disconnects. Principle VIII. - #6262

Merged
ten9876 merged 1 commit into
mainfrom
fix/dvk-review-followup
Oct 7, 2026
Merged

ten9876 merged 1 commit into
mainfrom
fix/dvk-review-followup

Conversation

@ten9876

@ten9876 ten9876 commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #6247 (#6244). A second remediation pass on #6247 produced these fixes, but #6247 merged before they could be pushed. Each fix is below. All of them are on the same DVK surface, and the a11y fold-in is a maintainer call.

  • License latch: a license feature name=digital_voice_keyer enabled=1 status clears an earlier 50004001 refusal, so a subscription activated mid-session re-enables DVK without a reconnect. The radio's licensed status outranks the earlier refusal.
  • Import admission: Import re-checks DVK admission when the upload actually starts. The menu item was enabled before a modal file dialog, and the DVK may have started recording or playing while the dialog was open.
  • Transfer flag on disconnect: DvkModel::reset() leaves the transfer flag to DvkWavTransfer, which clears it when its own transfer ends, because a transfer can outlive the connection by its timeout.
  • Busy window: it starts only after an upload that actually connected. A refused dvk upload no longer turns the next try into "file server still busy".
  • Upload port: a named port that never answers also gets the single retry on 42607, when the connect timeout fires, and an unparseable port reply is logged.
  • Export peer check: export now says why it turned a connection away ("Ignored a connection from X; waiting for the radio at Y…") instead of timing out silently. The maintainer ruled to keep the check strict to the radio's address.
  • STOP before the echo: its reply carries the pending start's slot, not −1.
  • Parser: a quoted value left open stops at the next key=" token, so it can't swallow the keys after it.
  • Screen readers: F-key name changes are announced one slot at a time. Slot loads and disconnect resets, which change many slots at once, stay silent.
  • MainWindow a11y (maintainer: fold in): the four ATU/AGC menu actions (m_swrScanAction, m_preTuneAction, m_clearAtuAction, m_agcTCalibrationMenuAction) put their disabled reason on statusTip as well as the tooltip. check_a11y on the touched GUI files goes from 4 findings to 0.

Constitution principle honored

Principle VIII. Each fix comes with a test that fails without it.

Test plan

  • Full local ctest on this branch: 671 of 672 pass. The one failure is control_receive_test, which already fails on main (CI Full Suite on 66f393220, before any DVK change); it is tracked in [full-suite] test suite failing on main (fp a1c5df639be3) #6248.
  • dvk_model_status_test (47 cases), which adds:
    • RadioModel license status clearing the refusal (only for DVK, and only enabled=1)
    • the pending-slot stop tag
    • the transfer flag surviving reset()
    • the quote-join stop
  • dvk_wav_transfer_generation_test adds three cases:
    • Import refused while the DVK is busy
    • a refused upload leaving no busy window
    • the timeout retry on 42607
  • Checked by inverting the fix: with the license clear, the quote stop or the busy-window guard removed, its test goes red, then green again once the file is restored byte-for-byte.
  • Static gates: check_engine_boundary (same 102 findings as main), check_capability_records, check_command_plane, check_test_registration, check_ci_test_gate and gen_touchpoint_manifest --check all pass.

Checklist

  • Commits are signed
  • No new flat-key AppSettings calls
  • Clean-room
  • No meter UI touched
  • No CHANGELOG entry
  • Security-relevant: this touches the export peer check (no change to its policy; it adds a visible reason)

🤖 Generated with Claude Code

…admission when it starts, and transfers stay honest across disconnects. Principle VIII.

Second remediation pass on #6247 (#6244): an automated review of
b8bac9d plus my own pass over those fixes.

- A `license feature name=digital_voice_keyer enabled=1` status now clears
  an earlier 50004001 refusal, so a subscription activated mid-session
  re-enables DVK without a reconnect.
- Import re-checks DVK admission when the upload starts. The menu was
  enabled before a modal file dialog, and the DVK may have started
  recording or playing while it was open.
- DvkModel::reset() leaves the transfer flag to DvkWavTransfer, which
  clears it when its own transfer ends; a transfer can outlive the
  connection by its timeout.
- The file server's busy window starts only after an upload that actually
  connected. A refused `dvk upload` no longer turns the next try into
  "file server still busy".
- A named upload port that never answers also gets the single 42607 retry,
  at the connect timeout; an unparseable port reply is logged.
- Export says why it turned a connection away ("Ignored a connection from
  X; waiting for the radio at Y…") instead of timing out silently.
- STOP before the radio's echo tags its reply with the pending start's
  slot, not -1.
- A quoted value left open stops at the next `key="` token, so it can no
  longer swallow the keys after it.
- F-key name changes are announced only one slot at a time; slot loads
  and disconnect resets (many slots at once) stay silent.
- The four ATU/AGC menu actions in MainWindow.cpp put their disabled
  reason on statusTip as well as the tooltip (maintainer: fold in).
  check_a11y on the PR's GUI files: 4 findings -> 0.

Maintainer rulings in this pass: admin-merge when green (the PR author is
the acting account); accept core/TxKeyingMarker.h's new includer
(DvkPanel.cpp, for the bridge TX markers); keep export strict to the
radio's address with the reason shown; keep the WAV encoder local.

Tests: dvk_model_status_test 47 (adds RadioModel licence-status clearing,
the pending-slot stop tag, the transfer flag surviving reset, and the
quote-join stop); dvk_wav_transfer_generation_test adds Import refused
while the DVK is busy, a refused upload leaving no busy window, and the
timeout retry on 42607. Each new guard was checked by inverting it: the
licence clear, the quote stop and the busy-window guard each turn their
test red. The full ctest suite passes: 667 tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ten9876
ten9876 requested a review from a team as a code owner October 7, 2026 21:52
@ten9876 ten9876 self-assigned this Oct 7, 2026
@ten9876
ten9876 merged commit bc1d7b8 into main Oct 7, 2026
7 checks passed
@ten9876
ten9876 deleted the fix/dvk-review-followup branch October 7, 2026 22:11

@ten9876 ten9876 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue fit

Partially. This follow-up to #6247/#6244 implements the intended license recovery, late Import admission, transfer ownership, connected-upload busy window, timeout fallback, export explanation, and pending STOP tag. The new shared-parser guard also truncates a valid quoted name, and the screen-reader change reduces rather than silences bulk name notifications. Reviewed head a02a4405a, merge base 5f86d2faa. The PR merged during verification at bc1d7b80 (2026-10-07 22:11:49 UTC); the parser condition is confirmed in that landed commit. This is a post-merge review; the blocking finding needs a follow-up fix.

Scope

Everything in the diff is explained by the body and DVK remediation, including the explicitly disclosed maintainer-approved MainWindow accessibility fold-in.

File/group Change Claimed? Verdict
DvkWavTransfer.{cpp,h} Late Import gate, connected-only busy window, single timeout retry, transfer diagnostics Yes In scope
DvkModel.{cpp,h}, RadioModel.cpp Clear refusal on licensed status; pending STOP slot; retain owner-controlled transfer flag Yes In scope
CommandParser.cpp Stop malformed quote joins at another quoted key Yes In scope; valid-value regression below
DvkPanel.{cpp,h} Debounce/coalesce name announcements Yes In scope; partial improvement below
MainWindow.cpp Four disabled reasons copied to statusTip Yes; maintainer fold-in In scope; verified
Two DVK tests, tests.cmake Socket-free regression assertions and isolated settings Yes In scope

The single commit's author date/message fits this remediation and its signature is verified. No new settings keys, protocol verbs, capability fields, dependencies, visual redesign, or CHANGELOG entry. The four architecture gates have identical normalized findings on base/head: 102 engine findings (zero blocking), 70 capability booleans, 368 raw commands, and a current unchanged touchpoint manifest. No new #5554 seam coupling found.

Blockers

  1. [P2] Preserve a legal quoted value whose closing token ends in = — src/core/backends/flex/CommandParser.cpp:24. For id=1 name="CQ a=" duration=1000, the closing token a=" contains =", so the new guard mistakes it for another quoted key and refuses the join. The real sanitizer accepts CQ a=; FlexLib's DVKRecordingStatus extracts the name between the quote pair, and its forbidden-character list does not prohibit =. Compiling the actual base/head parser and model against Qt 6.12 gives:
base: sent=CQ a= parsed="CQ a=" model=CQ a= duration=1000   (exit 0)
head: sent=CQ a= parsed="CQ     model=CQ    duration=1000   (exit 1)

The running head panel also reports Play slot 1: CQ after that status. Ordinary CQ Contest and CQ a=b controls remain intact. This reintroduces the name-truncation problem #6244 addressed for a valid user name; because parseKVs is shared, the same boundary affects other quoted fields.

Recognize a closing quote at the token's end before treating =" as a new key. Add the valid-name round trip to tests/dvk_model_status_test.cpp:103 beside the malformed-next-key case, keeping that existing case green. This drop-in replacement for the join block was compiled and passed both the valid CQ a= case and the existing malformed name="abc foo=1 bar="x" baz=2 case:

            if (end < tokens.size()
                && (!tokens[end].contains(QLatin1String("=\""))
                    || tokens[end].indexOf(QLatin1Char('"')) == tokens[end].size() - 1)) {
                for (qsizetype j = i + 1; j <= end; ++j) {
                    token += QLatin1Char(' ') + tokens[j];
                }
                i = end;
            }

Nits (non-blocking)

  • The bulk-notification silence claim is not established — src/gui/DvkPanel.cpp:405, src/gui/DvkPanel.cpp:420. setAccessibleName() itself emits NameChanged, as the Qt 6.12 QWidget implementation confirms. With accessibility active, a real running panel and QAccessible::installUpdateHandler filtered to F-key NameChanged events produced:
                  single rename    12-slot load    disconnect reset
merge-base panel       2                24                 24
head panel             2                12                 12

The timer halves the bulk event count, but the setters bypass its suppression and a single change still emits twice. These are observed Qt notifications, not a claim about what each native screen reader speaks. Carry an event-count test in the panel coverage and revise the implementation or the body's silence claim accordingly. The announcement queue can be disabled while the existing panel admission/theme tests still pass, so those tests do not demonstrate this behavior.

Verification and attacks

  • Built exact head and merge-base AetherSDR on Linux/Qt 6.12.0 using RelWithDebInfo -O2 -g1 and shared core. Built and ran only the focused targets: dvk_model_status_test (47 cases), dvk_wav_transfer_generation_test, dvk_panel_admission_test, and dvk_panel_theme_test: 4/4 passed. The modified transfer test is genuinely socket-free: its null model makes the deferred connect unreachable, and no download listener is started. Inert socket objects are not firmware peers.
  • Reverted seven guards individually in the scratch checkout: license clearing, malformed-quote stopping, pending STOP slot, transfer ownership on reset, connected-only busy window, late Import admission, and timeout retry. Each relevant test failed for the intended assertion. Restored original source bytes, rebuilt, and the model/transfer tests passed again. The separate valid-name probe fails only on the head. The running panel and accessibility event handler independently verified the name truncation and the notification counts above.
  • Drove only isolated offscreen demo instances with fresh settings, explicit sockets /tmp/pr6262-demo/{base,head,head2}/bridge.sock, identities pr6262-{base,head,head2}-review, and AETHER_AUTOMATION_NO_TX=1. Connected only to DEMO-0001; settled base/head2 state included {"connected":true,"serial":"DEMO-0001","sliceCount":1,"panCount":1,"transmitting":false}. menu open Tools plus dumpTree showed the three disabled SWR/ATU actions gaining a statusTip equal to their existing tooltip. For example, head Pre-tune returns {"enabled":false,"statusTip":"ATU memory controls are unavailable for this radio"}, while base has no statusTip. The first head snapshot also confirmed the disabled AGC-T reason; the settled head clears it when AGC-T becomes enabled. All owned instances were closed; no live radio or TX was used.
  • Attacked disconnect while an upload awaits its first command reply using a cold, socket-free model probe. The real onDisconnected callback drain finishes the transfer (error 0x50000063), yielding transfer=0, admission=1; the suspected stranded-admission case does not survive that lifecycle check. Reviewed stale-generation, one-retry, connected-error, strict-peer and refusal paths. Real firmware Import/Export and a foreign-peer connection were not exercised: demo does not implement licensed DVK, and this review used no live hardware or new socket test.
  • Accessibility lint reproduces 4 → 0 on the two touched GUI files. Test registration, CI-gate integrity, QSettings and whitespace checks pass. An additional automated code-review skill was unavailable; this was a manual audit with empirical checks. The full-suite claim was not independently rerun; #6248 records the disclosed pre-existing control_receive_test failure. Required CI checks passed for pull-request runs created 2026-10-07T21:52:55Z. Main subsequently advanced to this PR's squash merge at 2026-10-07T22:11:48Z, but both head and landed commit have tree 1a655602 and parent 5f86d2faa: the merge did not add untested tree changes.

Recommendation

Request changes in a follow-up. Fix and cover the valid quoted-name regression now present on main. The other seven guarded fixes survive targeted mutation, and the MainWindow accessibility reasons are verified. The remaining announcement issue is non-blocking partial remediation. The PR merged while this review was running; no merge or additional GitHub comment was performed by this review.

GitHub rejected REQUEST_CHANGES because the authenticated account is the PR author. This single review is therefore posted as COMMENT with the Request changes recommendation above.

ten9876 added a commit that referenced this pull request Oct 7, 2026
…ssibility events stand alone. Principle VIII.

Landing pass on #6264.

Parser (maintainer: keep the token rule, tighten it)
- The closing-quote test is a named predicate: a token closes the open
  value unless it opens another quoted field, and a token whose only quote
  is its last character always closes (endsWith && count == 1, which
  states what the first-quote-position test meant).
- The function comment now describes that rule, including the one shape it
  cannot tell apart: on a malformed line a lone `label="` reads as the
  close, exactly as a valid name ending in '=' does. A new test pins that
  case, and that the keys after it survive.
- The looped `=`-name assertions carry the name in their label, so a
  failure says which name broke.

Accessibility (maintainer: fold the #6262 review finding into #6264)
- setAccessibleName() and QLabel::setText() emit NameChanged themselves.
  The panel's extra coalesced F-key event and its manual status events are
  gone; F-key and row names are set only when they change.
- The status label's accessible name carries the last announced state, so
  each state change is one NameChanged and the 10 Hz elapsed-time text and
  transfer progress add none.
- dvk_panel_admission_test counts NameChanged through
  QAccessible::installUpdateHandler: a load of unchanged slots emits none
  on the F-keys, a rename emits one, a state change is one status event
  with no tick events after it, and disconnect emits one status event plus
  one for the renamed slot. Against the previous panel, three of those
  checks fail.

dvk_model_status_test 56/56, dvk_panel_admission_test 11/11,
dvk_panel_theme_test 33/33. Full ctest passes except control_receive_test,
whose fix (#6263) landed on main after this branch's base. Architecture
gates read the same on base and head.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ten9876

ten9876 commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator Author

The review's blocker (a quoted name ending in = was truncated) and its accessibility finding (the panel's extra NameChanged on top of Qt's own) are both fixed in #6264. Each comes with a test that fails without the fix: dvk_model_status_test and the NameChanged event counts in dvk_panel_admission_test.

ten9876 added a commit that referenced this pull request Oct 7, 2026
…ibility events. Principle VIII. (#6264)

## Summary

Fixes the quoted-name regression introduced by #6262, which its
[review](#6262 (review))
found, and folds in that review's accessibility finding (maintainer
call).

**Parser.** Given `id=1 name="CQ a=" duration=1000`, the parser read
`a="` as the start of another quoted field, and the DVK model displayed
`CQ`.
- A token now closes the open quoted value unless it opens another
quoted field.
- A token whose only quote is its last character always closes. So `CQ
a=`, `CQ =` and `CQ a= b=` stay whole, and the following `duration`
survives.
- One shape is genuinely ambiguous. On a malformed line, a lone
`label="` reads as the close, because it looks exactly like a valid name
ending in `=`. A test pins that case and checks that the keys after it
survive.
- The #6247 guard still holds: an unterminated value does not swallow a
later `bar="x"`.

**Accessibility.** `setAccessibleName()` and `QLabel::setText()` emit
`NameChanged` themselves, and the panel was adding events of its own on
top. The review measured 2 events for a single rename and 12–24 for a
slot load or disconnect.
- The panel no longer adds any events of its own.
- F-key and row names are set only when they change.
- The status line's accessible name holds the last announced state. Each
state change is now one event, and the 10 Hz elapsed-time text and
transfer progress add none.

## Constitution principle honored

**Principle VIII.** Each claim is backed by a test that fails without
the change. FlexLib's DVK status parsing keeps everything between the
quotes, equals signs included (Principle I).

## Validation

- **Parser:** against the merged `bc1d7b80f`, the new assertions fail 6
of 55, one per name ending in `=`. With this fix,
`dvk_model_status_test` passes 56/56, with each looped assertion naming
its value.
- **Accessibility events:** `dvk_panel_admission_test` (11/11) counts
`NameChanged` events through `QAccessible::installUpdateHandler`:
  - reloading unchanged slots: no F-key events
  - a rename: exactly one
- a state change: one status event, and nothing from the following ticks
  - a disconnect: one status event plus one for the renamed slot

  Against the previous panel, three of these fail.
- `dvk_panel_theme_test` passes 33/33.
- **Full `ctest`:** passes except `control_receive_test`. Its fix
(#6263) landed on `main` after this branch's base.
- **Static gates:** engine boundary, capability records, command plane,
touchpoint manifest, test registration and the CI gate read identically
on the merge base and the head. `check_a11y` reports nothing on
`DvkPanel`.
- **Not verified:** socket-free and offscreen only. No live radio, no
transmitting, and no real screen reader.

## Checklist

- [x] Signed commits
- [x] Socket-free regression coverage, and each guard checked by
inverting it
- [x] No new settings keys, dependencies or ratchet changes
- [x] No CHANGELOG change

Authored with OpenAI Codex. Landed with Claude Code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ten9876 added a commit that referenced this pull request Oct 12, 2026
… Principle VIII.

An audit of every page against the 106 PRs in v26.10.2, each fact checked
against the source at the release commit:

- Menu paths: AetherMap, AetherModem, Callsign Lookup and FreeDV Reporter
  are on View, and Waveforms is on Tools.
- New coverage: Windows Firewall rules and the Network Diagnostics page
  (#6289), live CW contacts (#6268), NB2 on the HL2 and ANAN-G2 (#5966),
  ANAN-G2 AGC-T and per-radio memory (#6282, #6129), HL2 state restore
  and its level changes (#6259, #6254, #5975), DVK import (#6247, #6262,
  #6251), Copy Assist from unprocessed audio (#6216), keyboard-operable
  status-bar indicators (#6267), the KPA1500 (#5905), CTR2 extensions
  and the AetherKnob (#6338), live PPM (#6082), and Icom COMP and the
  squelch scale (#6174, #6184).
- Known issues whose GitHub issues are closed are removed.
- The style guide now asks for US spelling, and every page follows it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@aethersdr-agent aethersdr-agent Bot mentioned this pull request Oct 12, 2026
2 tasks
ten9876 added a commit that referenced this pull request Oct 12, 2026
… and re-take the Stable snapshot. Principle VIII. (#6396)

## Summary

This brings the user guide (docs.aethersdr.com) up to date with
everything in v26.10.2 and re-takes the Stable snapshot so the default
site shows it. Docs only, apart from the TCI page prose in
`tools/docs/gen_reference.py`; no application source, test or CI
changes.

Every page was audited against the 106 PRs in the release. Every fact
that was added or kept was checked against the source at `f753dbfc4`,
the v26.10.2 release commit, not taken from the PR bodies alone.

## What changed

- **Menu paths.**
- AetherModem, Callsign Lookup, AetherMap and FreeDV Reporter are on
**Tools**. They are created on View and then moved to Tools
(`MainWindow_Menus.cpp:1519-1520`, `:1569-1575`); the style guide's
example says **Tools → AetherMap...**.
  - **Show live CW contacts** is on **View**.
  - Waveforms is on **Tools**, not File.
  - The VUDU applet button was called TXDSP.
  - Labels now match the source's `...` vs `…`.
- **Gaps from this cycle.**
- **Windows and Network Diagnostics:** Windows Firewall rules and the
Network Diagnostics Windows Firewall page (#6289); the `aether.network`
and `aether.nvafx` log categories (#6289, #6308).
  - **Remote access:** Tailscale shim revocation semantics (#6325).
  - **Sleep, App Nap and power throttling (#6195):** per-OS notes.
- **Hermes-Lite 2:** state restore, RX audio at unity, CW at TUNE level,
multi-interface discovery and a discovery troubleshooting entry (#6259,
#6254, #5975, #6009, #6293).
- **ANAN-G2:** AGC-T range, a "What is remembered" section, and supply
voltage and link status (#6282, #6129, #6137, #6211).
  - **NB2** on the HL2 and ANAN-G2 (#5966).
- **DVK:** WAV import requirements, the slot menu without Delete, status
text and licensing (#6247, #6262, #6251).
  - **Copy Assist** from unprocessed audio (#6216).
  - **Live CW contacts** replace the decoder's contact card (#6268).
  - **Status-bar indicators** work from the keyboard (#6267).
- **Volume:** controllers, hotkeys and TCI `volume` follow the active
output (#6129, #6260).
- **Peripherals:** the KPA1500 (#5905), CTR2 link extensions and the
AetherKnob (#6338), TMate 2 udev (#6250), MIDI RADE Modem and FDV modes
(#6031, #6038).
  - **RTL-SDR:** live PPM (#6082).
  - **Icom:** COMP and the MK2 squelch scale (#6174, #6184).
- **Known issues.** Entries whose GitHub issues are closed are removed
(each checked with `gh issue view`). As decided, this includes three
closed today without a demonstrated fix: #5107, #4824 and #5665.
- **US spelling.** `docs-style-guide.md` asked for British spelling; it
now asks for US, by the maintainer's decision, and every page is
converted. The generated TCI pages are converted at their source, the
prose strings in `tools/docs/gen_reference.py`. Code spans, links and
URLs were left alone. UI labels were checked against the source strings,
and none of them are British. Two in-page anchors and two Log Analyzer
rule anchors (`#bnr-is-grayed-out-…`) follow the renamed headings.
- **Stable snapshot.** `snapshot_stable.py 26.10.2` was re-run on the
release tree with these corrections, before `main` was merged in, so
Stable carries no post-release docs. `docs/` also has `main`'s
post-release pages, in US spelling. Stable alone keeps the IC-9700
waterfall-rate entry (#5996): #6402 fixed it after the 26.10.2 tag, so
26.10.2 still has it. The PDF manual already attached to the v26.10.2
release keeps the tag's docs.

## Validation

- `npm ci && npm run build` in `docs/user`: success. This is the
broken-link and broken-anchor check.
- `node tools/docs/test_log_rules.mjs`: 707 checks passed for 45 rules.
- `python3 tools/docs/gen_reference.py --check`: up to date (8 pages).
- `git diff --check`: clean.
- Menu paths on a build of this branch (offscreen, isolated settings, no
radio), `menu list`: `Tools → AetherModem...`, `Tools → Callsign
Lookup...`, `Tools → AetherMap...`, `Tools → FreeDV Reporter...`, `Tools
→ Waveforms...`, `View → Show live CW contacts`.

## Screenshots now out of date (not recaptured)

These need a recapture pass on the radio:
- **Old panadapter title strip (#6386):** `panadapter`, `main-window`,
`first-session-*`, `multi-slice-two-slices`, `split-pair`,
`tnf-markers`, `offscreen-vfo-indicator`, `pan-3d-stacked-trace`,
`default-light-theme`.
- **Pre-canon windows (#6334, #6339, #6341, #6372):** `aetherrx*`,
`aethertx*`, `aethermodem-aprs`, `bnr-panel`, `connect-dialog`,
`connect-by-ip-card`, `connect-icom-rows`, `connect-smartlink-card`,
`rx-agc-calibration`.
- **Other:**
  - `title-bar` (lowercase tab states, #6281);
  - `menu-help` (#6294);
  - `display-panel` (#6371);
  - `support-diagnostics-dialog`;
  - `waveforms-dialog` and `tailnet-remote-access` (show shim 0.4.0);
  - `about-window` (v26.10.1);
  - `radio-setup-qrz`.

## Found during the audit, not fixed here

- **App string bug:** `TailnetShimDialog.cpp:628` tells the user to
"Connect remotely with Connect → Manual"; the real path is **File →
Connect to Radio... → Connect by IP**.
- **ANAN AGC-T tooltips:** the RX applet and VFO tooltips show the
slider position as dB, which is wrong on ANAN. #6282 lists this as a
follow-up.
- **MIDI Master Volume on non-Flex radios:** it is refused while PC
Audio is off, whereas hotkeys, FlexControl and HID drive the line out.
The docs describe the code as it is.
- **RTL mode names:** `rtl-sdr.md` writes "FM-N" and "CW-R", but the
source strings are `FMN` and `CWR`. Left as is until someone confirms
what the mode menu displays.
- **IC-705 COMP readback:** inferred from the MK2 (#6174) and not
verified on an IC-705.
- **Not yet documented:** the #6230 Radio Health row "Forward responses
skipped", and the Store/MSIX package.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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