@delegance/claude-autopilot 7.10.0 → 7.11.0-pre.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -1
- package/README.md +19 -13
- package/dist/src/cli/examples.d.ts +15 -0
- package/dist/src/cli/examples.js +108 -0
- package/dist/src/cli/help-text.js +13 -0
- package/dist/src/cli/index.js +12 -1
- package/dist/src/core/concurrent-dispatch/budget-reservation.d.ts +163 -0
- package/dist/src/core/concurrent-dispatch/budget-reservation.js +642 -0
- package/dist/src/core/concurrent-dispatch/dep-graph.d.ts +68 -0
- package/dist/src/core/concurrent-dispatch/dep-graph.js +626 -0
- package/dist/src/core/concurrent-dispatch/git-op-queue.d.ts +47 -0
- package/dist/src/core/concurrent-dispatch/git-op-queue.js +114 -0
- package/dist/src/core/concurrent-dispatch/index.d.ts +13 -0
- package/dist/src/core/concurrent-dispatch/index.js +21 -0
- package/dist/src/core/concurrent-dispatch/merge-orchestrator.d.ts +99 -0
- package/dist/src/core/concurrent-dispatch/merge-orchestrator.js +831 -0
- package/dist/src/core/concurrent-dispatch/scheduler.d.ts +160 -0
- package/dist/src/core/concurrent-dispatch/scheduler.js +933 -0
- package/dist/src/core/concurrent-dispatch/types.d.ts +156 -0
- package/dist/src/core/concurrent-dispatch/types.js +38 -0
- package/dist/src/core/concurrent-dispatch/worktree-lifecycle.d.ts +138 -0
- package/dist/src/core/concurrent-dispatch/worktree-lifecycle.js +418 -0
- package/dist/src/core/phases/deploy.d.ts +19 -0
- package/dist/src/core/phases/deploy.js +87 -0
- package/dist/src/core/run-state/repo-lock.d.ts +110 -0
- package/dist/src/core/run-state/repo-lock.js +373 -0
- package/dist/src/core/run-state/serialized-writer.d.ts +90 -0
- package/dist/src/core/run-state/serialized-writer.js +341 -0
- package/examples/specs/fastapi.md +37 -0
- package/examples/specs/go-cli.md +32 -0
- package/examples/specs/node-cli.md +36 -0
- package/examples/specs/python-cli.md +35 -0
- package/examples/specs/rust-cli.md +34 -0
- package/package.json +14 -3
- package/skills/ui-ux-pro-max/SKILL.md +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
- v5.6 Phase 7 (docs reconciliation) — pending.
|
|
4
4
|
|
|
5
|
+
## 7.10.1 — 2026-05-13
|
|
6
|
+
|
|
7
|
+
**v7.10.1 — `examples` verb.** Patch release. Closes the discoverability
|
|
8
|
+
gap a new user hits between `setup` and `scaffold --from-spec`: the
|
|
9
|
+
new `claude-autopilot examples` verb prints sample specs for each
|
|
10
|
+
supported stack (node / python / fastapi / go / rust) so an operator
|
|
11
|
+
can pipe one to a file and feed it back into the scaffolder.
|
|
12
|
+
|
|
13
|
+
**New:** `claude-autopilot examples` lists all five stacks with a
|
|
14
|
+
5-line preview. `claude-autopilot examples <stack>` prints the full
|
|
15
|
+
spec for one stack to stdout — pipe-friendly:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
claude-autopilot examples fastapi > docs/specs/my-api.md
|
|
19
|
+
# edit the spec...
|
|
20
|
+
claude-autopilot scaffold --from-spec docs/specs/my-api.md
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Bundled examples.** Five spec markdown files ship in
|
|
24
|
+
`examples/specs/{node-cli,python-cli,fastapi,go-cli,rust-cli}.md` —
|
|
25
|
+
one per supported scaffold target. Each shows the `## Files` section
|
|
26
|
+
shape the scaffolder reads, plus a `## Goal` and `## How to use`
|
|
27
|
+
section for human readers.
|
|
28
|
+
|
|
29
|
+
**Package shape.** `examples/` is added to the published `files:`
|
|
30
|
+
array in package.json so the directory ships in the npm tarball — the
|
|
31
|
+
verb resolves spec paths via `findPackageRoot` and works under both
|
|
32
|
+
source and globally installed CLI invocations.
|
|
33
|
+
|
|
5
34
|
## 7.10.0 — 2026-05-13
|
|
6
35
|
|
|
7
36
|
### Added
|
|
@@ -91,7 +120,6 @@ usage except for the bundled `tsx` deprecation warning.
|
|
|
91
120
|
A1-A8 covering ESM/CJS safety, CLI parser scope, PATH self-pointer,
|
|
92
121
|
AST audit, type-only imports, hand-rolled PATH lookup dropping the
|
|
93
122
|
`which` dep, XDG state dir, npm-only --omit=optional documentation).
|
|
94
|
-
|
|
95
123
|
## 7.7.0 (2026-05-11)
|
|
96
124
|
|
|
97
125
|
**v7.7.0 — Rust scaffold support.** Minor release. Promotes Rust from
|
package/README.md
CHANGED
|
@@ -17,8 +17,11 @@ claude-autopilot brainstorm "add SSO with SAML for enterprise tenants"
|
|
|
17
17
|
# → writes spec (reviewed by Codex) → writes plan (reviewed by Codex) →
|
|
18
18
|
# → creates branch → implements with subagents → runs migrations →
|
|
19
19
|
# → runs full test + lint + type + security gate → opens PR →
|
|
20
|
-
# →
|
|
21
|
-
# →
|
|
20
|
+
# → runs risk-tiered Codex PR review (1/2/3 passes by spec risk) →
|
|
21
|
+
# → triages bugbot findings, auto-fixes real bugs, re-runs validate →
|
|
22
|
+
# → merges with your configured permissions (default is admin-squash;
|
|
23
|
+
# configure branch protection + required checks if you need to enforce
|
|
24
|
+
# reviews/CI gates that the autopilot agent should not bypass)
|
|
22
25
|
```
|
|
23
26
|
|
|
24
27
|
*No hosted agent. No per-seat subscription. Runs locally on your machine, against your real repo, using your API keys. Every phase is a Claude Code skill you can intervene in, rewire, or run by itself.*
|
|
@@ -50,13 +53,14 @@ Every finding came with a concrete remediation (often a code patch or named libr
|
|
|
50
53
|
| **Cursor BugBot / CodeRabbit** | Hosted | Per-PR or seat | Vendor's model | Review only | Post-hoc |
|
|
51
54
|
| **Aider / Cline** | Local CLI | Free + your API key | User's choice | None | Continuous |
|
|
52
55
|
| **OpenHands / SWE-agent** | Local research | Free | User's choice | Agent decides | Rare |
|
|
53
|
-
| **claude-autopilot** | **Local CLI, your repo** | **
|
|
56
|
+
| **claude-autopilot** | **Local CLI, your repo** | **Open source CLI + your model/API costs (Claude / Codex / Gemini / Groq / Ollama-local)** | **Multi-model per role (Claude + Codex + Gemini)** | **Skill-per-phase, rewireable** | **Every phase, all state on disk** |
|
|
54
57
|
|
|
55
|
-
|
|
58
|
+
Four things only this product gives you:
|
|
56
59
|
|
|
57
|
-
1. **
|
|
58
|
-
2. **
|
|
60
|
+
1. **No hosted workspace or remote sandbox.** Your repo stays on your machine. No third-party agent runtime, no SaaS-side orchestration, no per-seat markup. Model prompts (diffs, file context, design questions) are sent to whichever LLM providers you've configured (Anthropic / OpenAI / Google / Groq / Ollama-local). For a truly local-only setup, you must point _every_ model used by the entire execution path at a local endpoint: that includes the Claude Code agent runtime itself (configure a local Claude Code provider) AND the autopilot review adapter (`openai-compatible` pointed at Ollama). Pointing only the review adapter at Ollama still ships prompts/diffs to Anthropic via Claude Code. For most teams, local-only isn't the goal; "no hosted orchestration + your existing provider keys" is.
|
|
61
|
+
2. **Risk-tiered review depth (policy-driven).** Specs declare `risk: low | medium | high` in frontmatter. The autopilot skill runs 1 / 2 / 3 sequential Codex passes accordingly, each with a remediation cycle in between. Enforcement is encoded in the skill (an LLM-driven instruction set, not a hard CLI gate) so it's auditable and editable: read `.claude/skills/autopilot/SKILL.md`, swap the tier rules for your codebase, expand the auto-escalation keyword list. Designed for teams that want review depth to scale with change risk instead of running forensic-grade review on every typo.
|
|
59
62
|
3. **Ships as a Claude Code skill, not a competing IDE.** `/brainstorm`, `/autopilot`, `/migrate`, `/validate` are first-class Claude Code commands. As Claude Code grows, autopilot rides that adoption. You don't switch tools to use it; it's already there.
|
|
63
|
+
4. **Multi-model council, available as a verb.** `claude-autopilot council` dispatches the same diff or design question to Claude + Codex + Gemini in parallel and synthesizes the consensus. Wire it into the autopilot pipeline by editing `.claude/skills/autopilot/SKILL.md` Step 7, or invoke standalone for one-off design decisions. The default pipeline uses sequential Codex review (cheaper, faster, often sufficient for routine changes); council is the higher-rigor option when you want broader model diversity.
|
|
60
64
|
|
|
61
65
|
Plus the four practical differences:
|
|
62
66
|
|
|
@@ -128,9 +132,9 @@ Each phase is a Claude Code skill (`.claude/skills/<name>/SKILL.md`). You can in
|
|
|
128
132
|
| **Migrate** | `migrate` | Dispatches to the configured migration skill (see [Migrate phase](#migrate-phase)) — runs your migration tool dev → QA → prod with per-env validation | Deterministic |
|
|
129
133
|
| **Validate** | `validate` | Static rules + tests + type check + security scan + LLM review | Any |
|
|
130
134
|
| **PR** | `commit-push-pr` | Opens the PR with auto-generated title, summary, and test plan | Claude |
|
|
131
|
-
| **Review** | `review
|
|
135
|
+
| **Review** | `codex-pr-review` (default) or `council` (opt-in) | Sequential Codex pass on the diff with risk-tiered iteration count (1/2/3 passes for low/medium/high). Swap in `council` for parallel multi-model dispatch if you want higher rigor. | Codex (default) or multi-model |
|
|
132
136
|
| **Triage** | `bugbot` | Fetches automated reviewer findings, auto-fixes real bugs, dismisses false positives | Claude |
|
|
133
|
-
| **Deploy** | `deploy` | Deploys via configured adapter (`vercel` \| `fly` \| `render` \| `generic`) with optional log streaming, health check, and bounded auto-rollback (see [Deploy phase](#deploy-phase)) | Deterministic |
|
|
137
|
+
| **Deploy** (opt-in) | `deploy` | Deploys via configured adapter (`vercel` \| `fly` \| `render` \| `generic`) with optional log streaming, health check, and bounded auto-rollback (see [Deploy phase](#deploy-phase)). Not on the default `/autopilot` critical path: the autopilot loop ends at merge, and your CI/CD handles prod. Invoke `claude-autopilot deploy` directly, or wire it into the autopilot skill as Step 10. | Deterministic |
|
|
134
138
|
|
|
135
139
|
### Migrate phase
|
|
136
140
|
|
|
@@ -181,11 +185,13 @@ deploy:
|
|
|
181
185
|
|
|
182
186
|
Features that are hard or impossible to find in the competitive set:
|
|
183
187
|
|
|
184
|
-
- **
|
|
185
|
-
- **
|
|
186
|
-
- **
|
|
187
|
-
- **
|
|
188
|
-
- **
|
|
188
|
+
- **Risk-tiered review depth (policy-driven).** Specs are tagged `risk: low | medium | high` in their frontmatter, with auto-escalation by keyword detection for sensitive categories (auth, multi-tenancy, sandboxing, billing, secrets, migrations, RLS, deploy/IAM, vector-DB tenancy — extend the list in the skill for your codebase). The pipeline runs 1 / 2 / 3 sequential Codex passes accordingly, each with a remediation cycle in between. Enforcement is encoded in `.claude/skills/autopilot/SKILL.md` (LLM-driven instructions, not a hard CLI gate), so it's auditable and editable. For teams that need hard enforcement, gate the merge step on the configured pass count by extending the skill or wrapping the CLI.
|
|
189
|
+
- **Retry-loop sameness detector.** Validate / Codex / bugbot retry loops compute a failure fingerprint before consuming each retry. If the same fingerprint fires twice in a row, the pipeline halts and surfaces it to you — instead of burning the remaining retry budget on attempts that are making no progress. Available as a public subpath import (`@delegance/claude-autopilot/run-state/sameness-detector`) for embedding into your own retry loops.
|
|
190
|
+
- **Multi-model council, available as a verb.** `claude-autopilot council` dispatches the same prompt to 3+ models in parallel and synthesizes the consensus. Opt-in for the autopilot pipeline (wire it into Step 7 of the autopilot skill), or invoke standalone for design decisions and architecture questions.
|
|
191
|
+
- **Fix with test verification.** `claude-autopilot fix --verify` runs your full test suite after every patch and reverts on failure. Safer than any tool that proposes fixes without running your tests.
|
|
192
|
+
- **Bug-bot auto-triage.** Watches Cursor BugBot / Copilot comments on your PR, triages each (real bug vs false positive), auto-fixes confirmed bugs, dismisses noise with explanations.
|
|
193
|
+
- **Schema alignment rule.** Ensures DB migrations, backend types, and frontend types stay in sync. Custom static rule, not something any competitor ships.
|
|
194
|
+
- **SARIF output + GitHub Code Scanning integration.** Findings appear as annotations in the PR and in the Security tab.
|
|
189
195
|
|
|
190
196
|
## Just the review layer
|
|
191
197
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Supported stack id → relative path under `examples/specs/`. */
|
|
2
|
+
export declare const EXAMPLE_STACKS: Record<string, string>;
|
|
3
|
+
/** Public stack ids in the order we want them listed. */
|
|
4
|
+
export declare const EXAMPLE_STACK_IDS: readonly ["node", "python", "fastapi", "go", "rust"];
|
|
5
|
+
/** Resolve the absolute on-disk path for a stack's spec file. */
|
|
6
|
+
export declare function resolveExamplePath(stack: string): string | null;
|
|
7
|
+
/**
|
|
8
|
+
* Run the `examples` verb. With no `stack`, prints an intro + a summary card
|
|
9
|
+
* for each stack (path + first ~5 lines of the spec). With a stack id, prints
|
|
10
|
+
* the full spec content to stdout (suitable for piping into a file).
|
|
11
|
+
*
|
|
12
|
+
* Returns the exit code so the dispatcher can `process.exit(code)`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function runExamples(stack?: string): number;
|
|
15
|
+
//# sourceMappingURL=examples.d.ts.map
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// v7.7.1 — `claude-autopilot examples [<stack>]`
|
|
2
|
+
//
|
|
3
|
+
// Discoverability bridge between `setup` and `scaffold --from-spec`. A new
|
|
4
|
+
// user runs `setup`, then `scaffold --from-spec ???` and has no idea what a
|
|
5
|
+
// spec looks like. This verb prints sample specs — one per supported stack —
|
|
6
|
+
// straight to stdout so the operator can pipe to a file, edit, and feed back
|
|
7
|
+
// into `scaffold`.
|
|
8
|
+
//
|
|
9
|
+
// claude-autopilot examples → list all 5 stacks
|
|
10
|
+
// claude-autopilot examples node → print just the Node spec
|
|
11
|
+
// claude-autopilot examples fastapi > foo.md → spec-as-template via shell
|
|
12
|
+
//
|
|
13
|
+
// The spec files ship in the published tarball via the `files: ["examples/"]`
|
|
14
|
+
// entry in package.json. At runtime we resolve them relative to the package
|
|
15
|
+
// root (found by `findPackageRoot`), so `examples` works whether the CLI is
|
|
16
|
+
// run from source, the built dist/, or a globally installed `npm i -g`
|
|
17
|
+
// invocation.
|
|
18
|
+
import * as fs from 'node:fs';
|
|
19
|
+
import * as path from 'node:path';
|
|
20
|
+
import { findPackageRoot } from "./_pkg-root.js";
|
|
21
|
+
/** Supported stack id → relative path under `examples/specs/`. */
|
|
22
|
+
export const EXAMPLE_STACKS = {
|
|
23
|
+
node: 'examples/specs/node-cli.md',
|
|
24
|
+
python: 'examples/specs/python-cli.md',
|
|
25
|
+
fastapi: 'examples/specs/fastapi.md',
|
|
26
|
+
go: 'examples/specs/go-cli.md',
|
|
27
|
+
rust: 'examples/specs/rust-cli.md',
|
|
28
|
+
};
|
|
29
|
+
/** Public stack ids in the order we want them listed. */
|
|
30
|
+
export const EXAMPLE_STACK_IDS = ['node', 'python', 'fastapi', 'go', 'rust'];
|
|
31
|
+
const BOLD = (t) => `\x1b[1m${t}\x1b[0m`;
|
|
32
|
+
const DIM = (t) => `\x1b[2m${t}\x1b[0m`;
|
|
33
|
+
/** Resolve the absolute on-disk path for a stack's spec file. */
|
|
34
|
+
export function resolveExamplePath(stack) {
|
|
35
|
+
const rel = EXAMPLE_STACKS[stack];
|
|
36
|
+
if (!rel)
|
|
37
|
+
return null;
|
|
38
|
+
const root = findPackageRoot(import.meta.url);
|
|
39
|
+
if (!root)
|
|
40
|
+
return null;
|
|
41
|
+
return path.join(root, rel);
|
|
42
|
+
}
|
|
43
|
+
/** Print the first N non-empty lines of a file for the listing summary. */
|
|
44
|
+
function previewHead(absPath, n) {
|
|
45
|
+
try {
|
|
46
|
+
const body = fs.readFileSync(absPath, 'utf8');
|
|
47
|
+
const lines = body.split('\n');
|
|
48
|
+
const head = [];
|
|
49
|
+
for (const line of lines) {
|
|
50
|
+
head.push(line);
|
|
51
|
+
if (head.length >= n)
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
return head.join('\n');
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return '(failed to read example file)';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Run the `examples` verb. With no `stack`, prints an intro + a summary card
|
|
62
|
+
* for each stack (path + first ~5 lines of the spec). With a stack id, prints
|
|
63
|
+
* the full spec content to stdout (suitable for piping into a file).
|
|
64
|
+
*
|
|
65
|
+
* Returns the exit code so the dispatcher can `process.exit(code)`.
|
|
66
|
+
*/
|
|
67
|
+
export function runExamples(stack) {
|
|
68
|
+
if (!stack) {
|
|
69
|
+
console.log('');
|
|
70
|
+
console.log(BOLD('Sample specs for each supported stack.'));
|
|
71
|
+
console.log(DIM('Pass `examples <stack>` to print just one. Pipe to a file to use as a template:'));
|
|
72
|
+
console.log(DIM(' claude-autopilot examples node > docs/specs/my-feature.md'));
|
|
73
|
+
console.log(DIM(' claude-autopilot scaffold --from-spec docs/specs/my-feature.md'));
|
|
74
|
+
console.log('');
|
|
75
|
+
for (const id of EXAMPLE_STACK_IDS) {
|
|
76
|
+
const abs = resolveExamplePath(id);
|
|
77
|
+
if (!abs || !fs.existsSync(abs)) {
|
|
78
|
+
console.log(`${BOLD(id)} ${DIM('(example file not found)')}`);
|
|
79
|
+
console.log('');
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
console.log(BOLD(id));
|
|
83
|
+
console.log(DIM(` ${abs}`));
|
|
84
|
+
const head = previewHead(abs, 5);
|
|
85
|
+
for (const line of head.split('\n')) {
|
|
86
|
+
console.log(` ${line}`);
|
|
87
|
+
}
|
|
88
|
+
console.log('');
|
|
89
|
+
}
|
|
90
|
+
return 0;
|
|
91
|
+
}
|
|
92
|
+
const abs = resolveExamplePath(stack);
|
|
93
|
+
if (!abs) {
|
|
94
|
+
process.stderr.write(`\x1b[31m[claude-autopilot] unknown stack "${stack}" — valid: ${EXAMPLE_STACK_IDS.join(', ')}\x1b[0m\n`);
|
|
95
|
+
return 1;
|
|
96
|
+
}
|
|
97
|
+
if (!fs.existsSync(abs)) {
|
|
98
|
+
process.stderr.write(`\x1b[31m[claude-autopilot] example file missing on disk: ${abs}\x1b[0m\n`);
|
|
99
|
+
process.stderr.write(`\x1b[2m Did the published tarball include the "examples/" directory? See package.json "files".\x1b[0m\n`);
|
|
100
|
+
return 1;
|
|
101
|
+
}
|
|
102
|
+
const body = fs.readFileSync(abs, 'utf8');
|
|
103
|
+
process.stdout.write(body);
|
|
104
|
+
if (!body.endsWith('\n'))
|
|
105
|
+
process.stdout.write('\n');
|
|
106
|
+
return 0;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=examples.js.map
|
|
@@ -29,6 +29,7 @@ export const HELP_GROUPS = [
|
|
|
29
29
|
{ verb: 'init', summary: 'Scaffold guardrail.config.yaml + auto-detect migrate stack (writes .autopilot/stack.md)' },
|
|
30
30
|
{ verb: 'setup', summary: 'Auto-detect stack, write config, install pre-push hook' },
|
|
31
31
|
{ verb: 'scaffold', summary: 'Scaffold project skeleton from a spec markdown (--from-spec <path> [--stack node|python|fastapi|go|rust])' },
|
|
32
|
+
{ verb: 'examples', summary: 'Print sample specs for each supported stack (use as starter templates for `scaffold --from-spec`)' },
|
|
32
33
|
{ verb: 'autopilot', summary: 'Multi-phase orchestrator — run scan → spec → plan → implement under one runId (v6.2.0)' },
|
|
33
34
|
{ verb: 'brainstorm', summary: 'Pipeline entry point (Claude Code skill — see /brainstorm)' },
|
|
34
35
|
{ verb: 'spec', summary: 'Spec-writing pointer (Claude Code skill — see /brainstorm)' },
|
|
@@ -213,6 +214,18 @@ export const HELP_OPTIONS = {
|
|
|
213
214
|
claude-autopilot autopilot
|
|
214
215
|
claude-autopilot autopilot --budget 25
|
|
215
216
|
claude-autopilot autopilot --phases=scan,spec,plan`,
|
|
217
|
+
examples: `Options (examples):
|
|
218
|
+
[<stack>] Optional: print only the spec for one stack (node|python|fastapi|go|rust)
|
|
219
|
+
With no arg, lists all supported stacks with a 5-line preview each.
|
|
220
|
+
|
|
221
|
+
Behavior: read-only. Reads bundled spec files from the package's
|
|
222
|
+
\`examples/specs/\` directory and prints them to stdout. Pipe
|
|
223
|
+
to a file to use as a starter template:
|
|
224
|
+
|
|
225
|
+
claude-autopilot examples node > docs/specs/my-feature.md
|
|
226
|
+
claude-autopilot scaffold --from-spec docs/specs/my-feature.md
|
|
227
|
+
|
|
228
|
+
Exit codes: 0 success, 1 unknown stack id or missing bundled file.`,
|
|
216
229
|
dashboard: `Options (dashboard):
|
|
217
230
|
login Open browser, mint API key via loopback callback
|
|
218
231
|
logout Revoke server-side, delete local config
|
package/dist/src/cli/index.js
CHANGED
|
@@ -226,7 +226,7 @@ These are aliases for the flat subcommands; they still work without the 'advance
|
|
|
226
226
|
// gc, delete, doctor) are dispatched inside its case block. The singular
|
|
227
227
|
// `run resume` form is handled BEFORE the default `run` -> review dispatch
|
|
228
228
|
// kicks in (see disambiguation block just below).
|
|
229
|
-
const SUBCOMMANDS = ['init', 'run', 'runs', 'scan', 'report', 'explain', 'ignore', 'ci', 'pr', 'fix', 'costs', 'watch', 'hook', 'autoregress', 'baseline', 'triage', 'lsp', 'worker', 'mcp', 'test-gen', 'pr-desc', 'doctor', 'preflight', 'setup', 'council', 'migrate-v4', 'migrate', 'migrate-doctor', 'deploy', 'brainstorm', 'spec', 'plan', 'implement', 'review', 'validate', 'autopilot', 'internal', 'help', '--help', '-h'];
|
|
229
|
+
const SUBCOMMANDS = ['init', 'run', 'runs', 'scan', 'report', 'explain', 'ignore', 'ci', 'pr', 'fix', 'costs', 'watch', 'hook', 'autoregress', 'baseline', 'triage', 'lsp', 'worker', 'mcp', 'test-gen', 'pr-desc', 'doctor', 'preflight', 'setup', 'council', 'migrate-v4', 'migrate', 'migrate-doctor', 'deploy', 'brainstorm', 'spec', 'plan', 'implement', 'review', 'validate', 'autopilot', 'examples', 'internal', 'help', '--help', '-h'];
|
|
230
230
|
const VALUE_FLAGS = ['base', 'config', 'files', 'format', 'output', 'debounce', 'ask', 'focus', 'fail-on', 'note', 'reason', 'expires', 'profile', 'severity', 'prompt', 'context-file', 'path', 'adapter', 'ref', 'sha', 'spec', 'context', 'mode', 'phases', 'budget', 'stack'];
|
|
231
231
|
// Bare invocation — no subcommand, no flags → show welcome guide
|
|
232
232
|
if (args.length === 0) {
|
|
@@ -993,6 +993,17 @@ switch (subcommand) {
|
|
|
993
993
|
process.exit(0);
|
|
994
994
|
break;
|
|
995
995
|
}
|
|
996
|
+
case 'examples': {
|
|
997
|
+
// v7.7.1 — `claude-autopilot examples [<stack>]`. Bridges the
|
|
998
|
+
// discoverability gap between `setup` and `scaffold --from-spec` —
|
|
999
|
+
// new users don't know what a spec looks like. Optional positional
|
|
1000
|
+
// arg selects a single stack; no arg lists all five.
|
|
1001
|
+
const { runExamples } = await import("./examples.js");
|
|
1002
|
+
const target = args[1] && !args[1].startsWith('--') ? args[1] : undefined;
|
|
1003
|
+
const code = runExamples(target);
|
|
1004
|
+
process.exit(code);
|
|
1005
|
+
break;
|
|
1006
|
+
}
|
|
996
1007
|
case 'council': {
|
|
997
1008
|
const config = flag('config');
|
|
998
1009
|
const prompt = flag('prompt');
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { GuardrailError } from '../errors.ts';
|
|
2
|
+
import { SerializedWriter } from '../run-state/serialized-writer.ts';
|
|
3
|
+
/** Budget caps for a single run. `perRunUSD` is the hard ceiling on total
|
|
4
|
+
* committed spend (spent + active reservations) across all concurrent
|
|
5
|
+
* tasks. `perSubagentUSD` is the per-task hard cap that dispatch refuses
|
|
6
|
+
* to exceed even if perRunUSD has headroom. */
|
|
7
|
+
export interface BudgetCaps {
|
|
8
|
+
/** Total USD this run is allowed to commit across all subagents +
|
|
9
|
+
* in-flight reservations. */
|
|
10
|
+
perRunUSD: number;
|
|
11
|
+
/** Hard per-subagent cap. A pre-flight estimate exceeding this rejects
|
|
12
|
+
* dispatch; an actual cost exceeding it mid-execution triggers the
|
|
13
|
+
* scheduler's SIGTERM path (PR 4) — this layer just emits the
|
|
14
|
+
* `task.failed` event with `error_type: 'budget_exceeded'`. */
|
|
15
|
+
perSubagentUSD: number;
|
|
16
|
+
}
|
|
17
|
+
/** Per-task ledger entry. Reconstructed via `replayFromEvents` at startup
|
|
18
|
+
* / resume. */
|
|
19
|
+
export interface ReservationEntry {
|
|
20
|
+
task_id: string;
|
|
21
|
+
/** Latest reservation value (after any
|
|
22
|
+
* `task.budget_increased_reservation` events; ABSOLUTE, not delta). */
|
|
23
|
+
reserved_usd: number;
|
|
24
|
+
/** True once `task.budget_released` has landed for this task. */
|
|
25
|
+
released: boolean;
|
|
26
|
+
/** Actual cost if `released` is true. */
|
|
27
|
+
actual_cost_usd?: number;
|
|
28
|
+
}
|
|
29
|
+
/** Result of replaying events.ndjson into a fresh ledger state. */
|
|
30
|
+
export interface BudgetReplaySummary {
|
|
31
|
+
/** Sum of `actual_cost_usd` across released tasks. Committed against
|
|
32
|
+
* `perRunUSD` permanently. */
|
|
33
|
+
spentTotal: number;
|
|
34
|
+
/** Sum of `reserved_usd` for tasks NOT yet released. Each task
|
|
35
|
+
* contributes its LATEST reservation (absolute value), not the sum of
|
|
36
|
+
* reserved + increased values. */
|
|
37
|
+
activeReservedTotal: number;
|
|
38
|
+
/** `spentTotal + activeReservedTotal`. The number the headroom check
|
|
39
|
+
* compares against `perRunUSD`. */
|
|
40
|
+
committedTotal: number;
|
|
41
|
+
/** Per-task latest state. */
|
|
42
|
+
perTask: Map<string, ReservationEntry>;
|
|
43
|
+
}
|
|
44
|
+
/** Thrown by `reserve()` / `increaseReservation()` when the requested
|
|
45
|
+
* amount would push the run over `perRunUSD`, or when a pre-flight
|
|
46
|
+
* exceeds `perSubagentUSD`. Carries the GuardrailError code
|
|
47
|
+
* `budget_exceeded` for upstream resume classification. */
|
|
48
|
+
export declare class BudgetExceededError extends GuardrailError {
|
|
49
|
+
constructor(message: string, details: Record<string, unknown>);
|
|
50
|
+
}
|
|
51
|
+
export interface ReserveOptions {
|
|
52
|
+
/** Pre-flight cost estimate for the task in USD. */
|
|
53
|
+
preFlightEstimateUsd: number;
|
|
54
|
+
/** Budget caps for this run. */
|
|
55
|
+
caps: BudgetCaps;
|
|
56
|
+
}
|
|
57
|
+
export interface IncreaseReservationOptions {
|
|
58
|
+
/** New reservation total (NOT a delta — the absolute new value). */
|
|
59
|
+
newReservedUsd: number;
|
|
60
|
+
/** Free-form reason captured on the event. */
|
|
61
|
+
reason: string;
|
|
62
|
+
/** Budget caps for this run. */
|
|
63
|
+
caps: BudgetCaps;
|
|
64
|
+
}
|
|
65
|
+
export interface ReleaseOptions {
|
|
66
|
+
/** Actual cost spent by the subagent (from telemetry). */
|
|
67
|
+
actualCostUsd: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Budget reservation ledger. One instance per run, owned by the scheduler.
|
|
71
|
+
* All mutations route through the supplied `SerializedWriter` and re-replay
|
|
72
|
+
* events.ndjson under the exclusive lock so they are atomic against
|
|
73
|
+
* concurrent callers AND any other `BudgetReservation` instances pointed at
|
|
74
|
+
* the same run.
|
|
75
|
+
*/
|
|
76
|
+
export declare class BudgetReservation {
|
|
77
|
+
private readonly writer;
|
|
78
|
+
/** In-memory mirror of disk state, kept for fast `snapshot()` reads.
|
|
79
|
+
* NOT authoritative — every mutating operation re-replays the on-disk
|
|
80
|
+
* log inside the writer's exclusive lock before checking caps. Per-task
|
|
81
|
+
* reservations stored in USD (public API); the running totals below are
|
|
82
|
+
* in MICROS (integer-safe arithmetic). */
|
|
83
|
+
private reservations;
|
|
84
|
+
private spentMicros;
|
|
85
|
+
private activeReservedMicros;
|
|
86
|
+
constructor(writer: SerializedWriter);
|
|
87
|
+
/** Re-seed in-memory state from events.ndjson. Call on construction OR
|
|
88
|
+
* on resume. Safe to call multiple times — overwrites the cache. */
|
|
89
|
+
hydrateFromEvents(eventsNdjsonPath: string): Promise<void>;
|
|
90
|
+
/** Read the current in-memory state. Best-effort: a concurrent writer
|
|
91
|
+
* in another instance could make this stale until the next mutating
|
|
92
|
+
* call re-hydrates from disk. */
|
|
93
|
+
snapshot(): BudgetReplaySummary;
|
|
94
|
+
/**
|
|
95
|
+
* Reserve budget for a task. Atomic under the writer lock:
|
|
96
|
+
*
|
|
97
|
+
* 1. HARD cap check (pre-lock): `preFlightEstimate <= caps.perSubagentUSD`
|
|
98
|
+
* 2. Acquire SerializedWriter lock
|
|
99
|
+
* 3. Re-replay events.ndjson from disk (authoritative)
|
|
100
|
+
* 4. Verify task doesn't already have an in-flight reservation
|
|
101
|
+
* 5. Verify `caps.perRunUSD - committedTotal >= preFlightEstimate`
|
|
102
|
+
* (committedTotal = spent + active reservations)
|
|
103
|
+
* 6. If pass: append `task.budget_reserved` event + fsync
|
|
104
|
+
* If fail: append `task.budget_halt` event + fsync, then throw
|
|
105
|
+
* 7. Release lock
|
|
106
|
+
*
|
|
107
|
+
* Throws `BudgetExceededError` on cap violations. The `task.budget_halt`
|
|
108
|
+
* variant is durable: the event lands inside the same critical section
|
|
109
|
+
* before the throw propagates, so a crash post-throw still surfaces the
|
|
110
|
+
* halt on resume.
|
|
111
|
+
*/
|
|
112
|
+
reserve(taskId: string, opts: ReserveOptions): Promise<void>;
|
|
113
|
+
/**
|
|
114
|
+
* Bump an in-flight reservation to a new ABSOLUTE value. Atomic under
|
|
115
|
+
* the writer lock; re-replays disk state before checking caps.
|
|
116
|
+
* Re-checks `perRunUSD` against the NEW reservation total; halts the
|
|
117
|
+
* run with `task.budget_halt` if the bump would exceed the cap.
|
|
118
|
+
*
|
|
119
|
+
* Throws `BudgetExceededError` (with durable `task.budget_halt`) if no
|
|
120
|
+
* prior reservation exists, the bump is downward (use `release`
|
|
121
|
+
* instead), or the bump exceeds caps.
|
|
122
|
+
*/
|
|
123
|
+
increaseReservation(taskId: string, opts: IncreaseReservationOptions): Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* Release a reservation with the actual cost. Atomic under the writer
|
|
126
|
+
* lock; re-replays disk state. Moves the task's commitment from
|
|
127
|
+
* `activeReserved` to `spent`. Emits `task.budget_released` with
|
|
128
|
+
* `delta_vs_reservation_usd` (positive = under, negative = over).
|
|
129
|
+
*
|
|
130
|
+
* Note: a release with `actualCostUsd > reserved_usd` is NOT a halt —
|
|
131
|
+
* the budget was already committed at reservation time. The scheduler
|
|
132
|
+
* is expected to issue `increaseReservation` mid-flight when telemetry
|
|
133
|
+
* suggests overrun, and to emit `task.failed{error_type:'budget_exceeded'}`
|
|
134
|
+
* if the increase itself fails. This `release` just records the truth.
|
|
135
|
+
*/
|
|
136
|
+
release(taskId: string, opts: ReleaseOptions): Promise<void>;
|
|
137
|
+
/** Internal: replace in-memory ledger from a replay summary (in micros).
|
|
138
|
+
* Used by every mutating method to re-sync cache with disk under the
|
|
139
|
+
* lock. */
|
|
140
|
+
private applyReplayMicros;
|
|
141
|
+
/**
|
|
142
|
+
* Replay events.ndjson into a fresh `BudgetReplaySummary` (decimal USD).
|
|
143
|
+
* Used by:
|
|
144
|
+
* 1. `hydrateFromEvents` — runtime cache seed on resume / startup
|
|
145
|
+
* 2. tests — to assert reconstruction is exact
|
|
146
|
+
*
|
|
147
|
+
* Internally calls `replayFromEventsMicros` and converts to USD at the
|
|
148
|
+
* boundary so external consumers see decimal numbers, but the fold itself
|
|
149
|
+
* is integer-micro arithmetic.
|
|
150
|
+
*
|
|
151
|
+
* Line parsing is lenient: blank lines are skipped, parse failures stop
|
|
152
|
+
* the walk (treated as truncated tail; the next `appendEvent` would
|
|
153
|
+
* emit `run.recovery`, and budget state stays consistent up to the
|
|
154
|
+
* last-known-good line).
|
|
155
|
+
*/
|
|
156
|
+
static replayFromEvents(eventsNdjsonPath: string): BudgetReplaySummary;
|
|
157
|
+
/**
|
|
158
|
+
* Internal: micro-precision replay. Used by every mutating method INSIDE
|
|
159
|
+
* `withExclusive` so cap checks operate on integer arithmetic.
|
|
160
|
+
*/
|
|
161
|
+
private static replayFromEventsMicros;
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=budget-reservation.d.ts.map
|