Skip to content

docs: notify agents + contributors of the MainWindow decomposition (#3351)#3564

Merged
ten9876 merged 4 commits into
mainfrom
docs/mainwindow-decomp-notify
Jun 14, 2026
Merged

docs: notify agents + contributors of the MainWindow decomposition (#3351)#3564
ten9876 merged 4 commits into
mainfrom
docs/mainwindow-decomp-notify

Conversation

@ten9876

@ten9876 ten9876 commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator

Why

The #3351 MainWindow decomposition is real in the code but invisible at the
project level
— it's documented only inside each MainWindow_*.cpp header
comment, which you only see after you've already opened the wrong file to add
code. This surfaces it up front for both AI tools and human contributors, and
closes an ownership gap the split opened.

What's in here (5 pieces)

  1. Point-of-use banners at the top of MainWindow.cpp and MainWindow.h
    the one place everyone sees the instant they go to add code: "this file is
    not the home for new feature code; use the matching MainWindow_*.cpp
    sibling."
    Reaches every tool (Copilot, Aider, a human in an editor), not
    just ones that load AGENTS.md.
  2. New canonical doc docs/architecture/mainwindow-decomposition.md — the
    TU map, a "where does my change go?" decision table, and the
    include/wiring conventions (incl. the Qt 6.4.2 explicit-includes rule).
    Indexed in the docs/architecture README.
  3. AGENTS.md — flags the decomposition on the MainWindow architecture
    line and adds an "Adding code to MainWindow" pattern. Since CLAUDE.md /
    GEMINI.md / the Copilot + Aider files all point at AGENTS.md, this reaches
    every AI tool at once.
  4. CONTRIBUTING.md — a "Working in MainWindow" note for humans, and a
    clarification in the review-tier section.
  5. CODEOWNERS — enforces maintainer-only on the two core files
    (MainWindow.{h,cpp}), which CONTRIBUTING already claimed but CODEOWNERS
    never actually encoded.

Ownership decision (intentional)

Only core MainWindow.{h,cpp} is maintainer-gated. The MainWindow_*.cpp
sibling TUs are deliberately left on the Tier 3 reviewer default — widening
review/approval of extracted feature code to the whole reviewer team was a
primary goal of the decomposition, so feature work in a sibling TU doesn't
bottleneck on a maintainer. The CODEOWNERS comment documents this so a future
edit doesn't re-gate the siblings with a MainWindow* glob.

Verification

AetherSDR builds clean (banners are comments); all doc cross-links and the
AGENTS.md anchor resolve.

🤖 Generated with Claude Code

…3351)

The #3351 split is only recorded in each MainWindow_*.cpp header comment —
which you only see after opening the wrong file. This surfaces it up front,
for both AI tools and humans, and closes the ownership gap the split opened.

- MainWindow.cpp / MainWindow.h: point-of-use banner — "this file is not the
  home for new feature code; use the matching MainWindow_*.cpp sibling."
- docs/architecture/mainwindow-decomposition.md (new): the TU map + a
  "where does my change go?" decision guide + the include/wiring conventions;
  linked from the docs/architecture index.
- AGENTS.md: note the decomposition on the MainWindow architecture line and
  add an "Adding code to MainWindow" pattern (reaches all AI tools, since
  CLAUDE.md/GEMINI.md point here).
- CONTRIBUTING.md: a "Working in MainWindow" note, and clarify in the review
  tiers that ONLY core MainWindow.{h,cpp} is maintainer-only.
- CODEOWNERS: enforce maintainer-only on the two core files (which
  CONTRIBUTING already claimed but CODEOWNERS did not encode). The
  MainWindow_*.cpp siblings are deliberately LEFT on the Tier 3 reviewer
  default — broadening review of extracted feature code to the whole team was
  a goal of the decomposition.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ten9876 ten9876 requested review from a team as code owners June 13, 2026 21:51
ten9876 and others added 2 commits June 13, 2026 15:07
Follow-up to the decomposition notice: the doc said WHERE a new subsystem
goes but gave no criteria for WHEN a new MainWindow_*.cpp sibling is justified.

Adds a section with a floor and a ceiling:
- Default to extending an existing sibling; a new TU is for a distinct cohesive
  subsystem (~500+ lines) with no existing home — not a stray method or two.
- Size is a signal, not a trigger; don't pre-create near-empty TUs.
- Split an existing sibling only when it accretes a *second* subsystem.
- The ceiling: once a TU is one cohesive subsystem at a reviewable size, STOP.
  Subdividing finer adds build cost (every sibling re-parses the ~1,000-line
  MainWindow.h; header edits rebuild all 8) and arbitrary seams without
  decoupling anything. If tempted to slice thinner, extract a real class
  instead (the #3557 direction) — the only move that shrinks the shared header
  and creates a compiler-enforced boundary.

AGENTS.md table row + a short note cross-reference the new section.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The decomposition + new-TU sections grew the file past the stated count.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@NF0T NF0T self-assigned this Jun 13, 2026

@NF0T NF0T left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Content and structure are solid — the banners, AGENTS.md additions, CONTRIBUTING.md note, CODEOWNERS gating, and doc are all exactly the right response to the #3351 documentation gap.

One required fix before merge: the TU map in docs/architecture/mainwindow-decomposition.md is missing two of the nine sibling TUs. Both exist in CMakeLists.txt and have opening charters that make the entries easy to write:

Missing TU Charter (from file header)
MainWindow_DspApplets.cpp wirePooDooTiles() + wireDspApplets() — PooDoo RX status tiles, P/CW/PHNE/EQ applets, client DSP family (Compressor / Gate / De-esser / Tube / Reverb / AetherDSP / PUDU TX+RX), TX signal-chain + PUDU monitor wiring
MainWindow_Session.cpp wireDiscovery() / wireRadioModel() / wirePanLifecycle() — LAN/SmartLink discovery, RadioModel connection-state routing, pan-stream lifecycle; seeded as future RadioSession

A contributor looking at the table before adding DSP applet wiring or session-scoped code wouldn't find the right TU — which is exactly the gap this PR is closing.

Side note on #3407: the new "Wiring split mirrors the widget's lifecycle" convention in the doc clarifies our earlier comment. The RxApplet::wfmActivated connection in the constructor is correct per that rule (singleton widget, wired once at construction → stays in MainWindow.cpp). Only the activateWFM() / deactivateWFM() / reflectWfmButtons() bodies still need to move to _DigitalModes.cpp per the decision table.

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

Thanks for this, @ten9876 — surfacing the #3351 decomposition at the project level (point-of-use banners + canonical doc + AGENTS.md/CONTRIBUTING + the CODEOWNERS gap-close) is genuinely useful, and the layering across tools is well thought out. The banners are comments so there's no build risk, the AGENTS.md #adding-code-to-mainwindow anchor and the ../../CONTRIBUTING.md / ../../.github/CODEOWNERS relative links resolve correctly, the CODEOWNERS scoping-to-core-only is correct (there were no prior src/gui/ rules), and the "~440 lines" AGENTS.md figure now matches reality (it was stale at "~330").

One substantive issue, since this doc's whole job is to be the map agents consult before routing code:

The TU map is missing two sibling TUs, and the "8 today" count is off. The repo actually has 9 MainWindow_*.cpp siblings; the map in docs/architecture/mainwindow-decomposition.md lists 7. Missing:

  • MainWindow_Session.cpp (Phase 2c) — wireDiscovery() / wireRadioModel() / wirePanLifecycle(); the seed of the future RadioSession aggregate (#3445).
  • MainWindow_DspApplets.cpp (Phase 2d) — wireDspApplets() / wirePooDooTiles(); client-DSP applet + PooDoo tile wiring.

Both are real MainWindow:: members carved out under #3351, so they belong in the map. Concretely:

  1. Add the two rows to the TU map table (the Phase column already fits — 2c/2d).
  2. Update "there are 8 today" (in the When a new TU is warranted section) to 9.
  3. Minor consequence worth a glance: the decision-guide row "Connecting a newly-created radio object (slice/pan/VFO/DSP widget) → MainWindow_Wiring.cpp" slightly overlaps these — pan-lifecycle wiring actually lives in MainWindow_Session.cpp and DSP-applet wiring in MainWindow_DspApplets.cpp. Not blocking, but a one-line note ("session/pan-lifecycle wiring → _Session; DSP-applet wiring → _DspApplets") would keep an agent from landing it in the wrong sibling.

An incomplete map is the one failure mode that undercuts the goal here — an agent looking for where session/discovery or DSP-applet wiring goes wouldn't find a home and would likely default back to MainWindow.cpp, exactly what this is meant to prevent. Worth a quick pass to enumerate the siblings straight from ls src/gui/MainWindow_*.cpp so the map can't drift. Everything else looks good.


🤖 aethersdr-agent · cost: $6.0137 · model: claude-opus-4-8

…#3564 review)

NF0T (blocking) and the bot both caught that the TU map listed only 7 of the 9
MainWindow_*.cpp siblings. Root cause: the original list was enumerated from the
refactor/3351-phase2b-spots branch, which predates phases 2c/2d.

- Add MainWindow_Session.cpp (Phase 2c — wireDiscovery/wireRadioModel/
  wirePanLifecycle; seed of RadioSession #3445) and MainWindow_DspApplets.cpp
  (Phase 2d — wirePooDooTiles/wireDspApplets) to the TU map.
- Decision guide: split the generic "wire a new radio object → _Wiring" row so
  discovery/connection/pan-lifecycle routes to _Session and DSP-applet/PooDoo
  wiring routes to _DspApplets (the overlap the bot flagged).
- Fix the count: "8 sibling TUs" → 9 (10 files include MainWindow.h).
- Complete the condensed enumerations in AGENTS.md (routing cell) and
  CONTRIBUTING.md (sibling list) to match.

Verified the map against `ls src/gui/MainWindow_*.cpp` — all 9 present.

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

ten9876 commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator Author

Fixed in cea5aaa4 — thanks both, this was a real gap.

Root cause: I enumerated the sibling list from the refactor/3351-phase2b-spots branch, which predates phases 2c/2d — so MainWindow_Session.cpp and MainWindow_DspApplets.cpp were silently dropped. Exactly the "incomplete map sends an agent back to MainWindow.cpp" failure mode this PR is meant to prevent.

Changes:

  • TU map now lists all 9 siblings — added MainWindow_Session.cpp (2c — wireDiscovery/wireRadioModel/wirePanLifecycle, seed of RadioSession Design discussion: single AetherSDR instance, two radios — brief from @nigelfenton #3445) and MainWindow_DspApplets.cpp (2d — wirePooDooTiles/wireDspApplets).
  • Decision guide (@aethersdr-agent's point 3): split the generic "wire a new radio object → _Wiring" row so discovery/connection/pan-lifecycle → _Session and DSP-applet/PooDoo wiring → _DspApplets, with explicit "(not _Wiring)" markers.
  • Count corrected to 9 siblings (10 files include MainWindow.h).
  • Completed the condensed enumerations in AGENTS.md and CONTRIBUTING.md to match.

Verified the map against ls src/gui/MainWindow_*.cpp — all 9 present, so it can't drift on this pass.

@NF0T — re your #3407 side note: agreed, and the activateWFM/deactivateWFM/reflectWfmButtons body move to _DigitalModes.cpp is already done in #3562 (open). The RxApplet::wfmActivated constructor connection stays put, which the new "wiring split mirrors the widget's lifecycle" convention now documents as correct.

Ready for re-review.

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

Thanks for this, @ten9876 — this is a well-targeted bit of documentation hygiene. The "documented only inside each sibling's header comment, which you see after opening the wrong file" framing is exactly the gap, and surfacing it at the point of use is the right instinct.

I verified the structural claims against the tree and they hold up:

  • TU map is accurate. All nine MainWindow_*.cpp siblings plus MainWindowHelpers.{h,cpp} and MainWindowShortcutState.h exist exactly as listed; the "9 siblings / 10 files include the header" counts are correct.
  • The AGENTS.md line-count bump is real, not a typo. AGENTS.md on main is already 407 lines, so "~330" was stale; 407 + ~33 added ≈ "~440". Good catch correcting it.
  • CODEOWNERS does what the PR claims. The two exact-path lines are appended last, so under last-match-wins they gate only MainWindow.{h,cpp} to @aethersdr/maintainers while the sibling TUs fall through to the * Tier-3 reviewer default — matching the stated "deliberately broad" intent. The inline comment warning against a future MainWindow* glob is a nice touch.

Two minor, non-blocking points:

  1. The MainWindow.cpp banner's top rule line looks UTF-8-corrupted. In the diff, that first line's box-drawing run breaks with replacement characters (───���───) partway across, whereas the MainWindow.h banner is clean. It's harmless to the build (it's a comment), but a little ironic in a banner whose whole job is to look clean to everyone who opens the file — worth re-saving that line as UTF-8 to match MainWindow.h. Please double-check on your end, since this could in theory be a transport artifact rather than the committed bytes.

  2. CODEOWNERS header block vs. the new lines. The carefully-written tier narrative at the top (lines 1–52) maps src/ → Tier 3 reviewers and frames Tier 1 as "governance, security, bot policy." The two new maintainer-gated src/gui/MainWindow.{h,cpp} lines are source code at the maintainer tier — a genuine exception that the top-of-file model doesn't mention. The inline comment above the lines explains why well; consider a one-liner in the header block too (or noting it's an intentional source-code exception), so a reader following the tier model isn't surprised to find src/ files at Tier 1.

Neither blocks merge. Nice work closing the ownership gap the split opened.


🤖 aethersdr-agent · cost: $2.4734 · model: claude-opus-4-8

@NF0T NF0T enabled auto-merge (squash) June 14, 2026 00:07

@NF0T NF0T left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Both items from the CHANGES_REQUESTED are resolved. MainWindow_Session.cpp and MainWindow_DspApplets.cpp are now in the TU map with accurate charters drawn from their file headers, the sibling count is updated in the prose (9 TUs / 10 files), and the decision guide has two new disambiguation rows (_Session.cpp vs _Wiring.cpp for discovery/connection/pan-lifecycle; _DspApplets.cpp vs _Wiring.cpp for client-DSP applets). CONTRIBUTING.md and the AGENTS.md decision table are consistent with the updated map. Approved.

@ten9876 ten9876 merged commit e9f04c7 into main Jun 14, 2026
5 checks passed
@ten9876 ten9876 deleted the docs/mainwindow-decomp-notify branch June 14, 2026 00:12
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.

2 participants