a73x

docs/superpowers/plans/2026-09-05-component-separation.md

Ref:   Size: 8.8 KiB   History

# Component separation and independent development

The user authorized another separation sprint after interaction ownership commit
`efc99d5`, followed by a clearer division of ownership so daemon and GUI work can
proceed independently. Prior recorded-demo acceptance remains pending; this is
explicit advancement authorization, not retrospective demo approval.

Status: implemented, reviewed and validated. All final delivery gates passed;
the retained recording awaits user acceptance. Ownership roles are proposed;
no people are assigned.

## Scope and contract

Opening inspection found the daemon and GUI already independent in the production
module graph. The shared client facade serves actual common transport/discovery
needs; splitting it would require a larger change without evidence of benefit.
No separate preparatory cleanup was needed.

The smallest useful change is independent component testing and an independently
owned native policy module:

| Module | Owns | Declared production imports |
| --- | --- | --- |
| `native_core` | workspace, runtime, picker, persistence, interaction | client, term |
| `native` | frame adapter, font/atlas/painter, frame timing | native_core, client, term |
| `daemon` | existing server core and children | Unchanged |

`src/gui/native_core.zig` is the only module root that reaches its five child
files by relative import. The frame adapter consumes them through the declared
`native_core` import. Compatibility aliases in `native.zig` preserve its public
API without creating a second source owner. Native layout, runtime, shared
client behavior and all controls remain unchanged.

`native-core-test` compiles its own test artifact with shared QUIC support and
no window/font libraries. `native-test` runs that same artifact plus the
frame/painter tests. `daemon-test` and `client-test` reuse their existing run
nodes from aggregate `test`; there is no second test implementation or duplicate
artifact. All native targets remain opt-in.

Root owned the build graph, Makefile, independent validation and documentation.
Luna implemented and wired the core root and GUI imports. Terra independently
reviewed both changes and the ownership/test contracts. Fresh short contexts
were used, and recorded `turn_context.model` metadata confirmed Luna and Terra
immediately at startup. Closing cleanup corrected a forbidden window-library
name in the new root's comment, removed a redundant test alias and updated the
build comments. No production behavior was changed during cleanup.

## Acceptance and evidence

The final integrated ReleaseSafe build passed 47 native tests: 20 in the
independent core and 27 in the frame/painter suite. The new root contributes one
registration test; existing test coverage is retained.

Independent compilation was tested in a disposable snapshot containing the final
module/build changes. Each deliberate failure has a matching negative control:

| Snapshot condition | Expected independent result | Negative control |
| --- | --- | --- |
| Frame contains a deliberate compile error | `daemon-test native-core-test` pass | `native-test` fails with the planted GUI diagnostic |
| Daemon contains a deliberate compile error | `native native-test` pass | `daemon-test` fails with the planted daemon diagnostic |
| Window-library pkg-config search paths are empty | `native-core-test` passes | `native` fails to resolve its required packages |

All six checks passed. The snapshot files were restored in `finally`; the shared
checkout was never modified by the probes. This proves compile/test isolation,
not that shared wire changes can be made without coordinating their semantics.
Repository-wide source rules and shared build-file validity still apply.

Final gates use `ZIG_GLOBAL_CACHE_DIR=/tmp/muxg-zig-cache`, the pinned compiler,
and authorized local socket/PTY access:

| Gate | Result |
| --- | --- |
| `deps/zig/zig build install native native-test -Doptimize=ReleaseSafe -p dist/native-component-release --summary all` | Passed; both release binaries from one graph, 47 tests |
| Independent compilation probes above | Passed |
| `make native-e2e` | Passed; 62 scenarios |
| Prior-daemon compatibility | Passed separately; 63 total native integration scenarios |
| Real OpenSSH/Wayland recovery | All five groups passed at 200% |
| Wayland scale and raw-output stress | Scale passed; stress passed on normal-logging repeat, earlier misses retained |
| `make check` / `make ci` | Passed on the final fixture repair |

