feat(aetherd): establish the Stage 3 control protocol boundary - #5109
Merged
ten9876 merged 10 commits intoSep 3, 2026
Conversation
There was a problem hiding this comment.
Pull request overview
This PR establishes the first Stage-3 slice of the aetherd control-protocol boundary by introducing a bounded, transport-neutral v1 JSON envelope/handshake implementation, a current-user local IPC transport, and build-system/CI changes that enforce a QtWidgets-free engine/daemon.
Changes:
- Add the v1 control protocol codec + observe-only handshake/capability service, plus a
QLocalServertransport and focused negative/limit tests. - Split desktop-only QtWidgets-dependent code out of
aethercoreintoaetherdesktop_support, and introduce a QtCore/QtNetwork-onlyaetherdexecutable. - Extend engine-boundary checks and refresh/CI-enforce the generated aetherd touchpoint catalogue.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tools/check_engine_boundary.py | Expands EB3 scanning to include src/ app-shell files and refreshes the vendor-include baseline. |
| tests/tests.cmake | Registers new control-protocol tests and ensures desktop-only tests link through aetherdesktop_support. |
| tests/local_control_server_test.cpp | Adds transport/handshake/limits regression coverage for LocalControlServer. |
| tests/control_protocol_codec_test.cpp | Adds envelope/limit/response-shape tests for ControlProtocolCodec. |
| src/core/EibiClient.cpp | Removes a GUI-only dependency include from core. |
| src/core/control/LocalControlServer.h | Introduces the current-user local IPC server API and limits struct. |
| src/core/control/LocalControlServer.cpp | Implements local IPC listen/endpoint hardening, handshake deadline, client limits, and backpressure disconnect. |
| src/core/control/ControlService.h | Defines the transport-neutral handshake/capabilities service interface. |
| src/core/control/ControlService.cpp | Implements observe-only hello + capabilities.get flow and fail-closed dispatch. |
| src/core/control/ControlProtocolCodec.h | Defines the v1 envelope limits, request/parse result, and response helpers. |
| src/core/control/ControlProtocolCodec.cpp | Implements bounded JSON validation + envelope parsing/serialization. |
| src/core/AutomationServer.h | Moves setters out-of-line to support dependency decoupling. |
| src/core/AutomationServer.cpp | Adds out-of-line setter definitions. |
| src/aetherd/main.cpp | Adds the initial headless aetherd executable with local socket option and server start. |
| docs/architecture/aetherd-touchpoints.md | Updates touchpoint tagging completeness and expands tag notes. |
| docs/architecture/aetherd-touchpoint-tags.json | Updates/extends the generated tag catalogue. |
| docs/aetherd-control-protocol-v1-design.md | Adds the normative v1 contract document for Stage 3. |
| CMakeLists.txt | Builds new control components, adds aetherdesktop_support, introduces aetherd, and enforces “no QtWidgets” for engine/daemon. |
| AGENTS.md | Updates Stage-3 status and clarifies “no QtWidgets” in aethercore/aetherd. |
| .github/workflows/static-checks.yml | CI-enforces touchpoint-manifest freshness via gen_touchpoint_manifest.py --check. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Summary
aetherdexecutable and remove QtWidgets fromaethercoreaetherdesktop_supportEibiClient.cpp's now-unusedThemeManagerinclude as part of that desktop dependency splitIRadioBackendimplementorsSafety and scope
This is the first implementation slice of Stage 3, not the complete thin-client protocol. It deliberately advertises only
observe; it exposes no model resources, subscriptions, non-TX mutations, remote transport, credentials, or transmit method. Supplied authentication is rejected until a verifier exists. TX remains unavailable until the Stage 4 arbiter and authorization funnel are implemented.The desktop continues to consume models directly.
AutomationServerremains the desktop test bridge and is not promoted into the permanent protocol.aetherdis a build/test skeleton in this slice; it is not installed, packaged, or auto-started yet.aetherdis QtWidgets-free, but it inherits the engine's current runtime surface: Qt Concurrent, Gui, Multimedia, SerialPort, WebSockets, DBus, and qtkeychain when enabled, in addition to Core and Network.Qt6::Guiis currently required becauseBandPlanManagerandDxccColorProviderexposeQColor. Removing that edge and narrowing the other transitive dependencies are explicit later burndown targets rather than part of this skeleton PR.The EB3 baseline additions freeze vendor includes already present on the relevant
mainrevision before this PR classified those headers. The current-main ANAN/RTL additions are documented againstb1499334.AGENTS.mdnow matches the checker's narrow rule: a vocabulary-classification rebaseline must prove every added include predates the classification, document that evidence, and receive explicit maintainer review; the exact set is shrink-only afterward. That maintainer ruling remains open.Refs #3849.
Validation
upstream/main(f41dc755) per the repository stale-branch policy; preserved both the Stage 3 QtWidgets graph assertion and upstream's new CPack configuration in the only conflictcontrol_protocol_codec_testlocal_control_server_testautomation_device_diagnostics_testlocal_control_server_testbinds the productionQLocalServercurrent-user socket and covers observe-only capability negotiation, invalid JSON, unsupported versions, handshake timeout, client cap, oversized input, backpressure, stale endpoints, and crash recoveryidon uncorrelated errors fails the codec testLocalControlServer::Q_OBJECTfails the server meta-object testaetherdesktop_supportimplementation after the library splittools/check_engine_boundary.py --strict(0 blocking findings)tools/check_test_registration.py --stricttools/gen_touchpoint_manifest.py --check(211/211 current touchpoints classified)--checkinstead of silently regenerating an incomplete catalogueQt6::Widgetsfails configure through the recursiveaethercore/aetherdtarget-graph assertiongit diff --checkAetherSDRandaetherdMach-O outputsaetherdlinks the documented engine runtime modules and does not link QtWidgetsreadOnly=true,txAllowed=false, radio disconnected, and MOX/tune/transmit all false0a006f1a: Linux, Windows, macOS, and Static ChecksNo live-radio control or TX proof was performed.