@robmclarty/volley 0.8.0 → 0.9.0
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 +22 -0
- package/README.md +145 -37
- package/dist/cli.js +720 -185
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +109 -12
- package/dist/index.js +692 -272
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/builder/presets/harness_append_local.md +2 -1
- package/src/critic/presets/harness_append_local.md +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -32,7 +32,13 @@ type RunStatus = 'running' | 'success' | 'budget_exhausted' | 'cost_cap_reached'
|
|
|
32
32
|
/** The builder edited the gate that judges it, under `--fail-on-gate-edit`:
|
|
33
33
|
* the run halts on the spot rather than iterating, because a check the builder
|
|
34
34
|
* can rewrite is not evidence the work is done. */
|
|
35
|
-
'gate_edit_blocked' |
|
|
35
|
+
'gate_edit_blocked' |
|
|
36
|
+
/** A critique's other outcome: the critic requested changes, or the check
|
|
37
|
+
* failed, on the one change it reviewed. A run never ends this way. */
|
|
38
|
+
'rejected' | 'interrupted' | 'error';
|
|
39
|
+
/** What a run does: the builder/critic loop (`run`), or one check and one
|
|
40
|
+
* critique of a change already made, with no builder at all (`critique`). */
|
|
41
|
+
type RunMode = 'run' | 'critique';
|
|
36
42
|
/** User-facing configuration, before resolution (config file / flags). */
|
|
37
43
|
type VolleyConfig = {
|
|
38
44
|
prompt: string;
|
|
@@ -43,6 +49,7 @@ type VolleyConfig = {
|
|
|
43
49
|
builder_provider?: BuilderProvider;
|
|
44
50
|
builder_url?: string;
|
|
45
51
|
builder_max_steps?: number;
|
|
52
|
+
builder_max_tool_calls?: number;
|
|
46
53
|
allow_unsandboxed_builder?: boolean;
|
|
47
54
|
critic_model?: string;
|
|
48
55
|
critic_provider?: CriticProvider;
|
|
@@ -69,6 +76,13 @@ type ResolvedConfig = {
|
|
|
69
76
|
version: 2;
|
|
70
77
|
run_id: string;
|
|
71
78
|
started_at: string;
|
|
79
|
+
/** A run, or a critique (`volley critique`). A critique's builder fields
|
|
80
|
+
* hold the defaults, untouched by flags and the environment, since no
|
|
81
|
+
* builder is ever constructed, and its loop settings are one round with
|
|
82
|
+
* nothing isolated or committed. */
|
|
83
|
+
mode: RunMode;
|
|
84
|
+
/** The task. A critique needs none, since a critic judges against the
|
|
85
|
+
* criteria alone, so it's empty unless one was given to record. */
|
|
72
86
|
prompt: string;
|
|
73
87
|
criteria: string;
|
|
74
88
|
check: CheckMode;
|
|
@@ -84,6 +98,11 @@ type ResolvedConfig = {
|
|
|
84
98
|
* lmstudio, openrouter) takes one. */
|
|
85
99
|
builder_url: string | null;
|
|
86
100
|
builder_max_steps: number;
|
|
101
|
+
/** How many tool calls a tool-loop builder may make in one turn; fascicle
|
|
102
|
+
* runs the first that many, in order, and drops the rest. 1 by default,
|
|
103
|
+
* since some model and runtime pairs return parallel calls badly; raise it
|
|
104
|
+
* for a pair that handles them. Ignored by the `claude_cli` builder. */
|
|
105
|
+
builder_max_tool_calls: number;
|
|
87
106
|
/** Operator opt-out permitting a non-`claude_cli` builder to run without a
|
|
88
107
|
* sandbox — it gets a real host bash. Refused by default. */
|
|
89
108
|
allow_unsandboxed_builder: boolean;
|
|
@@ -127,9 +146,12 @@ type ResolvedConfig = {
|
|
|
127
146
|
* `VOLLEY_SANDBOX_IMAGE` override it. Meaningful only for a local builder —
|
|
128
147
|
* the `claude_cli` path never uses Docker. */
|
|
129
148
|
sandbox_image: string;
|
|
130
|
-
/** The root that holds each run's state at `<state_dir>/<run_id
|
|
131
|
-
*
|
|
132
|
-
*
|
|
149
|
+
/** The root that holds each run's state at `<state_dir>/<run_id>/`, as an
|
|
150
|
+
* absolute path: `--state-dir`, else the default root,
|
|
151
|
+
* `$XDG_STATE_HOME/volley` or `~/.local/state/volley`. `resolve_config`
|
|
152
|
+
* always sets one. Null is the layout older runs used, `<workspace>/.volley/`,
|
|
153
|
+
* rotated aside by the next fresh run: a run an older volley started
|
|
154
|
+
* resumes in it, and a hand-built config can still ask for it. */
|
|
133
155
|
state_dir: string | null;
|
|
134
156
|
workspace: string;
|
|
135
157
|
verbose: boolean;
|
|
@@ -270,7 +292,7 @@ type LoopState = {
|
|
|
270
292
|
halt: HaltReason;
|
|
271
293
|
cost_warned: boolean;
|
|
272
294
|
};
|
|
273
|
-
/** Projection of final loop state;
|
|
295
|
+
/** Projection of final loop state; the run's `summary.json` mirrors this. */
|
|
274
296
|
type RunResult = {
|
|
275
297
|
run_id: string;
|
|
276
298
|
status: RunStatus;
|
|
@@ -288,8 +310,15 @@ type RunResult = {
|
|
|
288
310
|
* other copy of its effects, so teardown commits them onto `volley/<run id>`
|
|
289
311
|
* and keeps the branch instead of force-deleting it. Null whenever nothing
|
|
290
312
|
* survived — every non-worktree run, every integrated run, every discarded
|
|
291
|
-
* one. `--json` consumers read it here;
|
|
313
|
+
* one. `--json` consumers read it here; the run's `summary.json` mirrors it. */
|
|
292
314
|
salvaged_branch: string | null;
|
|
315
|
+
/** A run, or a critique, which runs no builder. */
|
|
316
|
+
mode: RunMode;
|
|
317
|
+
/** Where this run keeps its config, summary, trajectory, feedback, verdict,
|
|
318
|
+
* and iterations: `<state_dir>/<run_id>/` under a state root, else the
|
|
319
|
+
* workspace's `.volley/`. Inside the sandbox container it is the container's
|
|
320
|
+
* path, which a harness maps back to the directory it mounted. */
|
|
321
|
+
run_state_dir: string;
|
|
293
322
|
};
|
|
294
323
|
//#endregion
|
|
295
324
|
//#region src/config.d.ts
|
|
@@ -307,6 +336,12 @@ type ResolveOptions = {
|
|
|
307
336
|
* while under `volley acp` each of its commands `ask`s a person first, which
|
|
308
337
|
* takes the container's place. */
|
|
309
338
|
uncontained_builder?: 'refuse' | 'ask';
|
|
339
|
+
/** Where the run's state goes, in place of what the config says: `volley
|
|
340
|
+
* resume` passes the root it found the run under, or null for a run an older
|
|
341
|
+
* volley kept in the workspace's `.volley/`, which resumes there. */
|
|
342
|
+
state_dir?: string | null;
|
|
343
|
+
/** A run (the default), or a critique, which has no builder or loop. */
|
|
344
|
+
mode?: RunMode;
|
|
310
345
|
};
|
|
311
346
|
/** Merge, expand, and validate a raw `VolleyConfig` into a `ResolvedConfig`.
|
|
312
347
|
* `check_resolved` comes from check detection against the workspace, so the
|
|
@@ -365,13 +400,19 @@ type BuilderDeps = {
|
|
|
365
400
|
};
|
|
366
401
|
//#endregion
|
|
367
402
|
//#region src/critic/run.d.ts
|
|
403
|
+
/** A critic that holds tools isn't constrain-decoded, so nothing stops it
|
|
404
|
+
* answering null for the feedback or the unmet list, as GLM did on approving.
|
|
405
|
+
* Both fields allow null and read it as empty, so that answer is a verdict
|
|
406
|
+
* rather than a schema failure that ends the run. fascicle sends the schema's
|
|
407
|
+
* input side, so the model sees each field as its type or null, still
|
|
408
|
+
* required; `.describe()` comes last so the description stays on the field. */
|
|
368
409
|
export declare const verdict_schema: z.ZodObject<{
|
|
369
410
|
verdict: z.ZodEnum<{
|
|
370
411
|
approved: "approved";
|
|
371
412
|
changes_requested: "changes_requested";
|
|
372
413
|
}>;
|
|
373
|
-
feedback: z.ZodString
|
|
374
|
-
unmet_criteria: z.ZodArray<z.ZodString
|
|
414
|
+
feedback: z.ZodPipe<z.ZodNullable<z.ZodString>, z.ZodTransform<string, string | null>>;
|
|
415
|
+
unmet_criteria: z.ZodPipe<z.ZodNullable<z.ZodArray<z.ZodString>>, z.ZodTransform<string[], string[] | null>>;
|
|
375
416
|
}, z.core.$strip>;
|
|
376
417
|
type VerdictOutput = z.infer<typeof verdict_schema>;
|
|
377
418
|
type CriticDeps = {
|
|
@@ -399,7 +440,7 @@ type RendererOptions = {
|
|
|
399
440
|
color: boolean;
|
|
400
441
|
max_cost_usd: number | null;
|
|
401
442
|
/** Where the run's trajectory is written, named when verbose output is cut
|
|
402
|
-
* short (default:
|
|
443
|
+
* short (default: "the run's trajectory.jsonl"). */
|
|
403
444
|
trajectory_path?: string;
|
|
404
445
|
write?: (text: string) => void;
|
|
405
446
|
};
|
|
@@ -467,6 +508,25 @@ type OrchestratorDeps = {
|
|
|
467
508
|
install_signal_handlers?: boolean;
|
|
468
509
|
};
|
|
469
510
|
export declare function run_volley(config: ResolvedConfig, deps: OrchestratorDeps, resume_from?: LoopState | null): Promise<RunResult>;
|
|
511
|
+
/** What a critique runs with: what a run does, less the builder's seat, plus
|
|
512
|
+
* the revision its change is measured from. */
|
|
513
|
+
type CritiqueDeps = Omit<OrchestratorDeps, 'seats'> & {
|
|
514
|
+
/** The revision the change under review is measured from (`--baseline`):
|
|
515
|
+
* everything that differs from it, committed or not, untracked files
|
|
516
|
+
* included. HEAD when absent, so the uncommitted edits are the change. */
|
|
517
|
+
baseline?: string;
|
|
518
|
+
/** The critic's tools in place of volley's reads, as for a run's critic. */
|
|
519
|
+
critic?: Omit<CriticSeat, 'engine'>;
|
|
520
|
+
};
|
|
521
|
+
/**
|
|
522
|
+
* `volley critique`: the check and the critic, once, over a change already
|
|
523
|
+
* made. No builder is constructed, and the engine serves the critic's seat
|
|
524
|
+
* alone, so a critic can be measured on fixed, labeled changes without paying
|
|
525
|
+
* for builder turns. It writes the state a one-round run does, with the mode
|
|
526
|
+
* recorded, and ends `success` on approval over a green check, else
|
|
527
|
+
* `rejected`.
|
|
528
|
+
*/
|
|
529
|
+
export declare function run_critique(config: ResolvedConfig, deps: CritiqueDeps): Promise<RunResult>;
|
|
470
530
|
//#endregion
|
|
471
531
|
//#region src/loop_state.d.ts
|
|
472
532
|
export declare function initial_state(): LoopState;
|
|
@@ -485,6 +545,13 @@ export declare function gate(config: ResolvedConfig, state: LoopState): {
|
|
|
485
545
|
export declare function status_of(value: LoopState, converged: boolean): RunStatus;
|
|
486
546
|
//#endregion
|
|
487
547
|
//#region src/sandbox.d.ts
|
|
548
|
+
/** Where volley inside the container keeps each run's state when no
|
|
549
|
+
* `--state-dir` names a root: the default root under the pinned `HOME`, since
|
|
550
|
+
* the image sets no `XDG_STATE_HOME`. `sandbox_run_args`'s `run_state` binds one
|
|
551
|
+
* run's host directory at that run's directory under it, so the state outlives
|
|
552
|
+
* the `--rm` container. Exported so a harness can map a contained run's
|
|
553
|
+
* `run_state_dir` back to the directory it mounted. */
|
|
554
|
+
export declare const SANDBOX_STATE_ROOT: string;
|
|
488
555
|
/** Canonical identity of the allowlist bridge the examples create (`docker
|
|
489
556
|
* network create --subnet <SANDBOX_NETWORK_SUBNET> <SANDBOX_NETWORK_NAME>`) and
|
|
490
557
|
* the host `DOCKER-USER` rules scope to. Exported so the blessed examples
|
|
@@ -530,7 +597,7 @@ export declare function network_run_args(network: SandboxNetwork, network_name:
|
|
|
530
597
|
/**
|
|
531
598
|
* The hardened `docker run` argv that launches volley inside its container.
|
|
532
599
|
* Pure and exported so the flag set is unit-testable without a
|
|
533
|
-
* daemon and the blessed examples
|
|
600
|
+
* daemon and the blessed examples and a parent harness can render it.
|
|
534
601
|
*
|
|
535
602
|
* A one-shot, foreground `--rm` container — the whole run *is* this
|
|
536
603
|
* container (an earlier design ran a detached `-d … sleep infinity` daemon volley
|
|
@@ -542,6 +609,25 @@ export declare function network_run_args(network: SandboxNetwork, network_name:
|
|
|
542
609
|
* the image entrypoint (the opt-in real-docker isolation test runs a raw `sh`
|
|
543
610
|
* this way).
|
|
544
611
|
*
|
|
612
|
+
* `run_state` binds the run's own state directory on the host,
|
|
613
|
+
* `<root>/<run_id>/`, at `<SANDBOX_STATE_ROOT>/<run_id>/`, where volley inside
|
|
614
|
+
* keeps that run's state when no `--state-dir` names a root, so it outlives the
|
|
615
|
+
* container at the path a run on the host would use. Only the one directory
|
|
616
|
+
* is mounted, never the root: the builder inside runs arbitrary commands, so
|
|
617
|
+
* it can rewrite its own run's state but can't read another run's trajectory
|
|
618
|
+
* or plant a check in another run's config. Its own run's state is still the
|
|
619
|
+
* builder's to rewrite, config.json included, so a host-side resume refuses
|
|
620
|
+
* that config, which volley signs only outside the sandbox (`./trust.ts`), and
|
|
621
|
+
* a directory holding a symlink: resume a contained run inside the container,
|
|
622
|
+
* with the same mount. Create the
|
|
623
|
+
* directory on the host first, empty (Docker on Linux makes a missing bind
|
|
624
|
+
* source owned by root, which the container's user can't write), and pass the
|
|
625
|
+
* same id to volley as `--run-id`. Keep it outside `build_root`, so the check
|
|
626
|
+
* never reads it, and pass no `XDG_STATE_HOME` in `env`, which would move the
|
|
627
|
+
* root off the mount. Omit it and no state is mounted: a contained run keeping
|
|
628
|
+
* its state under the default root then stops before spending (exit 5),
|
|
629
|
+
* since the read-only root filesystem leaves it nowhere to write.
|
|
630
|
+
*
|
|
545
631
|
* `store_volume` mounts the named volume as the pnpm store; omit it and no store
|
|
546
632
|
* is mounted. A store is shared by every run that mounts it, so a caller that
|
|
547
633
|
* installs dependencies in a separate container first can keep the builder's
|
|
@@ -551,13 +637,17 @@ export declare function network_run_args(network: SandboxNetwork, network_name:
|
|
|
551
637
|
* Never emits `--privileged` and refuses `--user 0`: volley must not hand
|
|
552
638
|
* the sandbox root or full capabilities. Everything writable under the
|
|
553
639
|
* `--read-only` rootfs is an explicit tmpfs or volume; the bind-mounted worktree
|
|
554
|
-
* is the
|
|
640
|
+
* and, when one is named, the state root are the host-visible write paths.
|
|
555
641
|
*/
|
|
556
642
|
export declare function sandbox_run_args(options: {
|
|
557
643
|
image: string;
|
|
558
644
|
build_root: string;
|
|
559
645
|
uid: number | null;
|
|
560
646
|
gid: number | null;
|
|
647
|
+
run_state?: {
|
|
648
|
+
root: string;
|
|
649
|
+
run_id: string;
|
|
650
|
+
} | null;
|
|
561
651
|
store_volume?: string | null;
|
|
562
652
|
network: SandboxNetwork;
|
|
563
653
|
network_name: string;
|
|
@@ -568,6 +658,13 @@ export declare function sandbox_run_args(options: {
|
|
|
568
658
|
command?: ReadonlyArray<string>;
|
|
569
659
|
}): string[];
|
|
570
660
|
//#endregion
|
|
661
|
+
//#region src/workspace.d.ts
|
|
662
|
+
/** The root each run's state sits under when `--state-dir` names none:
|
|
663
|
+
* `$XDG_STATE_HOME/volley`, else `<home>/.local/state/volley`. A relative
|
|
664
|
+
* `XDG_STATE_HOME` is ignored, as the XDG spec says. `home` is the host's by
|
|
665
|
+
* default; the sandbox passes its container's to spell the same root inside. */
|
|
666
|
+
export declare function default_state_root(env: Readonly<Record<string, string | undefined>>, home?: string): string;
|
|
667
|
+
//#endregion
|
|
571
668
|
//#region src/exit_codes.d.ts
|
|
572
669
|
export declare const EXIT_SUCCESS = 0;
|
|
573
670
|
export declare const EXIT_BUDGET_EXHAUSTED = 2;
|
|
@@ -580,5 +677,5 @@ export declare const EXIT_INTERRUPTED = 130;
|
|
|
580
677
|
export declare function exit_code_for_status(status: RunStatus): number;
|
|
581
678
|
export declare function exit_code_for_error(err: unknown): number;
|
|
582
679
|
//#endregion
|
|
583
|
-
export type { BuilderPermissionMode, CheckArtifact, CheckMode, CheckResult, CheckRunnerKind, CostSource, CriticPreset, CriticProvider, HaltReason, LoopState, PhaseRecord, RenderMode, Renderer, RendererOptions, ResolvedConfig, RunResult, RunStatus, SandboxNetwork, Verdict, VerdictOutput, VolleyConfig };
|
|
680
|
+
export type { BuilderPermissionMode, CheckArtifact, CheckMode, CheckResult, CheckRunnerKind, CostSource, CriticPreset, CriticProvider, CritiqueDeps, HaltReason, LoopState, PhaseRecord, RenderMode, Renderer, RendererOptions, ResolvedConfig, RunMode, RunResult, RunStatus, SandboxNetwork, Verdict, VerdictOutput, VolleyConfig };
|
|
584
681
|
//# sourceMappingURL=index.d.ts.map
|