The full CI attempt exposed the recurring terminal picker fixture race from the
prior sprint. Its script pressed Enter and immediately selected row 2 while the
host poll could still contain only session 0. That selection was clamped; waiting
for silence afterward could not repair it. The repaired script waits for the
actual unselected born-session row (`2  1`) before pressing 2, retaining the
selected-row and holder-count assertions and all original timeouts. Terra
rejected an initial wait on session 0 because it would accept the stale list.
The focused 15-scenario host group and the subsequent independent full CI run
both passed.
No terminal production code changed.

The first Wayland stress run narrowly missed the 20 ms frame p99 budget at
20.176 ms. The previously validated interaction release also missed it on that
compositor (20.567 ms before reopen, 20.270 ms afterward). After restarting the
owned compositor with normal logging, preserving its geometry, scale and GLES2
renderer settings, the final release passed unchanged budgets: 18.992 ms before
reopen and 18.246 ms afterward. This does not establish the exact cause of the
variation. Debug startup identified NVIDIA GeForce RTX 3080; normal-logging
startup did not repeat the device identification. Keep that provenance limit
with the measurement rather than inferring a performance improvement.

The successful 30.1-second stress run read 104.6 MB. Sampled input-to-painted
maxima were 55.5 ms on the shared daemon and 55.4 ms on the separate daemon,
94 samples each. The 5 ms polling interval and observation overhead make these
upper bounds. Runs used an isolated compositor without concurrent GUI fixtures
or recording, and no budget was relaxed. No new macOS result is claimed.

A 56.8-second actual GUI recording uses the final release at 200%, H.264
1100×700 with no audio. It shows the unchanged menu, resize, delayed End,
restoration and replacement behavior through three continuous clips with two
restart cuts. Input is through ordinary SDL events; this is not a new
compositor mouse-path trial. The fixtures and owned compositor were stopped.
The recording is retained at:
`/home/xanderle/.codex/visualizations/2026/09/05/01a071c2-5767-7790-a335-1a84536c9ca5/native-component-trial.mp4`.

Logs, exact probe commands, both stress failures and the successful repeat,
source/release hashes, recording driver and model metadata are in the sibling
`component-evidence/` directory. User recording acceptance is separate from all
automated checks. No new Tailscale route or payload was published.

## Ownership follow-up

The [ownership proposal](../../component-ownership.md) starts with daemon, native
GUI, and shared wire/client services. GUI policy and rendering now have a usable
internal boundary, but assigning them separate people is optional. Terminal and
browser frontends retain their own responsibilities. Shared build/release and
contract changes require coordination; ordinary internal work uses the focused
component gates and separate worktrees.

No directory reshuffle, repository split, named CODEOWNERS assignment or shared
wire redesign is included. Future assignments should follow these tested module
boundaries and account for mixed folders such as `src/client/` and `src/engine/`.

### Ownership handoff continuation

The user's subsequent “continue” advances the ownership handoff. This is a
documentation slice: reusable role briefs, worktree prerequisites, focused gate
selection and shared-contract handoffs. It does not change the production module
graph or imply acceptance of the retained GUI recording. Human assignments stay
open until names are supplied.

Opening review found one stale module table in `CLAUDE.md`; it now lists
`native_core` and its policy files separately from `native` and its painter files.
The ownership guide remains the single source for role briefs and handoffs.
Closing review checks the guide against the actual module roots and Makefile,
including mixed-directory ownership and the limits of focused test coverage.

The completed handoff passed independent review and `make ci` (including all
terminal integration scenarios, ten agent scenarios and throughput). No native
source or build wiring changed; the prior native validation and recording remain
the applicable runtime evidence. The focused Make recipes were independently
checked against the guide. Logs and model metadata are retained in
`ownership-evidence/` beside this thread's visualization artifacts.