Skip to content

feat(gui): the GPS window is AetherGPS, a CanonWindow workspace re-skinned to the canon palette. Principle VIII. - #6364

Merged
ten9876 merged 1 commit into
mainfrom
canon-gps-window
Oct 11, 2026
Merged

ten9876 merged 1 commit into
mainfrom
canon-gps-window

Conversation

@ten9876

@ten9876 ten9876 commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Part of #6239. The GPS window becomes AetherGPS, a CanonWindow workspace. It follows the recipe AetherRX and AetherTX (#6334), AetherModem (#6339) and AetherMap (#6340) use:

  • Name: AetherGPS in the window title, the canon header, the menu item (Tools → AetherGPS…) and the tooltip on the status-bar GPS indicator.
  • Chrome: no title bar, the ambient ground, the canon header and the corner close button. Drag any empty area to move it, resize it from any edge, and close it with Esc or Ctrl+W. The footer Close button is gone.
  • Kind: CanonWindow::Kind::Workspace, an independent top-level window with its own taskbar entry. It no longer follows View → Frameless Window, so showGpsLocationDialog() creates it directly instead of through showOrRaisePersistent(), which would set frameless mode on it.
  • Geometry: persists under its old key (GpsLocationDialogGeometry), so saved positions carry over.
  • Size: the minimum grows from 860×600 to 860×640, and the first-open size from 1080×720 to 1080×760, to make room for the header.

Look: it sits under the canon/aetherGps theme scope, with a canon sheet in AetherMap's vocabulary:

  • the top status strip and each section are raised cards; the metric tiles, the NTP tip and the clock-sync group are nested;
  • section titles are cyan, values ink and field titles muted;
  • buttons and the NTP server field are canon controls, and check boxes use the canon indicators;
  • the satellite bar keeps its green fill, now the color.background.success token instead of the #17663f and #ffffff literals.

The object name gpsLocationDialog is unchanged because IcomControls.cpp refers to it.

