{"_id":"@adlc/autopilot","name":"@adlc/autopilot","dist-tags":{"latest":"1.11.1"},"versions":{"1.11.1":{"name":"@adlc/autopilot","version":"1.11.1","description":"Quota-gated local issue-to-PR loop: picks a GitHub issue, shapes an ADLC ticket, dispatches one sandboxed fleet run per issue, gates, attests and opens the PR. Composes @adlc/fleet; adds no gate logic.","type":"module","license":"MIT","author":{"name":"Chris Williams","url":"@voodootikigod"},"repository":{"type":"git","url":"git+https://github.com/voodootikigod/adlc.git","directory":"packages/autopilot"},"homepage":"https://github.com/voodootikigod/adlc/tree/main/packages/autopilot#readme","bugs":{"url":"https://github.com/voodootikigod/adlc/issues"},"keywords":["adlc","agents","autopilot","github-issues","orchestration"],"bin":{"adlc-autopilot":"bin/adlc-autopilot.mjs"},"dependencies":{"@adlc/core":"1.11.1","@adlc/fleet":"1.11.1","@adlc/tickets":"1.11.1"},"scripts":{"test":"node --test test/*.test.mjs","test:gate":"AUTOPILOT_GATE_FULL=1 node --test test/spec-coverage.test.mjs"},"engines":{"node":">=18"},"publishConfig":{"access":"public","provenance":true},"gitHead":"c5772b4ff942bec77a34454c4fc888ae4e4b2c14","_id":"@adlc/autopilot@1.11.1","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-U8shIvh0dLHZJavd/lwRFck2+afEweZlwYyBZ7cWb8113xmTV4KX0rL1r54FW5scZYUiF0Mc8iJbq9EIdvM/1A==","shasum":"9625d81a6729bcf2c0ee413ecd273be39523222e","tarball":"https://registry.npmjs.org/@adlc/autopilot/-/autopilot-1.11.1.tgz","fileCount":68,"unpackedSize":571131,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDQGTNv6odD365lgZIjKjiU+qJr3pOmlBL9TysSZoBpYwIgMoGPom9lySTQy4wMtq6rA1n4IjgN+m6DSv0TsimfkF8="}]},"_npmUser":{"name":"voodootikigod","email":"voodootikigod@gmail.com"},"directories":{},"maintainers":[{"name":"voodootikigod","email":"voodootikigod@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/autopilot_1.11.1_1788952653670_0.9753658506113669"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-09T11:17:33.525Z","1.11.1":"2026-09-09T11:17:33.857Z","modified":"2026-09-09T11:17:34.076Z"},"maintainers":[{"name":"voodootikigod","email":"voodootikigod@gmail.com"}],"description":"Quota-gated local issue-to-PR loop: picks a GitHub issue, shapes an ADLC ticket, dispatches one sandboxed fleet run per issue, gates, attests and opens the PR. Composes @adlc/fleet; adds no gate logic.","homepage":"https://github.com/voodootikigod/adlc/tree/main/packages/autopilot#readme","keywords":["adlc","agents","autopilot","github-issues","orchestration"],"repository":{"type":"git","url":"git+https://github.com/voodootikigod/adlc.git","directory":"packages/autopilot"},"author":{"name":"Chris Williams","url":"@voodootikigod"},"bugs":{"url":"https://github.com/voodootikigod/adlc/issues"},"license":"MIT","readme":"# @adlc/autopilot\n\nQuota-gated local issue-to-PR loop. Picks the next GitHub issue from the open\nbacklog, shapes an ADLC ticket, dispatches **one sandboxed `@adlc/fleet` run per\nissue**, runs the outer gates in throwaway sandboxed clones, attests with a\ncross-model (Codex) review bound to the exact tree it pushes, and opens the PR.\nP6 (merge) stays human. Every escalation is a GitHub label the operator can flip\nfrom a phone.\n\nDesign contract: [`docs/specs/issue-autopilot-local.md`](../../docs/specs/issue-autopilot-local.md)\n· decisions: [`docs/adr/0016-issue-autopilot-local-substrate.md`](../../docs/adr/0016-issue-autopilot-local-substrate.md).\n\n## What it does\n\n- **Composes fleet, adds no gate logic.** The autopilot is an issue picker + a\n  quota gate + a rest loop around `fleet run --tickets <id> --no-pr\n  --no-complete --max-strikes … --wall-clock-minutes … --pre-strike-argv …\n  --model-plane-read bounded --model-plane-git mirror --model-plane-egress\n  allowlist --worker-deps …`.\n- **The quota gate is literal.** A Claude-consuming step starts only when the\n  5-hour AND the 7-day windows (and the worker model's scoped window) read\n  `< threshold` (default 50 %, tightenable never loosenable), sampled at most\n  60 s before the start, with a reserve for every start after the first in an\n  iteration. Unknown quota = no run.\n- **Trust stays here.** The manifest key reaches exactly seven key-bearing\n  children (`KEY_BEARING_ARGV` in `lib/keys.mjs`). The worker holds only its\n  harness credential, in a synthetic HOME bound read-only, behind an egress\n  allowlist naming only the model API, with a per-run bare git mirror as its\n  only git database. Gates run in per-gate clones inside a network-denied\n  sandbox. Every push is lease-guarded and verified at the endpoint.\n- **Everything is a state machine on disk.** One run record per issue under\n  `.adlc/autopilot-runs/`, written before the world-effect it names, so a crash\n  between the two is disambiguated by inspecting git/`gh` on the next\n  iteration. Deletion of anything is ownership-checked and never forced.\n\n## Usage\n\n```sh\nadlc autopilot loop   [--rest 10m] [--dry-run]                       # the service body\nadlc autopilot once   [--issue <n>] [--force] [--dry-run] [--dry-run-shape]\nadlc autopilot status [--json]\nadlc autopilot select [--top <n>] [--json]\nadlc autopilot quota  [--json] [--model <m>] [--quota-threshold <T>] [--quota-reserve <R>]\nadlc autopilot triage --issue <n> [--json]\nadlc autopilot reset  --issue <n> ( --confirm-delete <OID> [--delete-remote] | --attempts )\nadlc autopilot init   [--labels] [--service] [--write]\n```\n\nGlobal operator-local flags: `--repo <owner/name>` (or `ADLC_AUTOPILOT_REPO`;\nrequired for `loop`/`once`), `--model` (default `opus`), `--adapter`\n(`claude-code` only in v1), `--quota-threshold` (1–50), `--quota-reserve`\n(0–49, `< threshold`), `--trusted-bin-dirs <abs,…>`, `--ssh-identity <abs>`.\nPrecedence: CLI flag > `ADLC_AUTOPILOT_<UPPER_SNAKE>` > default. Every\nsubcommand exits 0/1/2 and supports `--json`.\n\n## Configuration\n\nRepo-committed (`.adlc/config.json`, a trust root): the `fleet` block fleet\nreads, an `autopilot` block (`restMinutes`, `maxOpenPrs`, `maxRounds`,\n`wallClockMinutes`, `ciFixRounds`, `ciWatchMinutes`, `reviewMaxBytes`, `repo`,\n`dispatchApproval`, `protectedPathsExtra`) that the CLI may lower but never\nraise, and a `ticketSync` block validated against ticket-sync's schema. A\ncommitted `quotaThreshold`/`quotaReserve`/`model`/`adapter` is warned and\nignored — the quota is the operator's.\n\n## Service\n\n`adlc autopilot init --service --repo <owner/name>` prints a `systemd --user`\nunit (`--write` installs it): absolute paths, `EnvironmentFile=<repo>/.env.local`\n(the manifest key, file must be `0600`), `Restart=on-failure`,\n`KillMode=control-group`, exactly one SSH auth mode. Then\n`systemctl --user enable --now adlc-autopilot`.\n\n## Exit codes\n\n- `0` — the iteration completed (a run, a CLARIFY, a rest, or a clean dry-run).\n- `1` — operational error: preflight red (the code names the item —\n  `untrusted-tool:<name>`, `repo-mismatch`, `key-file-insecure`,\n  `spec-approval-stale`, `plugin-parity`, …), `lock-held`, `bad-input:<field>`.\n- `2` — a gate refused: a pinned issue is excluded (the rule is named), a\n  `reset` was refused, a run ended `blocked`.\n\n## ADLC phase\n\nP0 (triage) through P5 (prosecution) as an unattended loop; P6 is the human's.\nIt consumes the tickets `@adlc/tickets` stores, the gates `spec-lint`,\n`coldstart`, `rails-guard`, `hollow-test`/`mutation-gate`, `prosecute\nrecord-cross-model` and `gate-manifest` record, and `fleet` for P4.\n\n## Tests\n\n`node --test packages/autopilot/test/` — offline, with fake `gh`/`claude`/fleet\nchildren and real temporary git repositories. `test/ac-registry.mjs` maps every\nspec §16 criterion to exported test functions and a mutation fixture;\n`test/spec-coverage.test.mjs` parses the spec at the pinned blob and fails on any\ncriterion without a load-bearing test. Real-bwrap and real-sshd checks skip\nloudly when the host lacks them.\n\n## Core gaps\n\nNone. Runtime dependencies are `@adlc/core`, `@adlc/fleet` and `@adlc/tickets`\nonly; the ticket-sync config schema is read from the pinned blob and evaluated\nby `lib/schema-lite.mjs` rather than importing `@adlc/ticket-sync`.\n\n## The AC coverage gate\n\n`npm run test:gate -w packages/autopilot` runs `test/spec-coverage.test.mjs` with\n`AUTOPILOT_GATE_FULL=1`: every §16 criterion of the spec is registered\n(`test/ac-registry.mjs`), every registered function is executed, and every\ncriterion's mutation fixture is proven to BITE. The execution passes take ~25\nminutes; without the variable only the static checks run (the root suite and\nthe mutation gate stay fast). Run the full gate before merging a change to this\npackage.\n","readmeFilename":"README.md","_rev":"1-594df7f4daa0c6b7b3b5a41ce4111d1d"}