docs/native-sprint-workflow.md
Ref: Size: 12.3 KiB History
# Native client sprint workflow
The repository's [sprint-delivery skill](skills/sprint-delivery/SKILL.md) supplies
the shared workflow and instructions for agents with different tool capabilities.
Any agent can read it directly; no personal skill installation is required.
Use this formula for each native client sprint. The tiling
[spec](superpowers/specs/2026-09-05-native-tiling-design.md) defines behavior;
the [delivery plan](superpowers/plans/2026-09-05-native-tiling.md) breaks it into
packages. Keep one sprint active, ending in a working demo and explicit acceptance.
1. **Review and scope.** Read the previous sprint's actions in [RETRO.md](../RETRO.md).
Produce the reuse and ownership map required by the shared skill, using the
[component briefs](component-ownership.md) and actual code/callers as evidence.
Define the smallest useful deliverable, its acceptance scenarios, and what
belongs to later sprints. Use existing agreements for material scope and
destructive-action semantics; clarify only unresolved points before
implementation. For other ergonomic choices, record the proposed defaults,
implement them as trial behavior, demonstrate them, and adjust them from the
resulting feedback. Record whether feedback comes from the recorded demo or a
hands-on trial; hands-on feedback is optional.
2. **Tidy the starting point.** Inspect the code the sprint will touch. Make small,
behavior-preserving refactors that simplify the planned work, review them,
run affected checks and `make check`, and commit separately. No cleanup quota:
if the code is ready, record that. Substantial refactors become explicit
packages; unrelated debt goes into the backlog.
3. **Assign a bounded pair.** Reuse one implementer and one independent adversarial
reviewer. Give them the package, relevant files, ownership boundaries,
acceptance criteria, and each other's names. Root owns integration, independent
acceptance, user communication, and commits. Delegate another task only when
it can progress independently. Load skills only where they help the work.
Cost default: explicitly select GPT-5.6 Luna for bounded implementation and
GPT-5.6 Terra for adversarial review. Start with task-specific context instead
of inheriting the full conversation. Escalate a concrete unresolved problem
to a stronger model when needed. Root coordinates and integrates; assign each
investigation one owner so agents do not repeat it independently by accident.
Check each agent's model immediately after startup. Prefer recorded session
`turn_context.model` metadata when available; distinguish it from the requested
spawn setting, and do not rely on an agent's self-description. Retain available
token counters with cached input identified separately; counters are not a
monetary bill. After a sandbox denial, use the authorized validation route
instead of repeating the same blocked suite or streaming its full failure log.
4. **Build a functional slice.** Establish the smallest model/interface contract,
then connect actual input, rendering, and daemon behavior. Keep changes small
enough to review. Avoid expanding into later sprint features.
5. **Resolve concrete review findings.** Apply the shared skill's correctness and
structural review criteria. The reviewer supplies a scenario or structural
finding, consequence, and expected result directly to the implementer. The
implementer returns a fix and evidence, or a reason the finding does not apply.
Root adjudicates disagreement against requirements and observed behavior. Agreement
is not a substitute for independent validation.
6. **Validate through real boundaries.** Drive ordinary SDL events into an isolated
GUI using `test/native_tiling.py`'s Rig. Compare actual framebuffer pixels and
independently queried daemon state, including every pane's PTY dimensions.
Exercise failure paths and event ordering. Observation helpers must not repair
the state under test. Use real Wayland at high DPI and a scale transition;
exercise SSH/QUIC when changes affect their behavior. Create and clean up only
owned fixture sessions and daemons.
An isolated compositor can exercise scale changes without changing the user's
monitor. Start it in its own process session. Wait for a window to map before
resizing it, or use a compositor mapping rule for fixture geometry. Record the
compositor's renderer: a software compositor is useful for functional checks,
but does not establish hardware frame-time performance. Run performance checks
separately from recordings and other GUI fixtures on that compositor.
`test/native_scale.py MUX MUXG --output HEADLESS-1` runs the retained
200%/100%/150%/200% scale scenario, including drag cancellation, real PTY sizes
and framebuffer checks. Set `XDG_RUNTIME_DIR`, `WAYLAND_DISPLAY`, and `SWAYSOCK`
to an owned isolated Sway compositor and pass both release binaries. The script
restores the output's original scale and closes its fixtures on exit.
For responsiveness, run `make native-stress` on Linux. It builds both binaries
in ReleaseSafe from the same build graph and drives raw `cat /dev/random` in
one pane while probing neighbours on the same daemon and a separate daemon.
It checks ongoing output, input through completed painted state, menus,
divider resizing, and close/reopen under load. Daemon inspection happens after
the timed paint observation. Report sampled latency as an upper bound; frame
timing alone does not establish input responsiveness.
For lifecycle work, independently observe the daemon after Detach and End,
including another attached client. Change focus and open another modal while
a destructive request is pending; a later confirmation must still identify
its original target. For persistence, retain original bytes across real
permission failures, reopen from a different working directory and scale, and
keep a sentinel in the terminal client's layout file.
For SSH handoff or reconnect changes on Linux, also run the real OpenSSH gate
from the [SSH follow-up plan](superpowers/plans/2026-09-05-ssh-error-classification.md).
`test/native_ssh.py` accepts the release daemon and GUI paths and uses its own
loopback sshd, keys, state, and sessions. Verify authentication refusal on both
restoration and reconnect, explicit Retry after correcting credentials,
unavailable-host recovery, join-only restoration, and bounded shutdown.
7. **Refactor the integrated result.** Reserve this as work, even after the opening
cleanup. Remove duplication, superseded paths, unnecessary state, and temporary
scaffolding exposed by implementation. Review the result again. For retained
debt, record location, consequence, reason, and next owner or trigger. Correctness
failures cannot be deferred past acceptance.
8. **Freeze and run final gates.** Stop source edits before compilation. Run the
required repository and native gates on the final result, retaining logs:
```sh
export ZIG_GLOBAL_CACHE_DIR=/tmp/muxg-zig-cache
make check
make ci
deps/zig/zig build native-core-test -Doptimize=ReleaseSafe
deps/zig/zig build native native-test -Doptimize=ReleaseSafe
make native-e2e
make native-stress # Linux raw-output responsiveness
```
`make ci` excludes native tests. Use the pinned compiler. Do not overlap
other builds in the same checkout with its `make check` stage: `test/bans.sh`
temporarily plants invalid source files to verify the source rules. Wait for
that stage to finish before starting native builds or integration tests.
The focused `make native-core-test` gate compiles workspace, runtime, picker,
persistence and interaction without window/font libraries. `native-test`
includes that same test artifact plus the frame/painter suite. Daemon and
shared client work can use `make daemon-test` and `make client-test`, which
reuse their artifacts from the aggregate unit gate. These focused commands
complement the full delivery checks above.
A sandbox denial is not a product failure: run required local socket/PTY checks with the appropriate
authorized permissions. Rerun affected gates after meaningful changes; do not
repeatedly run broad suites without a new reason.
9. **Record and serve the local demo.** Use Rig with `MUXG_VIDEODRIVER=wayland`
and the current compositor environment. Create fixtures, focus the owned GUI,
and drive the same user controls being delivered. Capture the actual compositor
window continuously; on Sway, find its rectangle by PID with `swaymsg -t get_tree`
and pipe repeated `grim -g GEOMETRY -s 1 -t ppm -` frames to ffmpeg. Encode H.264,
`yuv420p`, even dimensions, and `+faststart`, without audio. Stop recording
before closing the window so another application cannot enter the recording.
A slideshow of screenshots is useful evidence but is not a screen recording.
**Deliver a review webpage for every functional slice.** The page is the
primary handoff link and contains:
- The sprint goal and a concise account of what was achieved.
- An embedded recording of the actual application, with playback controls
and a direct video link. Include duration, recording environment and any
restart cuts; a screenshot may serve as its preview.
- What the user can see or try, and any controls needed to review it.
- Validation results and open issues, clearly separating implemented,
validated and accepted work. Preserve failed checks and material limits.
- What belongs to the next slice and what feedback is needed on this one.
Keep the page usable on desktop and mobile. Retain its source beside the
sprint records and its video outside temporary fixture directories. Verify
page loading, video metadata and seeking. Serve the page and its assets on
localhost by default, using a loopback HTTP server with byte-range support.
Give the user the local webpage URL, with the direct video link on the page.
Publishing is optional and happens only when explicitly requested; do not
ask about publishing during routine sprint delivery. Preserve unrelated services.
Build both demo binaries together in an isolated release prefix:
```sh
make install INSTDIR=dist/native-release BINDIR=dist/demo-bin
```
The rebased install target builds both binaries in ReleaseSafe; the isolated
`BINDIR` keeps demo setup out of the user’s installed executables. Pass
`dist/native-release/bin/mux` and `dist/native-release/bin/muxg` to Rig.
`make ci` can leave a Debug daemon in `zig-out`; `make native` builds only the
GUI. Checking just `muxg --version` therefore cannot establish the daemon's
build mode. Use the build graph's artifact paths for automated stress tests.
For a close/reopen demo, stop the recorder before closing the first window and
resume on the new owned window after launch. Join those continuous clips and
disclose the restart cuts; do not capture the intervening desktop.
For mouse acceptance, include the cursor with `grim -c` and drive the
compositor's virtual-pointer motion/button events. SDL-injected input can
validate application routing but does not demonstrate the compositor input
path. Cursor-warp commands can move the visible cursor without delivering
held-button motion. Verify actual divider movement and release, then check PTYs.
Verify playback and HTTP range responses. Retain the recording outside
temporary fixture directories and record the server's teardown command.
10. **Close honestly.** Inspect the final diff, commit validated work, and provide
the review webpage with the demo, controls, test results, and material limits.
User demo acceptance is
distinct from passing automation. Record whether acceptance covers a recording
or a hands-on trial, and capture any requested ergonomic adjustments separately.
Update the spec/plan status and RETRO.md with resolved findings and checkable
next-sprint actions. Mark acceptance only when given; a recorded-demo approval
does not imply hands-on feedback. On acceptance, stop that demo's owned
server and remaining GUI, recorder or compositor fixtures; remove any sharing
route created at the user's request. Recheck process ownership and verify
teardown. Preserve unrelated services and retain the page, recording and
validation evidence. Then begin the next authorized sprint with step 1.