Docs:

  • The user guide, menu reference, Radio Setup page, in-app help and the Tools-menu alt text in docs/user/screens.json use the new name.
  • The GPS page has a "Using AetherGPS" section that describes the window.
  • docs/style/* list AetherGPS among the canon windows.
  • Stale screenshot, to recapture after merge: menu-tools.png still shows "GPS Dashboard...".

Constitution principle honored

Principle VIII (Evidence Over Assertion) covers the checks below. The visual direction is RFC #6226's.

Test plan

  • Local build passes
  • Rendered offscreen with the app on scratch settings and the radio disconnected, opened via Tools → AetherGPS… over the automation bridge: the canon header, the cards, the cyan section titles and the corner ✕ draw.
  • The static-check scripts pass locally. The touchpoint manifest is unchanged.
  • embed_screenshots.py --check and gen_reference.py --check pass.
  • Not exercised: the window with live GPS data, since no radio was connected. No test covers this window, and this PR adds none.

Checklist

  • Commits are signed
  • No new flat-key AppSettings calls. The existing geometry key is reused.
  • Code is clean-room
  • All meter UI uses MeterSmoother (unchanged)
  • Documentation updated: docs/user/docs/aetherclock-and-gps.md and the pages that name the window, docs/style/*
  • Security-sensitive changes: n/a

🤖 Generated with Claude Code

@ten9876
ten9876 requested a review from a team as a code owner October 11, 2026 01:37
@ten9876 ten9876 self-assigned this Oct 11, 2026

@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.

The PR satisfies the AetherGPS conversion explicitly selected in #6239 under approved RFC #6226: dashboard/menu/tooltip naming, canon workspace chrome, scoped styling, the preserved geometry key, and matching documentation. This is an authorized visual migration, not an unrelated preference bundled into a fix. No standalone closing issue is claimed.

Scope

File/group Change Claimed? Verdict
src/gui/GpsLocationDialog.{cpp,h} Canon workspace, header/resizer, scoped stylesheet, geometry key, footer removal Yes In scope
src/gui/MainWindow.cpp, MainWindow_Menus.cpp, MainWindow_Wiring.cpp Tooltip/menu naming and construction outside persistent-dialog frameless tracking Yes In scope
Three docs/style/ guides Document the approved AetherGPS workspace exception Yes In scope
Four user-guide pages, docs/user/screens.json, in-app help Names, window instructions, synchronized screenshot alt text Yes In scope

All 14 files and the single commit are explained by the body; no outliers or unrelated hunks. No new settings key, protocol path, capability, dependency, token-default change, or weakened enforcement baseline. The commit has a verified good signature. Radio/GPS/NTP update and command wiring are unchanged.

Blockers

None.

Nits — non-blocking

  1. Recapture the already-disclosed Tools screenshot after merge. docs/user/docs/menu-reference.md:64 points at menu-tools.png, whose pixels still say GPS Dashboard while the synchronized alt text and menu now say AetherGPS. The body correctly discloses this, satisfying the project requirement to identify stale screenshots; it does not hold up this PR. Recapture the menu-tools recipe and re-embed it when the updated menu is available in the capture build.

Empirical verification and attacks

  • Built actual merge base b3e0302ea271fd8afc54e2bfdf73799d89a933c4 and exact head a13f93cc32e3a271c3f2d17871ec858b2611625f in an owned scratch checkout, with Qt 6.12 on Linux and the lean shared-core configuration. Built only the app and named test targets. Head canon_window_test and frameless_resizer_test pass (2/2). Both inspected targets are socket-free; the PR adds or modifies no tests, so there is no new assertion to mutation-check.

  • Drove base/head using explicit aethersdr-pr6364-base and aethersdr-pr6364-head sockets, offscreen with fresh isolated settings and TX disabled. Connected only to DEMO-0001, confirmed model: AetherSDR Demo, connected: true, and transmitting: false, then disconnected to expose the GPS window (the demo lacks GPS). Before/after captures show the intended old 1080×720 dashboard/title/footer versus new 1080×760 AetherGPS header, canon cards, and corner close. Both Default Dark and Default Light render successfully.

  • Opened AetherGPS twice: one visible GPS window. Changed View → Frameless Window while it was open: unchanged visible geometry. Minimize/restore returned minimized then normal. Corner-close/reopen retained geometry. The existing CanonWindow test verifies Escape/platform Close and geometry flushing; those keys were not synthesized through the GPS bridge session.

  • Saved real 1000×680 legacy base64 geometry from the merge-base dashboard, then seeded only that row into a fresh isolated migration profile. Head restored 1000×680 (Qt normalized the old top-edge position to y=25). Empty-header dragging and corner-close/reopen retained the moved position. After exiting and relaunching the head, bridge output was:

    {"class":"AetherSDR::GpsLocationDialog","objectName":"gpsLocationDialog","visible":true,"geometry":{"h":680,"w":1000,"x":331,"y":115},"windowState":"normal"}

    That proves persistence across a process boundary. An undersized programmatic resize clamped height to 640. The bridge intentionally removes the minimum-width constraint when asked for a narrower window; that probe is not evidence against the declared 860-pixel width floor.

  • Inspected concrete ownership/input paths: direct creation retains WA_DeleteOnClose and QPointer; capability-loss close still reaches inherited closing; Icom callers rely only on the preserved object name. Existing buttons already disable auto-default activation, and the explicit NTP field returnPressed → Apply connection survives the Workspace Return gate.

All four review-owned app launches were closed and their exit confirmed. The operator's existing app and live radios were not driven or closed. Captures/logs remain under /tmp/pr6364-runtime/.

Governance, checks, and limits

Independent scope/canon and lifecycle audits found no other concrete finding. A model-invocable automated code-review skill was unavailable; this was a manual pass with independent audits. No review-bot findings were present when checked.

Base/head per-file gate output is byte-identical: 102 existing engine-boundary findings, 70 frozen capability booleans, and 32 command-plane files / 368 commands. Both touchpoint manifests pass. Changed GUI files have zero accessibility checker warnings. Screenshot embedding (119 shots) and generated-reference (8 pages) checks pass; the docs-site CI build passes.

Unverified: live GPS/satellite/NTP telemetry/configuration and native Windows/macOS taskbar/input behavior. No GPS-specific test is added; generic canon/resizer tests cover reused machinery. Bridge dragAt sends QWidget events while FramelessResizer deliberately consumes QWindow events, so native all-edge resizing cannot be proven through that verb. Its installation was inspected and its socket-free edge/clamping test passes. No live hardware was used to fill these coverage boundaries.

All nine applicable checks pass, including Linux, Windows, macOS, Static checks and Docs; the release-only PDF attachment is skipped. CI is fresh against current main b3e0302ea271fd8afc54e2bfdf73799d89a933c4 dated 2026-10-10 20:41:06 UTC; the earliest head workflow was created 2026-10-11 01:37:55 UTC.

Recommendation: Approve with nits. Approved scope, two passing focused tests, green required CI, and concrete legacy/current geometry plus close/reopen checks support the conversion. Retain normal CODEOWNERS review and recapture the disclosed Tools screenshot after merge. This COMMENT review leaves formal approval to the maintainer.

@ten9876 ten9876 removed their assignment Oct 11, 2026
…inned to the canon palette. Principle VIII.

GpsLocationDialog follows the recipe AetherRX, AetherTX and AetherMap use:
- Name: AetherGPS in the window title, the canon header, the menu item
  (Tools -> AetherGPS...) and the status-bar GPS indicator's tooltip.
- Chrome: no title bar, the ambient ground, the canon header and the corner
  close button. Drag any empty area to move it, resize it from every edge,
  and close it with Esc or Ctrl+W. The footer Close button is gone.
- Kind: CanonWindow::Kind::Workspace, an independent top-level window with
  its own taskbar entry. It no longer follows View -> Frameless Window.
- Geometry persists under its old key (GpsLocationDialogGeometry), so saved
  positions carry over. The minimum grows from 860x600 to 860x640 and the
  first-open size from 1080x720 to 1080x760 for the header.

Look: it sits under the canon/aetherGps theme scope with a canon sheet in
AetherMap's vocabulary:
- the metric strip and each section are raised cards; the metric tiles, the
  NTP tip and the clock-sync group sit nested;
- section titles are cyan, values ink, field titles muted;
- buttons and the NTP server field are canon controls, and check boxes are
  the canon indicators;
- the satellite bar keeps its green fill, now the color.background.success
  token in place of the #17663f and #ffffff literals.

The user guide, menu reference, Radio Setup page, help text and the
menu-tools alt text use the new name, and the GPS page describes the
window. docs/style/* list AetherGPS among the canon windows.

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

@aethersdr-agent aethersdr-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Issue fit

Yes, with one divergence from the body. #6239 lists AetherGPS (GpsLocationDialog, "a workspace re-skinned to color.canon.*; the footer Close button is gone") under Picked: tool windows on CanonWindow, naming this PR, and the diff delivers exactly that: CanonWindow(…, Kind::Workspace), the canon header, canon/aetherGps scope, setGeometryKey("GpsLocationDialogGeometry"), FramelessResizer::install, the footer Close removed, and the rename carried through the menu, the status-bar tooltip, the user guide, the menu reference, Radio Setup, in-app help, screens.json and docs/style/*. The one claim the code does not support is the satellite progress bar (Blocker 1).

One governance note, not a finding: I could not find a maintainer comment on #6239 picking AetherGPS — the pick lives in the issue body, which the PR author maintains, and that line gained its (#6364) reference a minute after this PR opened. Four siblings (#6334, #6339, #6340, #6341) landed under the same section, so the path looks established; flagging it only so the maintainer can confirm the pick rather than inherit it from the tracker.

Scope

File(s) What it changes Claimed by the body? Verdict
src/gui/GpsLocationDialog.{h,cpp} PersistentDialog → CanonWindow::Kind::Workspace, canon sheet, header, resizer, footer Close removed, sizes +40 px Yes In scope
src/gui/MainWindow_Wiring.cpp showOrRaisePersistent → direct construct + WA_DeleteOnClose Yes (avoids setFramelessMode) In scope
src/gui/MainWindow_Menus.cpp Menu label → AetherGPS... Yes In scope
src/gui/MainWindow.cpp Status-bar GPS indicator tooltip text Yes In scope
docs/style/*.md (3 files) AetherGPS added to the canon-window and canon-scope lists Yes In scope
docs/user/docs/*.md, docs/user/screens.json, resources/help/aethersdr-help.md Rename + new "Using AetherGPS" section + Tools-menu alt text Yes In scope

Everything in the diff is explained by the issue. No build/CI files, no protocol or wire surface, no new settings key (the geometry key is reused), no capability change, no CHANGELOG.md entry, no deleted guard. docs/user/versioned_docs/version-stable/* correctly still says "GPS Dashboard" — that is the shipped release's docs. No socket test and no fake peer is added, modified or removed by this PR.

Blockers

1. src/gui/GpsLocationDialog.cpp:151-155 — the satellite bar is not what the body says it is, and the fill is effectively invisible.

The body states: "the satellite bar keeps its green fill, now the color.background.success token instead of the #17663f and #ffffff literals." The sheet contains no color.background.success (grep in the head checkout returns nothing); the rule is:

QProgressBar::chunk {
    background: {{color.canon.nested}};
    border: 1px solid {{color.canon.cyan}};
    border-radius: 4px;
}

Against the groove (QProgressBar { background: {{color.canon.control}} }, :145) in Default Dark that is #0e1a2a on #12233a — 1.11:1, a darker-than-the-groove band whose only cue is the 1 px cyan outline. docs/a11y.md:143-145 asks for "3 : 1 … for non-text components — … control states that need to be distinguishable". The old #17663f fill was 2.69:1 and is the only graphical indicator in the window. The counts survive in setFormat() (:773), so no information is lost — but a maintainer approving on the body's description gets something visibly different.

Either fix is fine; pick one and make them agree. For a visible fill that is still a token:

QProgressBar::chunk {
    background: {{color.accent.success}};
    border-radius: 4px;
}

(color.accent.success resolves to #4dd87a in dark — 8.6:1 on the groove. Note color.background.success, the token the body names, is #006040 and measures only 2.07:1 there, so it would not actually satisfy the ratio either.) If the maintainer prefers the cyan-outline look, keep the sheet and correct the body instead.

Nits

  • src/gui/GpsLocationDialog.cpp:44-47 — the sheet opens with QWidget { background: transparent; }, which cascades into the NTP field's standard context menu (QMenu parents to the QLineEdit at :622), leaving it transparent over whatever is behind the window. PskReporterMapDialog.cpp:207-212 and ConnectionPanel.cpp:83 both add a rule for exactly this. Non-blocking, and NetworkDiagnosticsDialog has the same gap, so it is a pattern hole rather than something this PR introduced:
    QMenu {
        background: {{color.canon.raised}};
        color: {{color.canon.inkSoft}};
        border: 1px solid {{color.canon.line}};
    }
  • src/gui/MainWindow.cpp:6153 — the tooltip became "Open AetherGPS" but setAccessibleName(QStringLiteral("GPS and station location")) on the next line kept the old wording, so a screen-reader user hears the pre-rename name for the control that opens it. The description on :6154-6155 is generic and fine.
  • The stale menu-tools.png is disclosed in the body and the alt text is already updated — no action asked for, just confirming I read it and agree the recapture belongs after merge.
  • No test is added, and the body says so. I agree none is owed: this is window chrome and QSS, which has no deterministic socket-free seam, and canon_window_test already pins the base class's placement, geometry round-trip, Escape/Ctrl+W and Return behaviour. tools/gen_touchpoint_manifest.py --check reports "manifest up to date", as claimed.

What I tried to break

  • Geometry migration. The body claims saved positions carry over from the PersistentDialog era. They do: PersistentDialog::saveGeometryToSettings wrote saveGeometry().toBase64(), and CanonWindow::restoreGeometryFromSettings (CanonWindow.cpp:170-191) falls through its 4-part x,y,w,h parse to restoreGeometry(QByteArray::fromBase64(saved)) for exactly that older blob. The grown minimum (860×640) is also honoured — restore does resize(QSize(w,h).expandedTo(minimumSize())).
  • Lifetime, both close paths. WA_DeleteOnClose plus a QPointer slot (MainWindow.h:1688): the ✕ button is wired to QDialog::close (CanonWindow.cpp:83) and deletes the window, nulling the pointer so the next showGpsLocationDialog() rebuilds; Escape and Ctrl+W go through reject() and only hide (CanonWindow.cpp:88,136-145), so the instance stays live and show()/raise() re-opens it. MainWindow.cpp:8309-8310 (GPS capability going false) tests the QPointer before close(). I could not construct a dangling-pointer or double-free ordering from these three paths.
  • Shutdown ordering. ~MainWindow explicitly pre-destroys m_networkDiagnosticsDialog (MainWindow.cpp:2754) and m_ax25HfPacketDecodeDialog (:2767) because they outlive AudioEngine and touch it. grep -n "m_audio\|AudioEngine" src/gui/GpsLocationDialog.cpp is empty — this window holds only RadioModel* and its own LocationAddressResolver, so it does not need a line in that block. Unchanged by the PR either way.
  • Theme scope resolution. ThemeManager::lookupRaw (ThemeManager.cpp:296-301) falls back to root, not to the parent path, when a scope is missing — so a canon/aetherGps that existed only as a string would silently lose every canon override. It doesn't: theme::setContainer → registerDeclaredContainer → scopeOrCreate (:1906-1914, :252-272) walks the segments and creates the node under canon. Same mechanism the four siblings rely on; no theme JSON entry is needed.
  • The global transparent rule vs. the embedded map. QWidget { background: transparent; } reaching MapView is the established pattern, not a regression — PskReporterMapDialog.cpp:199-203 carries the identical rule with the comment "The map itself paints its own."
  • Leftovers and dead code. makeActionButton is still used five times (:446,452,459,630,642), so removing the footer leaves no unused static. MainWindow_Wiring.cpp:36 already includes the header the direct new needs. Nothing outside versioned_docs still says "GPS Dashboard" or "GPS & Station Location"; IcomControls.cpp:499,507 references the object name gpsLocationDialog, which the PR deliberately kept. No test or script references this class.
  • Local static checks. gen_touchpoint_manifest.py --check, check_a11y.py (no GPS findings in the full output, not just the tail) and audit_colours.py (no new hex literals; the PR removes two) all pass. CI on a13f93c is green across build, check-windows, check-macos, Static checks, Build docs site and the sanitizer configure job.
  • CodeGuard leads. Checked via the security-audit subagent and spot-verified: no confirmed findings. The CMDI-BACKTICK/CMDI-AMP hits are Markdown-quoted identifiers in // comments and Qt mnemonics / C++ reference sigils; PATH-PROC is the fixed literal "/proc/self/status"; the SSRF/PII hits in screens.json are RFC 5737 TEST-NET addresses, 127.0.0.1 and you@example.com in accessibility alt prose, all present identically on main and none on a changed line. The one &-bearing string in the touched region ("Open GPS & Station Location") is in fact removed by this PR.

Everything above is reasoned from the code in the PR head checkout and from static checks — I have no build and cannot drive the GUI, so the contrast figures are computed from the resolved token values rather than observed on screen, and the window's behaviour with live GPS data is untested here as well as in the PR.

Recommendation

Approve with nits, once Blocker 1 is resolved one way or the other — either restore a visible fill or correct the body's description of it; that is a one-line change plus a body edit, not a redesign. The conversion itself is a faithful application of the #6226 recipe: the geometry migration, the two close paths, the theme scope and the teardown ordering all survived the attacks above, and the docs are complete. Next step: author picks the fill-or-body fix, and the maintainer confirms the AetherGPS pick on #6239 is theirs. Thanks for keeping the geometry key and the gpsLocationDialog object name stable — those are the two things a rename like this usually breaks.


🤖 aethersdr-agent · cost: $11.0235 · model: claude-opus-5

@aethersdr-agent

Copy link
Copy Markdown
Contributor

Cisco CodeGuard — static analysis of this PR (63 finding(s))

  • [HIGH] CS-VLN-SSRF-LOCALHOST — Vulnerability: CS-VLN-SSRF-LOCALHOST in docs/user/screens.json /tmp/aetherclaude/pr-6364/docs/user/screens.json:2579
  • [HIGH] CS-VLN-SSRF-LOCALHOST — Vulnerability: CS-VLN-SSRF-LOCALHOST in docs/user/screens.json /tmp/aetherclaude/pr-6364/docs/user/screens.json:4219
  • [MEDIUM] CS-PII-EMAIL — PII detected: email in docs/user/screens.json /tmp/aetherclaude/pr-6364/docs/user/screens.json:3877
  • [LOW] CS-PII-IP — PII detected: ip_address in docs/user/screens.json /tmp/aetherclaude/pr-6364/docs/user/screens.json:1122
  • [LOW] CS-PII-IP — PII detected: ip_address in docs/user/screens.json /tmp/aetherclaude/pr-6364/docs/user/screens.json:2579
  • [LOW] CS-PII-IP — PII detected: ip_address in docs/user/screens.json /tmp/aetherclaude/pr-6364/docs/user/screens.json:2625
  • [LOW] CS-PII-IP — PII detected: ip_address in docs/user/screens.json /tmp/aetherclaude/pr-6364/docs/user/screens.json:2659
  • [LOW] CS-PII-IP — PII detected: ip_address in docs/user/screens.json /tmp/aetherclaude/pr-6364/docs/user/screens.json:2756
  • [LOW] CS-PII-IP — PII detected: ip_address in docs/user/screens.json /tmp/aetherclaude/pr-6364/docs/user/screens.json:2796
  • [LOW] CS-PII-IP — PII detected: ip_address in docs/user/screens.json /tmp/aetherclaude/pr-6364/docs/user/screens.json:4219
  • [MEDIUM] CG-PATH-001 — Potential path traversal in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:9686
  • [MEDIUM] CG-PATH-001 — Potential path traversal in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:9798
  • [MEDIUM] CG-PATH-001 — Potential path traversal in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:9920
  • [MEDIUM] CG-PATH-001 — Potential path traversal in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:9921
  • [MEDIUM] CG-PATH-001 — Potential path traversal in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:9922
  • [HIGH] CS-VLN-PATH-PROC — Vulnerability: CS-VLN-PATH-PROC in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:6217
  • [HIGH] CS-VLN-PATH-PROC — Vulnerability: CS-VLN-PATH-PROC in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:6296
  • [CRITICAL] CS-VLN-CMDI-AMP — Vulnerability: CS-VLN-CMDI-AMP in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:526
  • [CRITICAL] CS-VLN-CMDI-AMP — Vulnerability: CS-VLN-CMDI-AMP in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:556
  • [CRITICAL] CS-VLN-CMDI-AMP — Vulnerability: CS-VLN-CMDI-AMP in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:559
  • [CRITICAL] CS-VLN-CMDI-AMP — Vulnerability: CS-VLN-CMDI-AMP in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:581
  • [CRITICAL] CS-VLN-CMDI-AMP — Vulnerability: CS-VLN-CMDI-AMP in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:3660
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:1280
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:1804
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:1896
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:1973
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:2015
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:2050
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:2345
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:3602
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:3693
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:6159
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:7965
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:8030
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:8104
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:8189
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:8370
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:8573
  • [CRITICAL] CS-VLN-CMDI-BACKTICK — Vulnerability: CS-VLN-CMDI-BACKTICK in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:9787
  • [LOW] CS-PII-IP — PII detected: ip_address in src/gui/MainWindow.cpp /tmp/aetherclaude/pr-6364/src/gui/MainWindow.cpp:6909

Automated static scan by Cisco DefenseClaw CodeGuard on the changed files. Advisory — some may be false positives; the review above verifies them.


🤖 aethersdr-agent · cost: $11.1538 · model: claude-opus-5

@ten9876
ten9876 merged commit e56cb0c into main Oct 11, 2026
10 checks passed
@ten9876
ten9876 deleted the canon-gps-window branch October 11, 2026 02:02
ten9876 added a commit that referenced this pull request Oct 11, 2026
…remote operation over CGNAT (#6389)

## Summary

Release prep for **v26.10.2**: the six release files plus the Stable
docs snapshot. Metadata and docs only; no source, test or CI changes.

Cutoff: `origin/main` at `46943eb3c` (#6083, merged 2026-10-11).
Anything that merges after it is folded in before the tag.

**106 merged changes** from **15 human contributors**, AetherClaude (2)
and Dependabot (0). First-time contributor: **@dacacioa**. This was
confirmed by checking each login for a merged PR before the previous
tag, not from `author_association`.

## Changelog

The range `v26.10.1..46943eb` was mapped through the commit-to-PR API
(`repos/…/commits/<sha>/pulls`), not from commit subjects. It holds 106
PRs and no direct commits, and every one is cited in the section.
`v26.10.1` is an ancestor of `main`, so nothing is excluded. #6083
merged before the branch was cut, so it is inside the range and needs no
unmerged-PR banner.

The notes lead with:
- the unified 52 px title bar (#6198);
- docs.aethersdr.com (#6286, #6298, #6294);
- remote operation over CGNAT through the in-radio tailnet shim (#6273,
#6318, #6325, #6319);
- the canon windows (#6227, #6334, #6339, #6340, #6341, #6364, #6372,
#6386).

Then come DVK import, FFT Smooth/De-comb, TCI tune and receiver events,
RTL-SDR multi-receiver delivery, HL2 and ANAN-G2 state memory, the
IC-7300MK2 fixes, the first clean sanitizer runs (stated beside #6350's
TSan red) and Authenticode signing.

Numbers come from the PR bodies. "On upgrading" callouts cover the
behavior changes the bodies flagged:
- HL2 receive audio is 12.04 dB quieter (#6254);
- HL2 host CW is +6.02 dB at a fixed drive (#5975);
- ANAN AGC-T is remapped (#6282);
- sleep prevention is on by default (#6195);
- the Tailscale MTU cap has no opt-out (#6319);
- IC-7300MK2 Auto SQL is withdrawn (#6184).

DeepFist (#5953, #6103) is described as applying only to
`ENABLE_DEEPFIST_EXPERIMENT` builds.

## Docs refresh, not just version strings

- **README**:
- Highlights: FFT Smooth/De-comb on the spectrum line; AetherMap naming;
remote over CGNAT and TCI tune/receiver events on the SmartLink/TCI
line; pre-NR Copy Assist; a new docs.aethersdr.com line.
- Supported Hardware: the KPA1500, marked as not yet validated on
hardware.
- Other radio families: HL2 state restore extended; ANAN-G2 gains AGC-T,
NB2, supply voltage/link and per-radio memory; RTL-SDR now "bundled in
every official package", with WFM stereo, PPM, per-receiver SQL/meters
and DAX/TCI feeds, and multi-receiver explicitly an evaluation.
- Roadmap section: the CTR2 line advanced and a visual-canon line added.
  - Maturity labels are unchanged.
- **ROADMAP**:
- In flight: a v26.10.2 sentence each for aetherd, Icom, ANAN-G2,
RTL-SDR (remaining is now production multi-receiver qualification and
digital FM, RFC #6079), Hermes-Lite 2 and the CTR2 relay (RFC #6332
extensions). A new entry for the visual canon (RFC #6226 / #6239).
  - Queued: RFC #4214 (approved 2026-10-09) added.
- Open RFCs, checked against `label:rfc`: #4214 leaves (approved); #4764
and #4861 leave (shipped by #6198 and #6216); #6346, #6232, #6212 and
#6209 join. #6332 is approved and folds into the CTR2 entry.
- Recently shipped: nine new `(v26.10.2)` entries, still within the
v26.10.x cycle, so no month-rollover trim.
- Backends (six: anan, flex, hl2, icom, rtl, sim) and NR engines (seven)
were checked against the tree; both are unchanged.

## Judgment calls flagged for the maintainer

All of these were decided through AskUserQuestion:
- Version **26.10.2**, date **2026-10-11**, opened ready for review.
- **#6350**, the TSan red in the weekly sanitizer lane: proceed, and
name it below.
- RFCs **#4764** and **#4861** come off Open RFCs as shipped. The issues
themselves are left open for you to close.
- RFC **#4214** goes under Queued (next cycle).
- A **visual canon** In-flight entry, plus a README Roadmap line.
- The **KPA1500** is listed in README Supported Hardware with "not yet
validated on hardware".
- Including **#6083**: you asked for it, and it merged before the
cutoff, so it ships as an ordinary part of the range.

## Known failing on `main`

- **`ctr2_hid_thread_port_test`** fails in the weekly TSan lane (runs of
2026-10-08 and 2026-10-10; #6350). `main`'s CI and Full Suite were green
at `414082197`. The CHANGELOG headline and intro say so: the lanes
achieved their first clean runs this cycle, and the test remains failing
under TSan. This prep does not fix the test, and the release ships with
it red in that lane.

## Scope

| file | change |
|---|---|
| `CMakeLists.txt` | `project(AetherSDR VERSION 26.10.2)` |
| `README.md` | Current version line, plus the prose refresh above |
| `AGENTS.md` | Current version line |
| `CHANGELOG.md` | new `[v26.10.2] — 2026-10-11` section; `[Unreleased]`
stays and stays empty; history below byte-identical |
| `packaging/linux/io.github.aethersdr.aethersdr.metainfo.xml` |
`<release version="26.10.2" date="2026-10-11"/>` first in `<releases>` |
| `ROADMAP.md` | cycle heading → post-v26.10.2, plus the prose refresh
above |
| `docs/user/versioned_docs/version-stable/**`,
`docs/user/versioned_sidebars/version-stable-sidebars.json`,
`docs/user/stable-version.json`,
`docs/user/src/components/LogAnalyzer/rules.json` | docs snapshot
(`tools/docs/snapshot_stable.py 26.10.2`), in its own commit. This is
the first snapshot since #6286. |

## Validation

Output of `check_release_prep.py --mapping mapping.json` at the branch
head: 30 checks, 1 FAIL (explained below), 1 WARN (the snapshot files,
listed in the scope table).

```
PASS v26.10.1 is an ancestor of origin/main
PASS all six version spots say 26.10.2
PASS CHANGELOG heading date equals metainfo release date
PASS appstreamcli validate
PASS metainfo <release> list is date-descending with unique versions
PASS `## [Unreleased]` stays and stays empty
PASS `## [v26.10.2]` sits directly under `[Unreleased]`
PASS the previous section is `[v26.10.1]`
PASS CHANGELOG diff is exactly the inserted section
PASS new section opens with a `### <headline>`
PASS intro sentence has the house shape
PASS new section has a `### Contributors` block
PASS release_contents.py --check (citations, intro and Contributors counts)
     PRs in range: 106  cited: 106; intro 106/15 matches; Contributors (16 entries) matches; first-time ['dacacioa']
     citations outside the range: #4764, #4861, #5468, #6192, #6226, #6271, #6332 (RFCs), #6238, #6350 (issues)
PASS code fences balance / no duplicated table headers or doubled `---` (README, ROADMAP, new section)
PASS every local link in README.md and ROADMAP.md resolves
PASS no heading removed from README/ROADMAP is still linked elsewhere
PASS Recently shipped `(vX)` markers run newest-first and lead with the new version
PASS Recently shipped intro names the current cycle (v26.10.x)
FAIL only the four current-version lines lose the `26.10.1` string outside CHANGELOG
     historical mentions must stay: "label": "26.10.1"
PASS diff touches no src/, tests/, third_party/ or .github/workflows/ path
PASS all six release files are in the diff
WARN files beyond the six (the docs snapshot)
PASS git diff --check
```

- **The one FAIL is the snapshot's version label, not a historical
mention.** `docs/user/stable-version.json`'s `"label"` is the docs
site's current Stable version, and `snapshot_stable.py` rewrites it by
design. The validator predates #6286 and knows only the four
current-version lines. Run on the six-file commit alone, the same check
passes (29 checks, 0 FAIL, 0 WARN).
- The docs build passes: `npm ci && npm run build` in `docs/user`. `node
tools/docs/test_log_rules.mjs` reports 707 checks passed for 45 rules.
The line moves it reports were already on `main`.
- Four merged PRs (#6340, #6341, #6364, #6372) named screenshots to
recapture after merge (`psk-reporter-sidebar.png`, `menu-tools.png`,
`connect-dialog.png`, `rx-agc-calibration.png`), and #6386 named the
panadapter shots (`panadapter.png` and the main-window captures, which
still show the old title strip). They were not recaptured, so the Stable
snapshot carries the older images.
- No configure, build or test was run for this prep; it is metadata
only, and CI builds it.
- `main` CI at the cutoff `46943eb3c`: Docs and CodeQL - Code Quality
are green; CI, Full Suite, CodeQL and the System Libraries Canary were
still running when this was opened. At `414082197`, every one of them
was green.

After merge: tag the resulting **main** commit, not this branch.

🤖 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
… palette. Principle VIII. (#6401)

## Summary

Part of #6239. **SpotHub** (`DxClusterDialog`) moves from
`PersistentDialog` to a `CanonWindow` workspace, following the recipe
AetherGPS (#6364) and AetherMap (#6340) use:
- **Chrome:** no title bar; the ambient ground, the canon header and the
corner close button. Drag any empty area to move it, resize it from any
edge, close it with Esc or Ctrl+W.
- **Kind:** `CanonWindow::Kind::Workspace`, an independent top-level
window with its own taskbar entry. It no longer follows **View →
Frameless Window**, so the **Settings → SpotHub…** handler creates it
directly instead of through `showOrRaisePersistent()`, which would set
frameless mode on it.
- **Geometry:** persists under its old key (`DxClusterDialogGeometry`),
so saved positions carry over.
- **Size:** minimum 360×600 (was 360×560) and first-open 760×680 (was
760×640), to make room for the header.

**Look.** It sits under the `canon/spotHub` theme scope, which maps the
tokens the tabs' remaining per-widget sheets use (status colors, labels)
onto the canon palette, plus one canon sheet:
- the tab pages are a raised card; the selected tab is cyan with a cyan
underline;
- group boxes are nested cards with cyan titles;
- fields, spin boxes and combos sit on `control`; the consoles and the
spot list are nested, with a canon header row;
- check boxes use the canon indicators;
- each source's **Connect / Start** button is the filled cyan primary;
- a checked toggle (Auto-Connect, Spots, Passive, Enabled/Disabled…)
keeps SpotHub's green fill, now the `color.toggle.success.*` tokens
instead of literals. The maintainer chose this over the canon aqua
outline, because the fill is the only on/off signal on the Display tab's
name-only toggles.

**Cleanup.** About 60 per-widget field, console, table, tab, checkbox
and toggle sheets are replaced by that one sheet, and the remaining hex
literals (swatch borders, the server and DXCC/Signal History labels) are
tokens. `kSpotHubToggle` is gone.

**Docs:**
- `docs/user/docs/spothub.md` describes the window (move, resize, close,
taskbar, Frameless Window).
- `docs/style/*` list SpotHub among the canon windows and its scope.
- **Stale screenshot, to recapture after merge:** `spothub.png` shows
the old window.

## Constitution principle honored

Principle VIII (Evidence Over Assertion) covers the checks below. The
visual direction is RFC #6226's; the checked-toggle color was the
maintainer's call.

## Test plan

- [x] Local build passes (Qt 6.12).
- [x] Full GUI on a scratch profile, opened via **Settings → SpotHub…**
over the automation bridge, every tab grabbed: Cluster, WSJT-X, FreeDV,
Spot List and Display draw the canon header, cards, cyan tabs and
titles, canon fields and the corner ✕; checked toggles fill green. A
clipped **Freeze** label (60 px fixed width) was fixed by tightening
button padding, and re-grabbed.
- [x] The bridge's `close` closed the window and saved
`DxClusterDialogGeometry` (`570,237,760,680`); reopening restored
760×680.
- [x] The static-check scripts (`check_engine_boundary`,
`gen_touchpoint_manifest --check`, `check_capability_records`,
`check_command_plane`) and `check_a11y.py` pass. The color-audit ratchet
is 43 references and 40 `setStyleSheet` calls below `main`.
- [x] `embed_screenshots.py --check` and `gen_reference.py --check`
pass.
- [ ] Not exercised: live spot traffic (no cluster connected) and the
live radio. No test covers this window, and this PR adds none.

## Checklist

- [x] Commits are signed
- [x] No new flat-key `AppSettings` calls; the existing geometry key is
reused
- [x] Code is clean-room
- [x] No meter UI touched
- [x] Documentation updated: `docs/user/docs/spothub.md`,
`docs/style/*`; no `CHANGELOG.md` entry
- [x] Security-sensitive changes: n/a

🤖 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