Skip to content

[Frontier] [CUT15-01] Install S15 fresh on jit-vm with owner acceptance and a recoverable install #341

Open

Description

@chayapats

[Frontier] [CUT15-01] Install S15 fresh on jit-vm with owner acceptance and a recoverable install

Body revised on 2026-11-03 for the owner's final decisions; the previous body (Pi-era target, Proxmox jit-work VM) remains in the issue edit history.

Parent

S15 — #316. Canonical spec: docs/specs/S15-conversational-autonomy.md.

Model tier

Frontier: production installer, service identity, host prerequisites for a protected nested VM, rollback of a failed install and owner acceptance of an exact build/policy.

Owner decisions (2026-11-03, final)

  1. Retire the Pi. Jit runs on the Proxmox VM jit-vm only. Start fresh: no Pi data (legacy or S14) is migrated. The Pi is not changed by this work; the owner retires it after cutover.
  2. Single-host topology: the S15 controller runs on jit-vm, and the working VM is a nested KVM guest that Jit creates and manages there (VM15-02 [Frontier] [VM15-02] Run the working VM as a Jit-managed nested KVM guest on the controller host #366, SETUP15-01 [Frontier] [SETUP15-01] Create the working computer automatically during S15 setup on KVM hosts #369). Owner-supplied VMs stay optional for extra compute (POOL15-01 [Frontier] [POOL15-01] Place work across several enrolled working computers in one team pool #370).
  3. Telegram bot removed 2026-11-06 (ADR 0085); no channel setup is needed.
  4. jit-vm has 10 vCPU / 20 GB (verified 2026-11-03: 10 CPUs, 19 GiB usable, vmx/AVX, no AVX2, /dev/kvm usable, 195 GB root with ~152 GB free).
  5. The old S14 test installs on jit-vm (service users jit/jit-s14, units, subuid ranges, Podman storage, 16 loop disks, evidence files) are test-only and are removed before the production install (authorized).

Context to read

AGENTS.md; CONTEXT.md; docs/agents/workflow.md; docs/specs/S15-conversational-autonomy.md; docs/adr/0064, 0067; install.sh; ops/package/installer/**; ops/evidence/s15-install-service.ts (the arm64 staging installer to generalize); src/s15/main.ts (S15RuntimeConfig, runS15); docs/runbooks/s14-default-cutover.md; tests/runtime-selection.test.ts.

Deliverable

  1. Installer (code, Refs #341): install.sh --s15 explicitly selects the S15 runtime as a separate installation (service identity, state, unit, journald namespace), never reinterpreting legacy/S14 configs or touching their data. It installs the host prerequisites the nested working VM needs (QEMU packages, kvm group for the service identity, lingering user manager), installs the exact release, generates the credential-free S15 runtime config without owner input, runs init, enables the service and lets setup create the working computer automatically. A failed install leaves a recoverable state: the new unit is stopped/removed, the prior release (if any) stays active, other installations are untouched, and re-running repairs idempotently. --s15 --uninstall stops/removes the service and retains data like the other runtimes. Upgrade switches the release atomically with a health check and rolls back to the previous release on failure.
  2. Live install on jit-vm (orchestrator): remove the old S14 test installs, install the exact final reviewed build, verify health and the automatically created working computer, and record exact SHA/hashes in .local.
  3. Owner acceptance (owner steps, last): owner password, Codex device login for the S15 service identity, the GitHub sandbox token, optional Google consent, review of the exact build/policy/rollback evidence, explicit acceptance, first ordinary conversation in the Web/PWA, then retiring the Pi.

Implementation steps

  1. Extend install.sh/installer with --s15 (mutually exclusive with --s14/--legacy), the S15 plan lines, prerequisites and dry-run coverage.
  2. Generate the S15 runtime config from detected facts (installation id, directories, origin/access model consistent with the S14 installer, the approved Codex subscription route catalog, no policy, no budget, no personal GitHub rule, local working-computer pool).
  3. Install a hardened system unit for the controller; the nested VM runs outside the controller cgroup per VM15-02 so restarts/upgrades do not kill it.
  4. Transactional install/upgrade with rollback of the release symlink and unit on failure; never delete another installation's data.
  5. Runbook docs/runbooks/s15-install.md: install, upgrade, rollback, uninstall, owner steps.

Acceptance criteria

  • install.sh --s15 on a fresh host yields a running S15 controller with a ready working computer and no hand-edited files.
  • Legacy/S14 selection and omitted-runtime configs are never reinterpreted; other installations are untouched (fixtures).
  • An injected failure at each install/upgrade step leaves the prior state recoverable and a re-run repairs it.
  • The live install on jit-vm runs the exact reviewed build with fresh state; old S14 test installs are gone; the Pi is unchanged.
  • Owner acceptance binds the exact build, host, policy revision and activation time; the first Web conversation performs real approved work and human-required gates behave as proved on [Frontier] [EVID15-01] Prove the protected boundaries and the GitHub scenario on the tested build #340.

Tests and evidence

  1. Installer/runtime-selection fixtures (--dry-run --root) for --s15, conflicts with --s14/--legacy, prerequisites, generated config shape and no-secret config.
  2. Failure-injection fixtures for each step → recoverable state; upgrade health-check failure → previous release restored.
  3. Live install log and service/working-computer health on jit-vm in .local, summarized here.
  4. Owner acceptance record (owner step).

Requirements

FR-18/23/35/36/37/38; NFR-04/07/08/10/12/14. Acceptance: S15-AC16.

Blocked by

Contracts used/delivered

Uses S15RuntimeConfig, runS15, VM15-02/SETUP15-01/CHAN15-01 setup paths. Delivers the --s15 installer selection, generated config, unit and runbook.

Out of scope

Migrating Pi or S14 data; changing the Pi; deleting the owner's Lima VMs on the Mac without asking.

Do not

Do not touch the Pi; do not import legacy/S14 state; do not put credentials in config, logs or the repo; do not install a policy, budget or personal GitHub rule on the owner's behalf; do not add AI attribution; do not merge the implementation PR yourself.

Definition of done

Installer PR: bun install --frozen-lockfile, bun run typecheck, bun run test, git diff --check pass; PR body Refs #341 (owner steps remain). This issue closes only after the live install and explicit owner acceptance are recorded.

Owner revision 2026-11-06

Telegram was removed from Jit (ADR 0085, #441) and the default authority became Grok-style (ADR 0084, #442). Telegram steps and evidence in this issue no longer apply; the first conversation and notifications use the Web/PWA.

Activity

  1. chayapats commented on Nov 3, 2026

    @chayapats
    OwnerAuthor

    Status (2026-11-03): every S15 implementation slice is merged and composed. Main c5f476eaf5478b585e9fbdc8c377ed918d6f408e contains the opt-in S15 runtime (init/setup/serve --s15, adoption --s15 --report), with S14 still the default and omitted-runtime configs never reinterpreted. MIG15-01 (#336, PR #364) delivered staged adoption with source preservation, a single-writer fence, conditional rollback and a read-only adoption status.

    The exact final build is staged on a new disposable arm64 controller with no owner or policy installed; see the evidence summary on #340. No existing installation (Pi, jit-vm, jit-arm) has been changed.

    Remaining for this ticket, all owner-only: complete the #340 live evidence prerequisites, then decide the exact installation, host/topology, build, policy revision, optional personal GitHub rule and any operating budget for activation, plus the rollback window. This issue stays open until that explicit owner acceptance and the named-host preservation/rollback evidence exist.

  2. changed the title [-][Frontier] [CUT15-01] Adopt the reviewed S15 release with owner acceptance and rollback[/-] [+][Frontier] [CUT15-01] Install S15 fresh on jit-vm with owner acceptance and a recoverable install[/+] on Nov 3, 2026
  3. chayapats commented on Nov 3, 2026

    @chayapats
    OwnerAuthor

    Installer code merged in #379 (merge 7f06716): install.sh --s15 creates the separate jit-s15 installation (controller identity, QEMU identity jit-s15-vmm with a single-launcher sudoers rule, generated credential-free config, hardened unit, systemd-bound registry proxy socket, transactional install/upgrade/uninstall with rollback, owner link delivered right after the health check, controller-only fallback without a kvm group). Runbook: docs/runbooks/s15-install.md. Still open here: the protected browser on the install (#380), the Schway renewal adoption (#381), the live install on jit-vm, and the owner acceptance steps.

  4. chayapats commented on Nov 3, 2026

    @chayapats
    OwnerAuthor

    Production install on jit-vm (2026-11-03)

    Installed: jit-s15 from branch jit/341-installer-live-fixes at d129276d8d8379c83840bcccb7618266b9db0d24, which is main 9082327 plus the installer-only fixes in #390 (#389). The release ID is 5884d9c6-8ecc-4cc9-9c5d-e0ecd16400f1. State is fresh; nothing was migrated from the Pi or from any S14/legacy install.

    How: ./install.sh --s15 --yes ran under a pty whose output was discarded, so the first-owner link went only to that pty, was never seen, and has expired. The install log and the jit-s15 journal contain no token=. The owner gets a fresh link by re-running install.sh --s15 from an ssh -t terminal, as the runbook says.

    Result: every step passed:

    • preflight … dependencies … owner-link-prepare → service-install → service-start → health → owner-link → working-computer.
    • Working computer: check host → download → verify checksum → disk and keys → first boot → first-time setup → identity and network-isolation checks → Ready.

    Verified on the host after install:

    • jit-s15.service (User jit-s15, 0 restarts) and jit-s15-vm-proxy.socket are active; the sign-in page answers 200 on 127.0.0.1:3002.
    • QEMU (jit-work-cbad1842eae9) runs as jit-s15-vmm (in kvm). jit-s15 is not in kvm. /etc/sudoers.d/jit-s15-vmm allows only /opt/jit-s15/libexec/jit-s15-vmm as jit-s15-vmm, and the journal shows the controller reaching QEMU only through that launcher.
    • The generated config has vm.local: true and vm.vmm.user: jit-s15-vmm, with policy, budget, GitHub, Google and browser config all null (Web-managed).
    • The protected browser's pinned Chromium was downloaded and verified (state/browser-engine/…/.jit-verified).

    Failures found on the way (all recoverable, as designed):

    1. On main 9082327 the install hung in dependencies: apt ran under timeout with the terminal as stdin and was stopped by SIGTTOU. I stopped it by hand; the installer reported Failed at dependencies and dpkg was clean. Fixed in fix(install): pass the S15 owner-link pipe flag and keep package managers off the terminal #390.
    2. Failed at release: my staged copy was group-writable. This is a correct refusal by the trusted-input rule, not a product bug.
    3. Failed at owner-link-prepare: the S15 owner-link argv lacked --output-fd 3. The fresh-install rollback removed the new state, as designed. Fixed in fix(install): pass the S15 owner-link pipe flag and keep package managers off the terminal #390.

    After #390 merges, I will re-run install.sh --s15 from main on this host. That exercises the in-place upgrade/repair path; the result will follow here.

    Remaining owner steps (Web UI only; the exact checklist is in the ignored owner notes):

    1. New owner link and owner password.
    2. Codex device login at /settings/provider.
    3. New Telegram bot at /resources/telegram.
    4. Approved websites at /resources/websites.
    5. Standing rules at /setup#s15-setup-rules.
    6. GitHub sandbox token at /resources/github, then the updated rules at /rules.
    7. CUT15-01 acceptance: an owner comment here naming the installation, the build, the policy revision and the activation time.

    Retiring the Pi stays an owner step after acceptance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestneeds-triageMaintainer needs to evaluate this issue.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions