Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Run Targets, Init Mandate, And Default-Run Integration

This backlog captures three intertwined make-target and manifest-policy requirements raised against the current Makefile and system-*.cue set. They share manifests, harness scripts, and review surface, so they should land as one mainline track rather than scattered fixes.

Policy Statements

  1. make run-* targets only start QEMU. Any scripted input driving, transcript assertion, timeout-based pass/fail, log greps, or harness script wrapping must live outside the run-* recipe – either in a sibling test-* target or in a host harness invoked by the user directly.
  2. init usage is MANDATORY in every boot manifest. The boot init binary must be init (the capos-init ELF). Service or demo binaries such as capos-shell, credential-store, terminal-session, network-client, revocable-read, memoryobject-shared-parent, and per-demo entrypoints must be declared as services and launched by init, never as the top-level init binary.
  3. make run stays the default user-facing target demonstrating a sane, safe, full-featured (as of the current state) capOS instance. When a milestone introduces a user-visible common service or binary, it must be integrated into make run – either auto-started or advertised through MOTD instructions describing how the operator reaches it – as part of the milestone’s doc-update gate.

Current State

run-* recipes that contain test logic

Snapshot from Makefile at branch base. All targets in this list embed input drivers, asserts, or harness invocations and therefore violate policy 1:

  • run-smoke, run-uefi, run-net
  • run-spawn, run-shell, run-restricted-shell-launcher
  • run-chat, run-adventure, run-terminal
  • run-credential, run-login, run-login-setup, run-local-users
  • run-network-client, run-tcp-listen-authority
  • run-telnet, run-telnet-vm
  • run-revocable-read, run-memoryobject-shared
  • run-ssh-host-key, run-ssh-authorized-key, run-ssh-public-key-session, run-ssh-public-key-auth, run-ssh-feature-policy, run-ssh-gateway-terminal-host, run-ssh-gateway-terminal-host-vm
  • run-ringtap-failing-call
  • run-measure

Compliant run-* recipes (QEMU-only):

  • run – interactive, manifest-driven, terminal on stdio.
  • run-display – interactive variant with QEMU display.

Manifests violating the init mandate

Init binary is something other than init:

  • system-smoke.cue – init binary capos-shell
  • system-shell.cue – init binary capos-shell
  • system-login.cue – init binary capos-shell
  • system-login-setup.cue – init binary capos-shell
  • system-local-users.cue – init binary capos-shell
  • system-credential.cue – init binary credential-store
  • system-terminal.cue – init binary terminal-session
  • system-network-client.cue – init binary network-client
  • system-revocable-read.cue – init binary revocable-read
  • system-memoryobject-shared.cue – init binary memoryobject-shared-parent

Manifests already compliant: system.cue, system-adventure.cue, system-chat.cue, system-spawn.cue, system-measure.cue, system-restricted-shell-launcher.cue, system-telnet.cue, system-tcp-listen-authority.cue, all system-ssh-*.cue.

Default-run feature integration gap

make run boots system.cue, which already wires the anonymous shell, the login flow with the seeded password verifier in MOTD, the chat/adventure demos, chat/adventure spawn instructions, and the host-local Telnet gateway. Milestones still absent from the default path or its MOTD are local-user setup, terminal-session focused proofs, SSH gateway terminal host, and any future SSH shell milestone.

The default make run recipe now attaches virtio-net with 127.0.0.1:2323 -> guest :23 forwarding for the Telnet gateway. Other network-backed milestones, such as the SSH gateway terminal host and future SSH shell, still require their own safe default forwarding or an explicit deferral before they can be called integrated into make run.

Open Gates

Gate A: Naming and contract

  • Decide the rename split. Pick one of the two consistent options and apply it uniformly: - Strict: run and run-display are the only run-* entrypoints; every other current run-* recipe (including run-uefi, run-net, run-measure) becomes test-* regardless of whether its body is reduced to a plain QEMU start, because the policy is enforced by name, not by current contents. - Permissive: any QEMU-only recipe against the default manifest with documented firmware/device flag variations may keep a run-* name, with test-* reserved for recipes that script input or assert output. Pick this only if the policy text in CLAUDE.md/REVIEW.md can spell out the boundary unambiguously so reviewers do not have to relitigate the split per target.
  • Document the chosen policy in CLAUDE.md “Build and Test” section and REVIEW.md so future targets are added under the right prefix without case-by-case judgement.

