@staix/agent-research 0.1.0 → 0.2.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 +30 -0
- package/README.md +108 -14
- package/package.json +4 -2
- package/src/autonomy.ts +50 -0
- package/src/cli.ts +18 -5
- package/src/commands-table.ts +6 -3
- package/src/commands.ts +56 -15
- package/src/copilot.ts +91 -0
- package/src/exp/attempts.ts +12 -4
- package/src/exp/investigate.ts +7 -2
- package/src/exp/protocol.ts +4 -1
- package/src/http.ts +46 -2
- package/src/lit/watch.ts +14 -1
- package/src/manifest.ts +3 -2
- package/src/mcp-tools.ts +18 -8
- package/src/mcp.ts +2 -0
- package/src/memory/archive.ts +3 -0
- package/src/paper/build.ts +4 -1
- package/src/paper/check.ts +4 -3
- package/src/paper/placeholders.ts +5 -3
- package/src/paper/review.ts +15 -3
- package/src/plan/controller.ts +42 -12
- package/src/plan/definition.ts +17 -5
- package/src/plan/state.ts +53 -17
- package/src/playbook.ts +14 -2
- package/src/study-export.ts +254 -0
- package/src/study.ts +45 -17
- package/src/ui/panel.js +8 -3
- package/src/ui/plugin.ts +21 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## [0.2.1] - 2026-11-08
|
|
6
|
+
|
|
7
|
+
- Fix release clean-install smoke to compare installed schema versions with the checkout's FORMAT_VERSIONS, including study v2; an offline regression runs in the ordinary check (#88).
|
|
8
|
+
|
|
9
|
+
- v0.2.0 was tagged but never published because its release smoke failed. This patch ships the fix without moving that tag.
|
|
10
|
+
|
|
11
|
+
## [0.2.0] - 2026-11-07
|
|
12
|
+
|
|
13
|
+
N-1 compatibility against 0.1.0, the latest published patch of the 0.1 minor line, checked by the `n1` CI job (`bun scripts/n1-check.ts`) on this release commit:
|
|
14
|
+
|
|
15
|
+
- N-1 CLI: every 0.1.0 command and usage (57 commands) remains, and each usage keeps every 0.1.0 word in order. Changes are additive only: new commands (`autonomy show|set`, `study export`), new optional options and wider enums (`init --autonomy auto|gates|copilot|step`, `accept:<artifact>` gates).
|
|
16
|
+
- N-1 MCP tools: every 0.1.0 tool (52 tools) remains with the same `readOnly` value. New tools are `ares_autonomy_show`, `ares_autonomy_set` and `ares_study_export`.
|
|
17
|
+
- N-1 study/ledger formats: 0.2.0 reads 0.1.0-written survey and experiment studies and ledgers (status, gate list, autonomy show, lit/attempt list) without rewriting their bytes, and plain `auto|gates` studies stay study v1. 0.1.0 refuses two records only newer features write, each without changing the file: study v2 (object, `copilot` or `step` autonomy policies), with its unsupported-schema-version error, and plans whose nodes declare `phase`, with an unknown-field error. Ledger events stay version 1; `studyBundle: 1` is a new export format, not a study record.
|
|
18
|
+
|
|
19
|
+
- N-1 CI check (#85 T1): a networked `n1` CI job, required by `ci-ok`, resolves N-1 from npm (the latest stable patch of the minor line directly below the checkout's major.minor core, whether or not the checkout is published), installs it into a temp prefix and fails on any removed N-1 command or usage word, removed MCP tool or flipped `readOnly`, on the checkout rewriting an N-1 study or ledger while reading it, or on N-1 not refusing a checkout study version it does not advertise (or not reading one it does) with bytes unchanged. On the initial publication line, with no previous minor, it prints an explicit skip and exits 0; registry and parse errors still fail. `bun run check` stays offline.
|
|
20
|
+
|
|
21
|
+
- Study export scan (#83): every rule (path, URL, key-like, env) now runs on decoded JSON/JSONL keys and string values, so a raw newline or tab before a path, URL, key or env assignment can no longer hide it; refusal messages are unchanged.
|
|
22
|
+
|
|
23
|
+
- Study export (#78): `study export <dir> --bundle DIR [--list]` on CLI/MCP writes a content-free dataset bundle (`manifest.json` with `bundle: 1`, studyBundle format, hashed study id, protocol hash, seal binding, window and counts; reduced `ledger.jsonl`; `attempts.jsonl`; `results.json` reduced to numbers, booleans, hashes, closed tokens and metric identifiers; `reviews.jsonl` counts; hash-only `evidence.json`) from committed study files only, into a new or empty directory. Paths, mounts, container ids, argv, env, images (digests kept) and free text are dropped, protocol-declared metric names/units and the selection metric stay as identifiers the dataset needs, guarded by the scan; and a scan refuses the whole export on any path, URL, env value or key-like token. N-1 effect: additive command, tool and output format; no existing CLI, MCP or study/ledger format changes.
|
|
24
|
+
|
|
25
|
+
- Copilot acceptance (#52 T3): three aggregate ordinary gates bind hypotheses Markdown + idea journal, manuscript source tree (excluding derived paper/build), and the complete review journal. Only each producing phase's copilot mode enables its downstream guards; other modes retain their behavior. Producers and diagnostics remain usable for their own drafts; changed content stales acceptance, while rebuilds do not stale accepted paper source. Approval records any explicit actor without person-only rules, and never occurs automatically. Protocol/attempt/closed-investigation/paper/review/archive paths share the interlocks; plan refusals retain the exact approval next step without starting backend preparation. Existing study v2 plus v1 gate/ledger envelopes are used, with bounded regular-file source hashing and no new draft store.
|
|
26
|
+
|
|
27
|
+
- Step autonomy (#52 T2): controller admission keeps step effects exclusive even with spare parallel slots; all terminal effect outcomes (including reconciliation) and a `plan.paused` (`reason: step`) receipt share one commit when work remains; gate nodes never pause. With no remaining work, the plan finishes done/failed without another resume, and failed CLI run exits nonzero. Durable `pauseReason` survives restart; explicit CLI/MCP resume continues the existing CLI controller, while MCP starts no controller. Detached admission and unchanged polls do not consume completion. Manual gate polling checks for effective auto candidates before taking a study lock.
|
|
28
|
+
|
|
29
|
+
- Autonomy policy (#52 T1): `autonomy show|set` on CLI/MCP, four stored modes and phase overrides; only effective `auto` grants pending gates. One gate-to-phase table covers scope/screen/design/final/review; plan gates use a unique explicitly declared downstream phase, otherwise the default (including undeclared or hub targets). Policy edits preserve past decisions and record actor/from/to/phase in one commit. The controller reloads policy before approval; verified starts do not force an obsolete auto policy.
|
|
30
|
+
|
|
31
|
+
- Format and N-1 effect (#5/#52): study v2 is required for the object form and copilot/step. The new reader keeps v1 support, plain auto/gates writers keep the v1 JSON layout, and v2 is never silently downgraded. Pre-policy 0.1.x readers, including published 0.1.0, refuse v2 with their existing unsupported-version error and preserve its bytes. Optional plan-node `phase` stays in plan v1; phase-free plans are unchanged, while the older strict 0.1.0 plan reader refuses this new field without rewriting it. Existing CLI/MCP operations remain, with additive policy tools; N-1 execution of the new v2 or phase-annotated records is not claimed. The next minor release must validate and state CLI, MCP and legacy-format N-1 separately under AGENTS.md.
|
|
32
|
+
|
|
33
|
+
- CI/release (#69): one fail-closed `ci-ok` aggregate, non-cancelling main checks, exact-main-commit CI admission before release staging, scripted release preparation and annotated tagging, rerun-safe GitHub Release notes/assets with bounded 429/5xx retry, and one pinned checkout version. Release reuses the full CI result while retaining Ubuntu/macOS clean-prefix artifact smoke checks.
|
|
34
|
+
|
|
5
35
|
## [0.1.0] - 2026-11-05
|
|
6
36
|
|
|
7
37
|
- Phase A6 setup/console/watch (#51): dry-run client and API-1 console registration with receipts, conditional undo and versioned roots; an explicit private study registry; read panels and event-timed inboxes; and eight decision-level console actions with preview/fingerprint confirmation, person attribution and stale-input refusal. Read-only console mode blocks writes. Saved literature watches run one finite, study-locked pass, retain ordinary scope/screen rules and never score rubrics or screen automatically; recurrence is person-managed agent-hub task proposals or user cron. Malformed watch versions are repairable; safe-integer future versions remain unchanged. CLI/MCP share watch and registry operations; MCP watch runs always return detached admission {started:true,configSha256} after locked config/scope/year preflight and finish in the same responsive MCP process. Outcomes arrive in watch.ran/watch show; every-source failure is recorded as ok:false. A second start while locked refuses. CLI watch run and watch.run plan steps remain synchronous (exit 1/failed node on all-source failure). Manifest lists studyRegistry/watchConfig v1 and watch ledger events. Tests use synthetic records/fake HTTP/runners and pinned console conformance, with no live deployment/amem/vault claim. No resident watcher is included.
|
package/README.md
CHANGED
|
@@ -2,16 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
Research engine for the agent family ([agent-hub](https://github.com/STAIxBWLB/agent-hub), [agent-mem](https://github.com/STAIxBWLB/agent-mem), [vault-mem](https://github.com/STAIxBWLB/vault-mem), [agent-console](https://github.com/STAIxBWLB/agent-console)). The plan and phases are in [#1](https://github.com/STAIxBWLB/agent-research/issues/1).
|
|
4
4
|
|
|
5
|
-
This checkout implements A1 literature studies, A2 container experiments and the A3 plan DAG: an append-only ledger, approval gates, verified reference identifiers, frozen candidate snapshots, separate evaluator containers, attempt records and a resumable controller with read-only hub task references. Investigation selection, idea decisions, winner/no-winner results, declared ablations, reserved-seed final evaluation and exploratory posthoc results are available. Paper check/build and build-bound review gates render evidence-backed Markdown. A5 adds amem lesson reads/archive and a reviewed skill proposal queue. A6 adds local client setup, registered-study console panels and confirmed decisions, and finite literature watch passes. Automatic idea generation/writing/reviewing remains later work.
|
|
5
|
+
This checkout implements A1 literature studies, A2 container experiments and the A3 plan DAG: an append-only ledger, approval gates, verified reference identifiers, frozen candidate snapshots, separate evaluator containers, attempt records and a resumable controller with read-only hub task references. Investigation selection, idea decisions, winner/no-winner results, declared ablations, reserved-seed final evaluation and exploratory posthoc results are available. Paper check/build and build-bound review gates render evidence-backed Markdown. A5 adds amem lesson reads/archive and a reviewed skill proposal queue. A6 adds local client setup, registered-study console panels and confirmed decisions, and finite literature watch passes. Per-phase autonomy (`auto`, `gates`, `copilot`, `step`) sets how far each phase runs before a recorded approval, and `study export` writes a content-free dataset bundle. Automatic idea generation/writing/reviewing remains later work.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
<!-- facts:install -->
|
|
10
|
+
Requires Bun 1.4.2 or newer. Install from npm:
|
|
10
11
|
|
|
11
12
|
```sh
|
|
12
13
|
bun add -g @staix/agent-research
|
|
13
14
|
ares --help
|
|
14
15
|
```
|
|
16
|
+
<!-- /facts:install -->
|
|
17
|
+
|
|
18
|
+
0.1.0 was the first npm release. v0.2.0 was tagged but never published because its release smoke failed; 0.2.1 carries the fix without moving that tag.
|
|
15
19
|
|
|
16
20
|
Or run from a checkout:
|
|
17
21
|
|
|
@@ -320,7 +324,7 @@ A no-argument `paper.build` conductor step emits `{sha256}` of the committed evi
|
|
|
320
324
|
|
|
321
325
|
## Memory and skill proposal workflow
|
|
322
326
|
|
|
323
|
-
|
|
327
|
+
Lessons and archive call the `amem` CLI on PATH (`search --json --explain`, `brief --json`, `note add - --json`). Its output parser was written against amem 0.20.3; the tests use a fake runner, so no amem version is tested live here. Start each phase with an intent-specific lesson read, then archive only at the end of the study:
|
|
324
328
|
|
|
325
329
|
```sh
|
|
326
330
|
ares lessons study --for "compare candidate hypotheses" --half-life 180 --limit 50 --json
|
|
@@ -417,11 +421,31 @@ The planner drafts that campaign and a person approves/activates it in agent-hub
|
|
|
417
421
|
|
|
418
422
|
A ready hub node records its unit's child task id and waits for that task's approval. Pending campaign approval or activation waits without a manual retry. An initial read outage may leave the dispatch unbound until its first successful read; the task is then pinned for that plan revision, including across restarts and retries. Missing units/tasks, cancelled tasks and a different binding fail with the reason. A new plan revision can bind the unit's new task. Hub waits use the controller backoff, do not consume step slots, and do not redispatch agent work. Their completed output is an id/hash reference, so a downstream plan gate can bind to it.
|
|
419
423
|
|
|
424
|
+
## Study export
|
|
425
|
+
|
|
426
|
+
```sh
|
|
427
|
+
ares study export study --bundle /absolute/path/to/new-bundle --list --json
|
|
428
|
+
ares study export study --bundle /absolute/path/to/new-bundle --json
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
`study export` writes a dataset bundle from committed study files only; it never reads the executor workdir or logs. The target must be a new or empty directory outside the study (symlinks are resolved first); `--list` names the six files and writes nothing. Reads take the study lock once; files are written after it is released.
|
|
432
|
+
|
|
433
|
+
| File | Content |
|
|
434
|
+
| --- | --- |
|
|
435
|
+
| `manifest.json` | `bundle: 1`, format versions, hashed study id, protocol hash, seal binding, ledger time window, counts by status and run, and each file's sha256 |
|
|
436
|
+
| `ledger.jsonl` | event envelopes with hashed actor ids; `data` keeps only per-event-type allowlisted closed fields |
|
|
437
|
+
| `attempts.jsonl` | one row per attempt: identity hashes, seed, `labelSha256`, status, stage, reason class, per-stage exit code, duration, network, limits and image digest, metrics with provenance, output hashes and sealing booleans |
|
|
438
|
+
| `results.json` | receipt-verified closed investigate, ablate and final results reduced to numbers, booleans, hashes, closed tokens and metric identifiers |
|
|
439
|
+
| `reviews.jsonl` | reviewer model family, build hash, finding kinds and counts, blocking count and resolutions |
|
|
440
|
+
| `evidence.json` | placeholder ref hashes, families, attempt bindings and source hashes |
|
|
441
|
+
|
|
442
|
+
Paths, mounts, container ids, argv, env, image names (digests are kept), free text and malformed identity fields are dropped. Metric names/units and the selection metric stay because the dataset needs them to read values. Every key and string value is then scanned; an absolute POSIX/Windows/UNC path, URL, `NAME=value` assignment or key-like token refuses the whole export, and nothing is written. Each file is bound-checked in memory first.
|
|
443
|
+
|
|
420
444
|
## What sealed means
|
|
421
445
|
|
|
422
446
|
The `design` gate binds the exact protocol bytes and the sorted `task/` file tree hashes, plus the raw selection file hash when present. Editing any sealed input reopens the gate. A budget-only change also reopens it, while the comparable attempt protocol hash excludes budget. The executor configuration is outside the seal; the attempt records the executor it used.
|
|
423
447
|
|
|
424
|
-
Sealing and metrics are **ares-observed**: ares builds the argv and checks the observed container configuration. They are never **host-observed** or **runner-attested**.
|
|
448
|
+
Sealing and metrics are **ares-observed**: ares builds the argv and checks the observed container configuration. They are never **host-observed** or **runner-attested**. agent-hub 0.26.0 added signed receipts from a registered external runner for hub research attempts ([agent-hub#1018](https://github.com/STAIxBWLB/agent-hub/issues/1018)), so far covered by source and test-key fixtures only. Ares does not read or bind those receipts; that integration and a live registered runner are still needed before an ares attempt can be runner-attested. This seal neither attests to an untrusted host nor establishes support for a research claim.
|
|
425
449
|
|
|
426
450
|
## What the checks mean
|
|
427
451
|
|
|
@@ -434,6 +458,63 @@ Sealing and metrics are **ares-observed**: ares builds the argv and checks the o
|
|
|
434
458
|
|
|
435
459
|
`scope` binds to the content of `scope.json`; `screen` binds to the set of included papers; `design` binds the experiment protocol and task tree, plus selection/final-seeds files when present; `final` binds closed upstream results and design; `review` binds the current rendered/evidence hashes and current-build review/resolution event hashes; `plan:<node-id>` binds a plan gate to all upstream observed output references. Changing bound content returns its gate to pending. With `--autonomy auto` a pending gate is approved as `auto` when a command needs it; with `gates` (default) someone must run `ares gate approve`. The ledger records who approved: a person, an agent (detected from the agent environment) or `auto`. Which of them may approve is the workspace's policy, not the tool's. For experiments, automatic design and final approval is committed with a verified candidate start; a failed preparation records no approval. The review gate is approved explicitly after its readiness conditions pass; no current command auto-requires it.
|
|
436
460
|
|
|
461
|
+
### Autonomy policy
|
|
462
|
+
|
|
463
|
+
`ares autonomy show <dir> --json` reads the stored policy and effective mode for every phase. `ares autonomy set <dir> <auto|gates|copilot|step> [--phase PHASE]` changes the default or one override in a single study/ledger commit. The event records the actor, the complete `from` and `to` policies, and `phase` (null for a default change). A default change retains existing overrides. Earlier gate approvals and rejections are kept; policy changes do not re-decide them.
|
|
464
|
+
|
|
465
|
+
```sh
|
|
466
|
+
ares autonomy set study gates
|
|
467
|
+
ares autonomy set study auto --phase literature
|
|
468
|
+
ares autonomy show study --json
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
Phases are `scope`, `literature`, `hypotheses`, `design`, `investigate`, `ablate`, `final`, `posthoc`, `write`, `review` and `archive`. Only `auto` approves pending gates automatically; `gates`, `copilot` and `step` require recorded approval. Step execution and copilot draft acceptance are described below. Approval authority remains workspace policy, with no person-only restriction.
|
|
472
|
+
|
|
473
|
+
| Gate | Phase |
|
|
474
|
+
| --- | --- |
|
|
475
|
+
| `scope` | `scope` |
|
|
476
|
+
| `screen` | `literature` |
|
|
477
|
+
| `design` | `design` |
|
|
478
|
+
| `final` | `final` |
|
|
479
|
+
| `review` | `review` |
|
|
480
|
+
| `accept:hypotheses` | `hypotheses` |
|
|
481
|
+
| `accept:paper` | `write` |
|
|
482
|
+
| `accept:reviews` | `review` |
|
|
483
|
+
| `plan:<id>` | The declared phase shared by every guarded immediate downstream node; otherwise the study default |
|
|
484
|
+
|
|
485
|
+
Plan nodes may declare `phase` from the same list. Dependencies through `needs` and explicit edges both identify guarded downstream nodes. Mixed phases, any undeclared target, no targets or a hub target use the study default; a gate's own `phase` is not a substitute, and command/run names are not inferred. Phase edits participate in node staleness; changing policy does not invalidate already-approved gates. The controller reloads policy inside each approval transaction.
|
|
486
|
+
|
|
487
|
+
With an effective `step` policy, the CLI controller keeps step work exclusive even with `--parallel` greater than 1. For effect nodes (step and hub), every terminal outcome (`done`, `failed`, `cancelled`, `uncertain`, including reconciliation) and its `plan.paused` receipt (`reason: step`) are committed together when work remains. Gate approvals do not consume a step. When no work remains, the plan finishes `done` or `failed` without a pause or acknowledgement resume; a failed terminal plan makes `ares run` exit nonzero. `ares plan show` exposes `pauseReason: step`; that pause survives controller restart, and unchanged observation polls do not append receipts. Detached attempt admission is not completion: the pause follows the observed terminal result. Gates in a step phase still require approval, with no automatic grant.
|
|
488
|
+
|
|
489
|
+
Use `ares plan control <dir> resume --command-id <new-id> --expected-revision <revision>` to continue. A resume through CLI or MCP changes the same durable plan state; MCP does not start a controller. The controller must already be running via `ares run` to admit work. Mode and phase are read again inside admission and completion transactions, so pending work follows the current recorded policy. Manual-only pending gate polls do not take a study lock.
|
|
490
|
+
|
|
491
|
+
Legacy `auto|gates` string studies retain study v1 and their existing JSON layout. Object policies (`{default, phases}`), `copilot` and `step` require study v2. Once a study is v2, later policy changes never downgrade it. This reader supports v1 and v2; the published 0.1.0 reader rejects v2 with its unsupported-version guidance and leaves the file untouched. Plan `phase` is an optional v1 field: phase-free plans keep their previous shape, while the older strict 0.1.0 plan reader rejects a declared phase without changing the file.
|
|
492
|
+
|
|
493
|
+
### Copilot draft acceptance
|
|
494
|
+
|
|
495
|
+
A copilot phase produces drafts until an ordinary `accept:<artifact>` gate approves their current content hash. There are three aggregate artifacts; the guard is enabled by the **producing** phase's mode, not the consuming phase. `auto`, `gates` and `step` do not enable these guards. New studies still default to `gates`, with no implicit copilot override or automatic drafting.
|
|
496
|
+
|
|
497
|
+
| Artifact gate and phase | Producer and content | Guarded consumers |
|
|
498
|
+
| --- | --- | --- |
|
|
499
|
+
| `accept:hypotheses`, `hypotheses` | Optional `hypotheses.md` plus the complete `idea.added`/`idea.decided` journal, produced by source edits and `idea add`/`idea decide` | `protocol`, attempt admission (all runs and plan preparation), `investigate close`, the closed-investigation reader used by ablate/final trusted-source paths, `paper build`, archive preview/export |
|
|
500
|
+
| `accept:paper`, `write` | Manuscript source files under `paper/`, including notes/assets; `paper/build/` is derived and excluded | `review add`, `review resolve`, review readiness/approval, archive preview/export |
|
|
501
|
+
| `accept:reviews`, `review` | Complete `review.added`/`review.resolved` journal across all builds, produced by `review add`/`review resolve` | Review readiness/approval, archive preview/export |
|
|
502
|
+
|
|
503
|
+
Source edits or new relevant journal records make the prior accept stale (the gate becomes pending for its new hash). Gate decisions and unrelated ledger entries are excluded from artifact hashes, so approval never invalidates itself. Rebuilding or repairing `paper/build/` does not stale `accept:paper`; existing fresh-build, citation, number and review-readiness checks still apply. Acceptance is a workflow checkpoint, not scientific verification or a way to clear blocking findings.
|
|
504
|
+
|
|
505
|
+
```sh
|
|
506
|
+
ares autonomy set study copilot --phase write
|
|
507
|
+
# Author or edit paper/manuscript.md and any source assets.
|
|
508
|
+
ares paper check study
|
|
509
|
+
ares paper build study
|
|
510
|
+
ares gate list study
|
|
511
|
+
ares gate approve study accept:paper
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
In-phase editing and own-draft diagnostics remain usable before acceptance: idea edits/list, paper check/build and review edits/show do not require accepting the artifact they produce. A build still consumes accepted hypotheses when that producing phase is copilot; review edits consume accepted paper source. Diagnostics that cannot use an unaccepted trusted source report the required gate and approval command. Plan adapters preserve the same refusal guidance and do not prepare an attempt backend before hypotheses acceptance.
|
|
515
|
+
|
|
516
|
+
Approvals use the existing CLI/MCP gate handler, record the actor and bind the current hash. No agent/person exemption or person-only restriction is added, and accepts are never implicit auto approvals. Source reads are bounded: hypotheses Markdown at most 2 MiB; paper source at most 500 regular files, 64 MiB total, 1000 directories and 64 levels. Source links and special files are refused. Existing study-v2 copilot policy and version-1 gate/ledger records carry the feature; no new draft store or interchange format is introduced.
|
|
517
|
+
|
|
437
518
|
## Study files
|
|
438
519
|
|
|
439
520
|
| File | Content |
|
|
@@ -467,7 +548,10 @@ Experiment logs and outputs live on the executor at `<workdir>/<study-id>/<attem
|
|
|
467
548
|
|
|
468
549
|
The implemented CLI surface below comes from `src/commands-table.ts`; `ares --help` prints current usage. Every operation exposing `--json` supports structured output.
|
|
469
550
|
|
|
551
|
+
<!-- facts:commands -->
|
|
470
552
|
```text
|
|
553
|
+
ares autonomy show <dir> [--json]
|
|
554
|
+
ares autonomy set <dir> <auto|gates|copilot|step> [--phase PHASE] [--json]
|
|
471
555
|
ares skill propose <dir> --file PATH|- [--json]
|
|
472
556
|
ares skill decide <dir> <name> <accept|reject|withdraw> --reason TEXT [--pr URL] [--json]
|
|
473
557
|
ares skill list <dir> [--json]
|
|
@@ -481,12 +565,13 @@ ares console add <dir> [--json]
|
|
|
481
565
|
ares console remove <dir> [--json]
|
|
482
566
|
ares console list [--json]
|
|
483
567
|
ares manifest [--json]
|
|
484
|
-
ares init <dir> --question TEXT [--mode survey|experiment] [--autonomy auto|gates] [--json]
|
|
568
|
+
ares init <dir> --question TEXT [--mode survey|experiment] [--autonomy auto|gates|copilot|step] [--json]
|
|
485
569
|
ares run <dir> [--parallel 1..8] [--json]
|
|
486
570
|
ares plan set <dir> --file PATH|- [--json]
|
|
487
571
|
ares plan control <dir> <pause|resume|retry|cancel|skip> [node] --command-id ID --expected-revision N [--json]
|
|
488
572
|
ares plan show <dir> [--json]
|
|
489
573
|
ares status <dir> [--json]
|
|
574
|
+
ares study export <dir> --bundle DIR [--list] [--json]
|
|
490
575
|
ares scope <dir> --file PATH|- [--json]
|
|
491
576
|
ares idea add <dir> --file PATH|- [--json]
|
|
492
577
|
ares idea decide <dir> <id> <refine|pivot> --reason TEXT [--attempts ID[,ID...]] [--commit SHA] [--cause TEXT] [--retry-when TEXT] [--json]
|
|
@@ -503,8 +588,8 @@ ares protocol <dir> --file PATH|- [--json]
|
|
|
503
588
|
ares executor set <dir> --kind local|ssh [--host ALIAS] --workdir PATH [--json]
|
|
504
589
|
ares executor check <dir> [--json]
|
|
505
590
|
ares gate list <dir> [--json]
|
|
506
|
-
ares gate approve <dir> <scope|screen|design|final|review|plan:node-id> [--reason TEXT] [--json]
|
|
507
|
-
ares gate reject <dir> <scope|screen|design|final|review|plan:node-id> --reason TEXT [--json]
|
|
591
|
+
ares gate approve <dir> <scope|screen|design|final|review|plan:node-id|accept:artifact> [--reason TEXT] [--json]
|
|
592
|
+
ares gate reject <dir> <scope|screen|design|final|review|plan:node-id|accept:artifact> --reason TEXT [--json]
|
|
508
593
|
ares attempt run <dir> --repo PATH --commit SHA [--seed N] [--run NAME] [--label TEXT] [--retry ID] [--detach] [--json]
|
|
509
594
|
ares attempt list <dir> [--run NAME] [--status running|succeeded|failed|cancelled|unknown] [--limit N] [--offset N] [--json]
|
|
510
595
|
ares attempt show <dir> <id> [--json]
|
|
@@ -526,16 +611,21 @@ ares cite check <dir> <draft> [--json]
|
|
|
526
611
|
ares playbook
|
|
527
612
|
ares mcp
|
|
528
613
|
```
|
|
614
|
+
<!-- /facts:commands -->
|
|
615
|
+
|
|
616
|
+
<!-- facts:mcp-tools -->
|
|
617
|
+
The MCP server publishes 55 tools: `ares_autonomy_show`, `ares_autonomy_set`, `ares_watch_set`, `ares_watch_run`, `ares_watch_show`, `ares_console_add`, `ares_console_remove`, `ares_console_list`, `ares_setup`, `ares_manifest`, `ares_archive`, `ares_lessons`, `ares_skill_propose`, `ares_skill_decide`, `ares_skill_list`, `ares_plan_set`, `ares_plan_control`, `ares_plan_show`, `ares_status`, `ares_study_export`, `ares_scope_set`, `ares_gate`, `ares_idea_add`, `ares_idea_decide`, `ares_investigate_show`, `ares_investigate_close`, `ares_ablate_add`, `ares_ablate_show`, `ares_ablate_close`, `ares_posthoc_show`, `ares_final_close`, `ares_final_seeds`, `ares_selection_set`, `ares_protocol_set`, `ares_executor_set`, `ares_executor_check`, `ares_attempt_run`, `ares_attempt_list`, `ares_attempt_show`, `ares_attempt_cancel`, `ares_attempt_reconcile`, `ares_attempt_logs`, `ares_lit_search`, `ares_lit_list`, `ares_lit_screen`, `ares_lit_card`, `ares_lit_verify`, `ares_lit_bib`, `ares_review_add`, `ares_review_resolve`, `ares_review_show`, `ares_paper_build`, `ares_paper_check`, `ares_cite_check`, `ares_playbook`.
|
|
618
|
+
<!-- /facts:mcp-tools -->
|
|
529
619
|
|
|
530
620
|
Memory tools are `ares_archive`, `ares_lessons`, `ares_skill_propose`, `ares_skill_decide` and `ares_skill_list`; `ares_idea_decide` accepts pivot cause/retryWhen. Archive may write external amem notes; lessons reads external amem. Both carry `openWorldHint`; skill operations stay local. MCP calls preserve agent attribution even without a native shell marker.
|
|
531
621
|
|
|
532
622
|
Watch tools are `ares_watch_set` (`{study, watch}`), `ares_watch_run` and `ares_watch_show` (`{study}`). `ares_watch_run` always returns the detached admission result `{started:true,configSha256}` after config/scope/year preflight under the study lock. Read the eventual completed result through `ares_watch_show`; `watch.ran` records an all-source failure as `ok:false`. The finite pass stays in the MCP process, which can still answer ping and `tools/list`; another start while locked refuses. CLI `watch run` and the `watch.run` plan step remain synchronous. Registry tools are `ares_console_add` and `ares_console_remove` (`{study}`), and `ares_console_list` (no arguments). These use the same shared operations as the CLI. Registry commands manage local registration only; they do not start a console.
|
|
533
623
|
|
|
534
|
-
MCP uses shared command handlers; `ares_setup` exposes the same registration preview/apply/undo operations. `init`, the controller loop `run`, and the server entrypoint `mcp` are CLI-only. Investigation tools are `ares_selection_set`, `ares_idea_add`, `ares_idea_decide`, `ares_investigate_show` and `ares_investigate_close`. Plan tools are `ares_plan_set`, `ares_plan_show` and `ares_plan_control`; `ares_gate` accepts `plan:<node-id>`. Setting, showing or controlling a plan never starts the controller loop. Start `ares run` in a separate terminal before resuming through MCP. Experiment tools are `ares_protocol_set`, `ares_executor_set`, `ares_executor_check`, `ares_attempt_run`, `ares_attempt_list`, `ares_attempt_show`, `ares_attempt_cancel`, `ares_attempt_reconcile` and `ares_attempt_logs`; `ares_gate` accepts `design`, `final` and `review`. Paper/review tools are `ares_paper_check`, `ares_paper_build`, `ares_review_add`, `ares_review_resolve` and `ares_review_show`. Phase tools include `ares_final_seeds`, `ares_ablate_add`, `ares_ablate_show`, `ares_ablate_close`, `ares_final_close` and `ares_posthoc_show`. Attempt run is always detached over MCP, and executor-reaching tools carry `openWorldHint`.
|
|
624
|
+
MCP uses shared command handlers; `ares_setup` exposes the same registration preview/apply/undo operations. `init`, the controller loop `run`, and the server entrypoint `mcp` are CLI-only. Investigation tools are `ares_selection_set`, `ares_idea_add`, `ares_idea_decide`, `ares_investigate_show` and `ares_investigate_close`. Plan tools are `ares_plan_set`, `ares_plan_show` and `ares_plan_control`; `ares_gate` accepts `plan:<node-id>`. Setting, showing or controlling a plan never starts the controller loop. Start `ares run` in a separate terminal before resuming through MCP. Autonomy tools are `ares_autonomy_show` and `ares_autonomy_set`; `ares_gate` also accepts `accept:<artifact>`. `ares_study_export` writes the same bundle as `study export` and needs an absolute `bundle`. Experiment tools are `ares_protocol_set`, `ares_executor_set`, `ares_executor_check`, `ares_attempt_run`, `ares_attempt_list`, `ares_attempt_show`, `ares_attempt_cancel`, `ares_attempt_reconcile` and `ares_attempt_logs`; `ares_gate` accepts `design`, `final` and `review`. Paper/review tools are `ares_paper_check`, `ares_paper_build`, `ares_review_add`, `ares_review_resolve` and `ares_review_show`. Phase tools include `ares_final_seeds`, `ares_ablate_add`, `ares_ablate_show`, `ares_ablate_close`, `ares_final_close` and `ares_posthoc_show`. Attempt run is always detached over MCP, and executor-reaching tools carry `openWorldHint`.
|
|
535
625
|
|
|
536
626
|
## Version and format discovery
|
|
537
627
|
|
|
538
|
-
`ares manifest --json` (MCP `ares_manifest`, no arguments) reports the running package version, implemented command names/usages and the schema versions of family-readable records. It needs no study, network or executor. Current versions are `manifest`, `
|
|
628
|
+
`ares manifest --json` (MCP `ares_manifest`, no arguments) reports the running package version, implemented command names/usages and the schema versions of family-readable records. It needs no study, network or executor. Current versions are `manifest`, `ledgerEvent`, `experimentProtocol`, `executor`, `experimentAttempt`, `studyPlan`, `experimentSelection`, `investigateResult`, `experimentFinalSeeds`, `ablateResult`, `finalResult` and `paperEvidence`, all version 1, carried by each record's `v` field. `study: 2` is the latest supported study format; legacy v1 is also supported. `skillProposal: 1` is also listed; proposal Markdown carries `skillProposal: 1` frontmatter and skill events carry that version in their data. The `ledgerEvents` list advertises `archive.exported`, `skill.proposed`, `skill.decided`, `watch.set`, `watch.ran` and `autonomy.set` in the version-1 ledger envelope. The manifest also lists `studyRegistry: 1`, `watchConfig: 1` and `studyBundle: 1`; a `study export` bundle manifest carries its version as `bundle: 1` rather than `v`. Unsupported ledger/proposal/registry/watch versions are refused without rewriting their bytes. `mcp.tools` publishes `{name, readOnly}` for installers; grants are fail-closed for mutating or outside-reaching tools.
|
|
539
629
|
|
|
540
630
|
Within a supported schema, readers preserve additive fields on study/attempt records and keep ledger events with unknown kinds. Appending to the ledger leaves prior lines intact; updating an attempt keeps unrecognized fields and stage entries. Unknown stage entries remain readable, including logs and totals, but budget-gated starts refuse with an upgrade instruction because this version cannot account for their resource use. A future schema version or unknown execution status/stage is refused with an upgrade instruction, leaving the original data unchanged. Unknown plan versions or node kinds are refused without changing plan.json. Command input remains strict so unknown options or protocol fields cannot silently change an experiment.
|
|
541
631
|
|
|
@@ -553,21 +643,25 @@ Keys are sent with requests only; they are never written to the study.
|
|
|
553
643
|
|
|
554
644
|
## Not implemented yet
|
|
555
645
|
|
|
556
|
-
Automatic idea generation, parallel attempts, held-out evaluator data, significance tests,
|
|
646
|
+
Automatic idea generation, parallel attempts, held-out evaluator data, significance tests, binding agent-hub runner receipts (agent-hub#1018) to ares attempts, automatic manuscript writing/reviewing, LaTeX/PDF builds and venue templates, claim-passage evidence pending agent-hub#931, exporting verified references as vault-mem reference notes (vault-mem 0.5.0 accepts reference metadata since vault-mem#73; the ares side is not built).
|
|
557
647
|
|
|
558
648
|
## Release
|
|
559
649
|
|
|
560
|
-
|
|
650
|
+
Prepare a release on a clean release branch with `bun run release:prepare <version>`. This bumps `package.json` and moves the Unreleased notes into a dated CHANGELOG section. Review and merge that bump through a PR, then fast-forward local `main` to `origin/main`. On clean, synchronized `main`, the owner runs `bun run release:tag`. It verifies the version, dated notes and successful `Check` / `ci-ok` result for that exact main commit, refuses an existing local or remote tag, and creates and pushes an annotated `v<version>` tag. Never hand-create or move a release tag or reuse a published version.
|
|
651
|
+
|
|
652
|
+
Documentation stamps must be fresh before tagging. `docs/verified.json` records, for `README.md` and `src/playbook.ts` (the `ares playbook` text), the commit their prose was last checked against and the source paths it describes; edits to the stamped documents themselves are not counted as source drift. `bun run check` warns about a stale document; `bun run release:tag` and the tag workflow run `bun scripts/check-docs.mjs --require-fresh` and refuse. To restamp in the release PR, reread each stale document against the release PR's base commit on `origin/main`, fix the prose, and set its `verifiedAgainst` to that base commit (it survives the squash merge; never stamp a branch commit). Mechanical README facts (install line, command list, MCP tools) are generated: run `bun scripts/readme-facts.ts --write` after changing `package.json`, `src/commands-table.ts` or the MCP tool table.
|
|
653
|
+
|
|
654
|
+
The tag workflow first waits up to 30 minutes for the exact commit's main-push `Check` workflow and `ci-ok` aggregate to succeed. A failed, skipped or cancelled result refuses release. It checks fresh documentation stamps, the matching package version, dated CHANGELOG and main ancestry before staging. It reuses CI rather than rerunning the full suite, then installs dependencies, stages a hash-bound tarball and runs clean-prefix CLI, manifest and MCP smoke checks on Ubuntu and macOS. Publication uses the exact validated Linux tarball with provenance. The GitHub release follows with the dated notes, tarball and hash manifest; reruns edit the existing release and replace assets, with three bounded attempts for GitHub 429/5xx errors. When the `SITE_DISPATCH_TOKEN` secret is set, the workflow then sends a `product-release` dispatch to STAIxBWLB/agent-hub-site so the family portal re-syncs; a dispatch failure does not fail the release. npm publication remains one-time; an already published version cannot be republished.
|
|
561
655
|
|
|
562
|
-
Publication runs only when
|
|
656
|
+
Publication runs only when `NPM_PUBLISH_ENABLED` is `true` and a reviewer approves `npm-production`. It uses Node 24 and npm 11.5.1 or newer with [npm OIDC trusted publishing](https://docs.npmjs.com/trusted-publishers), without an npm token. The owner manages trusted-publisher settings, environment approval and branch protection requiring `ci-ok`; the scripts do not change those settings.
|
|
563
657
|
|
|
564
|
-
|
|
658
|
+
N-1 compatibility is stated per minor release in CHANGELOG.md, separately for CLI, MCP tools and study/ledger formats. For 0.2.0, N-1 is 0.1.0: every 0.1.0 CLI command and usage and every 0.1.0 MCP tool with its `readOnly` value remain, and this version reads 0.1.0 studies and ledgers without rewriting them. 0.1.0 refuses records only newer features write: study v2 (object, `copilot` or `step` autonomy policies) and plans with a node `phase`, each without changing the file. The `n1` CI job (`bun scripts/n1-check.ts`), required by `ci-ok`, checks these claims on every build against the latest published patch of the minor line directly below the checkout's version (0.1.x for every 0.2 release). On the initial publication line it prints a skip.
|
|
565
659
|
|
|
566
660
|
## Development
|
|
567
661
|
|
|
568
662
|
```sh
|
|
569
663
|
bun install --frozen-lockfile
|
|
570
|
-
bun run check # typecheck, boundary check, tests (no network), package dry-run
|
|
664
|
+
bun run check # typecheck, boundary check, README facts, doc stamps, tests (no network), package dry-run
|
|
571
665
|
```
|
|
572
666
|
|
|
573
667
|
Live executor acceptance is separate from the offline gate. From a checkout with the configured SSH executor, run `bun scripts/live-exp.ts --host dgx-h100-2`. It uses a CPU-only synthetic Git repository, checks commit-specific scores, evaluator isolation, oversized logs, read-only log retrieval and archive containment, and prints a bounded summary. It removes its labeled containers and leaves private artifacts for inspection. The recorded A2 live proof is in [PR #14](https://github.com/STAIxBWLB/agent-research/pull/14); it covers that dgx Docker configuration, not every host or the local backend.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@staix/agent-research",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Research engine for the agent family: literature with verified references, study ledger and gates (ares)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -30,7 +30,9 @@
|
|
|
30
30
|
"LICENSE"
|
|
31
31
|
],
|
|
32
32
|
"scripts": {
|
|
33
|
-
"check": "bun x tsc --noEmit && bun scripts/check-boundary.ts && bun test && bun pm pack --dry-run",
|
|
33
|
+
"check": "bun x tsc --noEmit && bun scripts/check-boundary.ts && bun scripts/readme-facts.ts && bun scripts/check-docs.mjs && bun test && bun pm pack --dry-run",
|
|
34
|
+
"release:prepare": "bun scripts/release-tag.ts prepare",
|
|
35
|
+
"release:tag": "bun scripts/check-docs.mjs --require-fresh && bun scripts/release-tag.ts tag",
|
|
34
36
|
"release:stage": "bun scripts/release.ts stage",
|
|
35
37
|
"release:smoke": "bun scripts/release-smoke.ts"
|
|
36
38
|
}
|
package/src/autonomy.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const AUTONOMY_MODES = ["auto", "gates", "copilot", "step"] as const;
|
|
2
|
+
export const PHASES = ["scope", "literature", "hypotheses", "design", "investigate", "ablate", "final", "posthoc", "write", "review", "archive"] as const;
|
|
3
|
+
export type AutonomyMode = typeof AUTONOMY_MODES[number];
|
|
4
|
+
export type Phase = typeof PHASES[number];
|
|
5
|
+
export const ACCEPT_ARTIFACTS = ["hypotheses", "paper", "reviews"] as const;
|
|
6
|
+
export type AcceptArtifact = typeof ACCEPT_ARTIFACTS[number];
|
|
7
|
+
export type Autonomy = AutonomyMode | { default: AutonomyMode; phases: Partial<Record<Phase, AutonomyMode>> };
|
|
8
|
+
|
|
9
|
+
/** Direct gate mappings are explicit; plan gates receive their declared guarded phase. */
|
|
10
|
+
export const GATE_PHASES = { scope: "scope", screen: "literature", design: "design", final: "final", review: "review", "accept:hypotheses": "hypotheses", "accept:paper": "write", "accept:reviews": "review" } as const satisfies Record<string, Phase>;
|
|
11
|
+
|
|
12
|
+
function refuse(field: string, reason: string): never {
|
|
13
|
+
throw new Error(`${field}: ${reason}; correct the policy and retry ares autonomy set with a supported mode and phase`);
|
|
14
|
+
}
|
|
15
|
+
function object(raw: unknown): raw is Record<string, unknown> {
|
|
16
|
+
return typeof raw === "object" && raw !== null && !Array.isArray(raw) && (Object.getPrototypeOf(raw) === Object.prototype || Object.getPrototypeOf(raw) === null);
|
|
17
|
+
}
|
|
18
|
+
export function validateAutonomyMode(raw: unknown): AutonomyMode {
|
|
19
|
+
if (typeof raw !== "string" || !AUTONOMY_MODES.includes(raw as AutonomyMode)) refuse("autonomy.mode", "expected auto, gates, copilot or step");
|
|
20
|
+
return raw as AutonomyMode;
|
|
21
|
+
}
|
|
22
|
+
export function validatePhase(raw: unknown): Phase {
|
|
23
|
+
if (typeof raw !== "string" || !PHASES.includes(raw as Phase)) refuse("autonomy.phase", `expected one of ${PHASES.join(", ")}`);
|
|
24
|
+
return raw as Phase;
|
|
25
|
+
}
|
|
26
|
+
/** Validate strictly and return a detached policy, leaving the input unchanged. */
|
|
27
|
+
export function validateAutonomy(raw: unknown): Autonomy {
|
|
28
|
+
if (typeof raw === "string") return validateAutonomyMode(raw);
|
|
29
|
+
if (!object(raw)) refuse("autonomy", "mode string or policy object required");
|
|
30
|
+
for (const key of Reflect.ownKeys(raw)) if (key !== "default" && key !== "phases") refuse("autonomy", "unknown policy field");
|
|
31
|
+
const mode = validateAutonomyMode(raw.default);
|
|
32
|
+
if (!object(raw.phases)) refuse("autonomy.phases", "phase-to-mode object required");
|
|
33
|
+
const phases: Partial<Record<Phase, AutonomyMode>> = {};
|
|
34
|
+
for (const key of Reflect.ownKeys(raw.phases)) {
|
|
35
|
+
const phase = validatePhase(key);
|
|
36
|
+
phases[phase] = validateAutonomyMode(raw.phases[phase]);
|
|
37
|
+
}
|
|
38
|
+
return { default: mode, phases };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function resolvePhaseAutonomy(policy: Autonomy, phase?: Phase): AutonomyMode {
|
|
42
|
+
if (typeof policy === "string") return policy;
|
|
43
|
+
return phase === undefined ? policy.default : policy.phases[phase] ?? policy.default;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Unknown gate kinds and phase-ambiguous plan gates use the study default. */
|
|
47
|
+
export function resolveAutonomy(policy: Autonomy, gate: string, guardedPhase?: Phase): AutonomyMode {
|
|
48
|
+
const phase = gate.startsWith("plan:") ? guardedPhase : Object.hasOwn(GATE_PHASES, gate) ? GATE_PHASES[gate as keyof typeof GATE_PHASES] : undefined;
|
|
49
|
+
return resolvePhaseAutonomy(policy, phase);
|
|
50
|
+
}
|
package/src/cli.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { findCommand, help, type CommandSpec } from "./commands-table.ts";
|
|
|
3
3
|
import * as ops from "./commands.ts";
|
|
4
4
|
import { createHttp, type Http } from "./http.ts";
|
|
5
5
|
import { PLAYBOOK } from "./playbook.ts";
|
|
6
|
-
import { detectActor, readTextBounded } from "./study.ts";
|
|
6
|
+
import { detectActor, readTextBounded, releaseStudyLocksForExit } from "./study.ts";
|
|
7
7
|
|
|
8
8
|
const INPUT_BYTES = 65_536;
|
|
9
9
|
export interface Io extends ops.ExperimentRuntime { readStdin?: () => Promise<string>; http?: Http; signal?: AbortSignal }
|
|
@@ -97,11 +97,14 @@ export async function run(args: string[], env: NodeJS.ProcessEnv = process.env,
|
|
|
97
97
|
}
|
|
98
98
|
case "run": {
|
|
99
99
|
count(spec, positional, 1); const parallel = integer(flags["--parallel"], "--parallel");
|
|
100
|
-
|
|
100
|
+
const completed = await ops.planRun(positional[0]!, { ...(parallel !== undefined ? { parallel } : {}) }, ctx);
|
|
101
|
+
result = completed; if (completed.state === "failed") code = 1; break;
|
|
101
102
|
}
|
|
102
103
|
case "manifest": count(spec, positional, 0); result = ops.manifest(); break;
|
|
103
104
|
case "playbook": count(spec, positional, 0); return { text: PLAYBOOK.trimEnd(), code: 0 };
|
|
104
105
|
case "mcp": throw new Error("mcp: run `ares mcp` with no other arguments");
|
|
106
|
+
case "autonomy show": count(spec, positional, 1); result = ops.autonomyShow(positional[0]!); break;
|
|
107
|
+
case "autonomy set": count(spec, positional, 2); result = await ops.autonomySet(positional[0]!, positional[1]!, str("--phase"), ctx); break;
|
|
105
108
|
case "init": {
|
|
106
109
|
count(spec, positional, 1);
|
|
107
110
|
const question = str("--question");
|
|
@@ -123,6 +126,11 @@ export async function run(args: string[], env: NodeJS.ProcessEnv = process.env,
|
|
|
123
126
|
}
|
|
124
127
|
case "plan show": count(spec, positional, 1); result = ops.planShow(positional[0]!); break;
|
|
125
128
|
case "status": count(spec, positional, 1); result = ops.status(positional[0]!); break;
|
|
129
|
+
case "study export": {
|
|
130
|
+
count(spec, positional, 1); const bundle = str("--bundle");
|
|
131
|
+
if (bundle === undefined) throw new Error("study export: --bundle DIR is required; pass a new or empty output directory");
|
|
132
|
+
result = await ops.studyExport(positional[0]!, { bundle, ...(flags["--list"] ? { list: true } : {}) }); break;
|
|
133
|
+
}
|
|
126
134
|
case "scope": {
|
|
127
135
|
count(spec, positional, 1);
|
|
128
136
|
const file = str("--file");
|
|
@@ -260,11 +268,16 @@ export async function run(args: string[], env: NodeJS.ProcessEnv = process.env,
|
|
|
260
268
|
}
|
|
261
269
|
|
|
262
270
|
/** `ares mcp`: stdout carries protocol frames only. */
|
|
263
|
-
export async function runMcp(env: NodeJS.ProcessEnv = process.env): Promise<void> {
|
|
271
|
+
export async function runMcp(env: NodeJS.ProcessEnv = process.env, http?: Http): Promise<void> {
|
|
264
272
|
const [{ serveMcp }, { createAresMcp }] = await Promise.all([import("./mcp.ts"), import("./mcp-tools.ts")]);
|
|
265
|
-
const server = createAresMcp(env);
|
|
273
|
+
const server = createAresMcp(env, http);
|
|
274
|
+
const terminate = () => {
|
|
275
|
+
try { server.terminate(); }
|
|
276
|
+
finally { releaseStudyLocksForExit(); process.exit(143); }
|
|
277
|
+
};
|
|
278
|
+
process.once("SIGTERM", terminate);
|
|
266
279
|
try { await serveMcp({ tools: server.tools, handlers: server.handlers, name: "ares", version }); }
|
|
267
|
-
finally { await server.waitForIdle(); }
|
|
280
|
+
finally { try { await server.waitForIdle(); } finally { process.off("SIGTERM", terminate); } }
|
|
268
281
|
}
|
|
269
282
|
|
|
270
283
|
/** Standard input stops at the input bound instead of buffering everything first. */
|
package/src/commands-table.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
export interface CommandSpec { name: string; usage: string; mutates: boolean | "network"; options: Record<string, "flag" | "value"> }
|
|
3
3
|
const json = { "--json": "flag" } as const;
|
|
4
4
|
export const COMMANDS: readonly CommandSpec[] = [
|
|
5
|
+
{ name: "autonomy show", usage: "autonomy show <dir> [--json]", mutates: false, options: json },
|
|
6
|
+
{ name: "autonomy set", usage: "autonomy set <dir> <auto|gates|copilot|step> [--phase PHASE] [--json]", mutates: true, options: { "--phase": "value", ...json } },
|
|
5
7
|
{ name: "skill propose", usage: "skill propose <dir> --file PATH|- [--json]", mutates: true, options: { "--file": "value", ...json } },
|
|
6
8
|
{ name: "skill decide", usage: "skill decide <dir> <name> <accept|reject|withdraw> --reason TEXT [--pr URL] [--json]", mutates: true, options: { "--reason": "value", "--pr": "value", ...json } },
|
|
7
9
|
{ name: "skill list", usage: "skill list <dir> [--json]", mutates: false, options: json },
|
|
@@ -15,12 +17,13 @@ export const COMMANDS: readonly CommandSpec[] = [
|
|
|
15
17
|
{ name: "console remove", usage: "console remove <dir> [--json]", mutates: true, options: json },
|
|
16
18
|
{ name: "console list", usage: "console list [--json]", mutates: false, options: json },
|
|
17
19
|
{ name: "manifest", usage: "manifest [--json]", mutates: false, options: json },
|
|
18
|
-
{ name: "init", usage: "init <dir> --question TEXT [--mode survey|experiment] [--autonomy auto|gates] [--json]", mutates: true, options: { "--question": "value", "--mode": "value", "--autonomy": "value", ...json } },
|
|
20
|
+
{ name: "init", usage: "init <dir> --question TEXT [--mode survey|experiment] [--autonomy auto|gates|copilot|step] [--json]", mutates: true, options: { "--question": "value", "--mode": "value", "--autonomy": "value", ...json } },
|
|
19
21
|
{ name: "run", usage: "run <dir> [--parallel 1..8] [--json]", mutates: "network", options: { "--parallel": "value", ...json } },
|
|
20
22
|
{ name: "plan set", usage: "plan set <dir> --file PATH|- [--json]", mutates: true, options: { "--file": "value", ...json } },
|
|
21
23
|
{ name: "plan control", usage: "plan control <dir> <pause|resume|retry|cancel|skip> [node] --command-id ID --expected-revision N [--json]", mutates: "network", options: { "--command-id": "value", "--expected-revision": "value", ...json } },
|
|
22
24
|
{ name: "plan show", usage: "plan show <dir> [--json]", mutates: false, options: json },
|
|
23
25
|
{ name: "status", usage: "status <dir> [--json]", mutates: false, options: json },
|
|
26
|
+
{ name: "study export", usage: "study export <dir> --bundle DIR [--list] [--json]", mutates: true, options: { "--bundle": "value", "--list": "flag", ...json } },
|
|
24
27
|
{ name: "scope", usage: "scope <dir> --file PATH|- [--json]", mutates: true, options: { "--file": "value", ...json } },
|
|
25
28
|
{ name: "idea add", usage: "idea add <dir> --file PATH|- [--json]", mutates: true, options: { "--file": "value", ...json } },
|
|
26
29
|
{ name: "idea decide", usage: "idea decide <dir> <id> <refine|pivot> --reason TEXT [--attempts ID[,ID...]] [--commit SHA] [--cause TEXT] [--retry-when TEXT] [--json]", mutates: true, options: { "--cause": "value", "--retry-when": "value", "--reason": "value", "--attempts": "value", "--commit": "value", ...json } },
|
|
@@ -37,8 +40,8 @@ export const COMMANDS: readonly CommandSpec[] = [
|
|
|
37
40
|
{ name: "executor set", usage: "executor set <dir> --kind local|ssh [--host ALIAS] --workdir PATH [--json]", mutates: true, options: { "--kind": "value", "--host": "value", "--workdir": "value", ...json } },
|
|
38
41
|
{ name: "executor check", usage: "executor check <dir> [--json]", mutates: "network", options: json },
|
|
39
42
|
{ name: "gate list", usage: "gate list <dir> [--json]", mutates: false, options: json },
|
|
40
|
-
{ name: "gate approve", usage: "gate approve <dir> <scope|screen|design|final|review|plan:node-id> [--reason TEXT] [--json]", mutates: true, options: { "--reason": "value", ...json } },
|
|
41
|
-
{ name: "gate reject", usage: "gate reject <dir> <scope|screen|design|final|review|plan:node-id> --reason TEXT [--json]", mutates: true, options: { "--reason": "value", ...json } },
|
|
43
|
+
{ name: "gate approve", usage: "gate approve <dir> <scope|screen|design|final|review|plan:node-id|accept:artifact> [--reason TEXT] [--json]", mutates: true, options: { "--reason": "value", ...json } },
|
|
44
|
+
{ name: "gate reject", usage: "gate reject <dir> <scope|screen|design|final|review|plan:node-id|accept:artifact> --reason TEXT [--json]", mutates: true, options: { "--reason": "value", ...json } },
|
|
42
45
|
{ name: "attempt run", usage: "attempt run <dir> --repo PATH --commit SHA [--seed N] [--run NAME] [--label TEXT] [--retry ID] [--detach] [--json]", mutates: "network", options: { "--repo": "value", "--commit": "value", "--seed": "value", "--run": "value", "--label": "value", "--retry": "value", "--detach": "flag", ...json } },
|
|
43
46
|
{ name: "attempt list", usage: "attempt list <dir> [--run NAME] [--status running|succeeded|failed|cancelled|unknown] [--limit N] [--offset N] [--json]", mutates: false, options: { "--run": "value", "--status": "value", "--limit": "value", "--offset": "value", ...json } },
|
|
44
47
|
{ name: "attempt show", usage: "attempt show <dir> <id> [--json]", mutates: false, options: json },
|