### Mode: autonomy-doctor

<!-- opt-in-capability: sandbox-provision -->

The **sandbox provisioner "doctor"** — the answer to *"can this machine run the Claude sandbox, and can you fix it?"* (AD-044: macOS Seatbelt built-in / Linux+WSL2 `bwrap`+`socat` / native Windows → WSL2). **Division of labor:** YOU narrate the diagnosis and relay the consent question; the KIT does the deterministic detect → consent-gated install → verify. It is **guarded**: the privileged lane runs ONLY with the per-run consent tuple, always faces the harness permission prompt (the mode sits outside every velocity auto-approve tier), **never auto-runs, never writes repo files, and never commits**.

Run **`node ${CLAUDE_SKILL_DIR}/tools/autonomy-doctor.mjs [--verify | --apply <pm>:<pkg[,pkg...]>]`**:

1. **Flagless = FS-only preview** (the default; runs NO subprocesses): the diagnosis, the exact absolute-path command the doctor WOULD run, and the exact `--apply <pm>:<pkgs>` consent line. It **never claims "ready"** — binaries present without proof render `present-unverified`, never exit `0`.
2. **`--verify`** — the unprivileged diagnostic: a `bwrap` user-namespace smoke plus `socat -V` (captured stdio). This is the ONLY source of a Linux **ready-verified** claim. Honesty split: a green verify proves the **OS primitives, not Claude-init** — the output always states the restart step. Under root/`SUDO_UID` the verified claim is REFUSED (`root-unproven`); a namespace-denied smoke with present binaries reports a loud `indeterminate` (nested sandboxing / already inside a container — re-run from an unsandboxed shell).
3. **`--apply <pm>:<pkgs>`** — the consent-gated privileged install: the tuple must EQUAL the re-derived plan (consent binds to the previewed plan; a mismatch or a bare `--apply` refuses with `2` usage and runs NOTHING), the exact resolved command is re-printed immediately before execution, then the verify lane runs automatically. Sudo boundary: root drops sudo; a passwordless sudo proceeds with a LOUD note; a password-needing sudo without a controlling terminal runs NOTHING and prints the exact command to run in the USER's terminal (`handoff-required`).

**Trust gate:** everything executed resolves to an ABSOLUTE path inside the fixed trusted dirs `/usr/bin:/bin:/usr/sbin:/sbin` (`/usr/local/bin` deliberately excluded); a binary or package manager found only outside is a loud `untrusted-path` / `unknown-pm` degrade, never executed. The privileged child gets a minimal scrubbed env (trusted-dir PATH + LANG), an argv array, no shell. Package names come from a frozen internal map (`bubblewrap`, `socat`); apt runs through the env trampoline (`env DEBIAN_FRONTEND=noninteractive …`) so non-interactivity survives sudo's `env_reset`.

**Exit codes (frozen):** `0` ready (`ready-verified` / `ready-assumed`; Linux only via the verify oracle) · `1` precondition STOP (`no-deployment`) · `2` usage (bare `--apply`, tuple mismatch, unknown flag) · `3` not-ready diagnosis (`missing-binaries` offer / `present-unverified` / `handoff-required`) · `4` install failed (`install-failed`) · `5` verify failed (`verify-failed` / `indeterminate` / `root-unproven`) · `6` unsupported / untrusted (`unsupported-platform` win32 / `unknown-pm` / `untrusted-path`). The machine summary line prints LAST in every diagnosis outcome (`--help` prints the help text alone): `[autonomy-doctor] status=<token> platform=<p> missing=<csv> pm=<name|none>`.

**Stamp EXEMPTION (stated, deliberate):** the doctor runs behind the docs/ai presence gate ahead of every lane (`--help` and parse-time usage errors return earlier) but has **NO `.workflow-version` stamp gate** — it provisions the OS, never lineage-bound repo content, so the global stale-deployment→upgrade routing does not apply to this mode.

**Residuals (disclosed in the preview):** a root-owned hostile binary inside the trusted dirs is out of the threat model; Claude itself resolves `bwrap`/`socat` via PATH at session init (the doctor warns on a PATH shadow, never fixes PATH); the harness permission prompt shows the `--apply` tuple, not the absolute-path command — bridged by the apply-time re-print.

Output is **English/structured** — **localize it to the user's conversational language** when you narrate.

**Invariants:** guarded (the MUTATING lane only via `--apply` with the matching tuple, exactly once) · preview-first · never auto-runs · outside every velocity auto-approve tier · never writes repo files · never commits · loud degrades, never silent.