Gate B: Init mandate enforcement

  • For every non-compliant manifest above, restructure so the init binary is init and the previous top-level binary becomes a service. Preserve the focused-proof intent: the service receives the same scoped caps it had as init, init holds only the bootstrap authority needed to spawn and supervise it, and the smoke/proof transcript continues to assert the same boundary properties.
  • Add a manifest-loader validation rule (or mkmanifest check) that rejects any manifest whose initConfig.init.binary is not init. The rule should also reject the field being missing. Update host tests to cover the negative case.
  • Update every doc that currently describes shell-led or service-led manifests as having the service as init. A 2026-04-28 12:48 UTC docs pass reconciled the current default system.cue path as standalone-init-owned while preserving focused shell-led smoke descriptions where system-smoke.cue and system-shell.cue still boot capos-shell directly. Gate B remains open until the focused manifests themselves are migrated or documented as explicit exceptions, the loader/manifest validation rule lands, and a final re-grep confirms no stale default-boot wording remains.

Gate C: Test split

  • Move every scripted input driver, transcript assertion, timeout wrapper, harness invocation, and log grep currently embedded in a run-* recipe into a new test-* recipe. The run-* side, where retained, becomes a one-line qemu-system-x86_64 ... $(QEMU_COMMON) $$serial_args invocation against the same ISO.
  • Keep tools/qemu-*-smoke.sh, tools/qemu-*-harness.sh, and the ringtap viewer assertion out of run-* recipes. They are acceptable inside test-* recipes or as standalone host scripts.
  • Update CI hooks, developer docs, and WORKPLAN.md checkpoints that reference make run-<x> for verification to call make test-<x> instead. Audit REVIEW_FINDINGS.md and the recent changelog updates so historical entries stay accurate while new gates use the renamed targets.

Gate D: Default-run feature integration

  • Define an integration checklist that every milestone’s doc-update step must satisfy before close: either auto-start the new user-visible service from system.cue with safe defaults, or extend the MOTD with a clear, copy-pasteable instruction block describing how to reach the feature from the default boot.
  • Backfill the integration for already-shipped milestones whose user-visible services are still absent from make run: local-user setup, terminal-session, and the SSH gateway terminal host slice. Telnet gateway is already wired into system.cue, MOTD, and default host-loopback QEMU forwarding. For each remaining milestone, either wire the service into system.cue (preserving the default-safe posture) or add a MOTD section with the exact command. Network-backed milestones must also record the QEMU device and forwarding posture. Telnet gateway is already wired through the default make run virtio-net path with host-loopback forwarding. SSH gateway terminal-host integration remains deferred until its production/non-loopback gates pass or a separate host-local development forwarding rule is reviewed. A MOTD-only addition is not sufficient for a network-backed milestone.
  • Add the integration checklist to the “Stage Implementation Workflow” section of CLAUDE.md so future milestones cannot land without it.

Interaction With Paused SSH Shell Gateway Milestone

WORKPLAN.md currently pauses the SSH Shell Gateway behind Service Object Identity Migration. When SSH work resumes, it will still have a visible goal of make run-ssh-shell and additional make run-ssh-* proofs. Without an explicit checkpoint, that milestone can land more non-compliant run-* recipes (scripted host harnesses, transcript asserts, network-only smokes) before this backlog is applied.

  • Before the SSH Shell Gateway milestone closes, add Gate A’s naming decision and Gate C’s test split as a milestone-level prerequisite: the user-visible target name (run-ssh-shell vs test-ssh-shell) and the location of any host harness must conform to the chosen rename split, and make run integration must be addressed under Gate D rather than left as a separate run-ssh-* recipe. Record the decision in the SSH milestone checkpoint or block its closeout.

Sequencing

Gate A is purely policy and naming and unblocks the others. Gate B (init mandate) and Gate C (test split) can proceed in parallel on separate branches per affected manifest area, because they touch different files: B rewrites system-*.cue and may add services to init/src/main.rs, while C touches Makefile and the tools/qemu-* harnesses. Gate D follows once the test split lands so MOTD updates land alongside system.cue changes without competing with make run’s recipe.

Out Of Scope

  • Renaming or relocating tools/qemu-*-smoke.sh and tools/qemu-*-harness.sh scripts. They stay where they are; only their callers change.
  • Producing a new test runner that aggregates all test-* targets. That is a separate CI ergonomics task.
  • Reworking the focused-proof transcript content. The intent is to preserve current proof coverage, not extend it.