@post-print/agent-test 0.3.3 → 0.3.5
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/README.md +126 -157
- package/dist/check.d.ts +38 -0
- package/dist/check.d.ts.map +1 -0
- package/dist/check.js +169 -0
- package/dist/check.js.map +1 -0
- package/dist/cli.d.ts +12 -14
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +342 -366
- package/dist/cli.js.map +1 -1
- package/dist/compare-scenario.d.ts +33 -0
- package/dist/compare-scenario.d.ts.map +1 -0
- package/dist/compare-scenario.js +128 -0
- package/dist/compare-scenario.js.map +1 -0
- package/dist/debug-bundle.d.ts +2 -2
- package/dist/debug-bundle.d.ts.map +1 -1
- package/dist/debug-bundle.js +12 -12
- package/dist/debug-bundle.js.map +1 -1
- package/dist/doctor.d.ts +6 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +136 -14
- package/dist/doctor.js.map +1 -1
- package/dist/expect.d.ts +6 -5
- package/dist/expect.d.ts.map +1 -1
- package/dist/expect.js +67 -57
- package/dist/expect.js.map +1 -1
- package/dist/host-log.d.ts +17 -0
- package/dist/host-log.d.ts.map +1 -0
- package/dist/host-log.js +154 -0
- package/dist/host-log.js.map +1 -0
- package/dist/hosts.d.ts +22 -0
- package/dist/hosts.d.ts.map +1 -0
- package/dist/hosts.js +84 -0
- package/dist/hosts.js.map +1 -0
- package/dist/html-report.d.ts +0 -13
- package/dist/html-report.d.ts.map +1 -1
- package/dist/html-report.js +381 -318
- package/dist/html-report.js.map +1 -1
- package/dist/index.d.ts +15 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -7
- package/dist/index.js.map +1 -1
- package/dist/live-isolation.d.ts +11 -5
- package/dist/live-isolation.d.ts.map +1 -1
- package/dist/live-isolation.js +32 -14
- package/dist/live-isolation.js.map +1 -1
- package/dist/load-adapters.d.ts +13 -0
- package/dist/load-adapters.d.ts.map +1 -0
- package/dist/load-adapters.js +76 -0
- package/dist/load-adapters.js.map +1 -0
- package/dist/load-suite.d.ts.map +1 -1
- package/dist/load-suite.js +16 -0
- package/dist/load-suite.js.map +1 -1
- package/dist/mcp-config.d.ts +8 -0
- package/dist/mcp-config.d.ts.map +1 -1
- package/dist/mcp-config.js +46 -0
- package/dist/mcp-config.js.map +1 -1
- package/dist/preflight.d.ts +2 -2
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js +4 -4
- package/dist/preflight.js.map +1 -1
- package/dist/progress.d.ts +7 -0
- package/dist/progress.d.ts.map +1 -1
- package/dist/progress.js +39 -9
- package/dist/progress.js.map +1 -1
- package/dist/record-trace.d.ts +11 -20
- package/dist/record-trace.d.ts.map +1 -1
- package/dist/record-trace.js +10 -57
- package/dist/record-trace.js.map +1 -1
- package/dist/report-preview-server.d.ts +2 -0
- package/dist/report-preview-server.d.ts.map +1 -0
- package/dist/report-preview-server.js +24 -0
- package/dist/report-preview-server.js.map +1 -0
- package/dist/report-preview.d.ts +11 -0
- package/dist/report-preview.d.ts.map +1 -0
- package/dist/report-preview.js +161 -0
- package/dist/report-preview.js.map +1 -0
- package/dist/run-suite.d.ts +62 -11
- package/dist/run-suite.d.ts.map +1 -1
- package/dist/run-suite.js +697 -206
- package/dist/run-suite.js.map +1 -1
- package/dist/scenario-story.d.ts +41 -0
- package/dist/scenario-story.d.ts.map +1 -0
- package/dist/scenario-story.js +198 -0
- package/dist/scenario-story.js.map +1 -0
- package/dist/suite-summary.d.ts +2 -0
- package/dist/suite-summary.d.ts.map +1 -1
- package/dist/suite-summary.js +70 -22
- package/dist/suite-summary.js.map +1 -1
- package/dist/theme.d.ts +29 -5
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +204 -45
- package/dist/theme.js.map +1 -1
- package/dist/types.d.ts +107 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/validate-seeds.d.ts.map +1 -1
- package/dist/validate-seeds.js +21 -6
- package/dist/validate-seeds.js.map +1 -1
- package/dist/validate-suite.d.ts +3 -1
- package/dist/validate-suite.d.ts.map +1 -1
- package/dist/validate-suite.js +256 -22
- package/dist/validate-suite.js.map +1 -1
- package/package.json +5 -5
- package/dist/compare.d.ts +0 -79
- package/dist/compare.d.ts.map +0 -1
- package/dist/compare.js +0 -232
- package/dist/compare.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,210 +1,179 @@
|
|
|
1
1
|
# @post-print/agent-test
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<!-- source-of-truth: the direct-agent test package -->
|
|
4
4
|
|
|
5
|
-
<!-- doc-meta: owner=eng | last-reviewed=2026-
|
|
5
|
+
<!-- doc-meta: owner=eng | last-reviewed=2026-09-13 -->
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
<!-- review-deps: paths=packages/test/src/*.ts,packages/test/src/**/*.ts,packages/test/package.json -->
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Scenario runner for real Cursor, Claude, and OpenAI Codex agents, built on `@post-print/agent-harness`.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
> **Deprecated and removed:** stored-trace replay is not an agent test. `host: "replay"`, `replayTrace`, `--record-fixtures`, and the old `--live` mode flag are rejected with migration guidance.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
## Direct TypeScript API
|
|
14
|
+
|
|
15
|
+
`runAgentTest` is the execution core. JSON suites load into this same function.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { runAgentTest } from "@post-print/agent-test";
|
|
19
|
+
|
|
20
|
+
const result = await runAgentTest({
|
|
21
|
+
cwd: process.cwd(),
|
|
22
|
+
scenario: {
|
|
23
|
+
name: "uses the project instructions",
|
|
24
|
+
prompt: "Review the current change.",
|
|
25
|
+
rubric: { mustReadPath: ["AGENTS.md"] },
|
|
26
|
+
},
|
|
27
|
+
});
|
|
16
28
|
```
|
|
17
29
|
|
|
18
|
-
|
|
30
|
+
The default host is Cursor. Set `scenario.host`, `defaults.host`, or the top-level `host` option to `claude` or `openai`. The scenario host wins over the top-level override, which wins over suite defaults. The default suite name is `direct`. Sealed-workspace isolation, judging, timeout enforcement, and announce-stop retry are enabled by default.
|
|
19
31
|
|
|
20
|
-
##
|
|
32
|
+
## JSON suites and CLI
|
|
21
33
|
|
|
22
|
-
|
|
34
|
+
JSON is an authoring adapter, not a stored answer. This repository keeps host-agent suites under `agent-suites/<suite>/scenarios.json`. Consumer repositories can use the same layout.
|
|
23
35
|
|
|
24
36
|
```bash
|
|
25
37
|
npx agent-test --suites-dir agent-suites
|
|
26
|
-
npx agent-test --suites-dir agent-suites --
|
|
27
|
-
npx agent-test --suites-dir agent-suites --
|
|
28
|
-
npx agent-test --suites-dir agent-suites --
|
|
29
|
-
npx agent-test --
|
|
30
|
-
npx agent-test
|
|
31
|
-
npx agent-test --suites-dir agent-suites --
|
|
32
|
-
npx agent-test --suites-dir agent-suites
|
|
33
|
-
npx agent-test --doctor
|
|
38
|
+
npx agent-test --suites-dir agent-suites --host cursor
|
|
39
|
+
npx agent-test --suites-dir agent-suites --suite smoke
|
|
40
|
+
npx agent-test --suites-dir agent-suites --suite tools
|
|
41
|
+
npx agent-test --suites-dir agent-suites --suite mcp
|
|
42
|
+
npx agent-test --suites-dir agent-suites --suite judge
|
|
43
|
+
npx agent-test --suites-dir agent-suites --suite depth
|
|
44
|
+
npx agent-test --check --suites-dir agent-suites
|
|
34
45
|
```
|
|
35
46
|
|
|
36
|
-
|
|
47
|
+
In-repo suites list `hosts: ["cursor", "claude", "openai"]`. `npx agent-test --suites-dir agent-suites` and `bun run test` run every suite on each host. That is the consumer confidence gate. Pass `--host cursor` to pin one adapter.
|
|
37
48
|
|
|
38
|
-
|
|
49
|
+
`smoke` is the short host proof. `tools` checks Read and Write. `mcp` checks echo invoke and a lookup read. `judge` starts a second host call that scores the reply. One judge scenario runs two workspace arms and scores both transcripts together. `depth` checks workspace roots, seed patches, injected context, mustRun, and skill invoke. `bun run test:smoke` stays on Cursor.
|
|
39
50
|
|
|
40
|
-
|
|
41
|
-
| --- | --- |
|
|
42
|
-
| ends with `.html` | the HTML report is written to exactly that file (parent dirs created) |
|
|
43
|
-
| any other path | treated as a directory: `report.html` plus all other report content — per-suite `<suite>.suite-report.json`, and the compare JSON / markdown / HTML when `--compare-pairs` is used |
|
|
51
|
+
`scenario.host` pins that scenario to one host. A matrix run skips it on the other hosts.
|
|
44
52
|
|
|
45
|
-
|
|
53
|
+
## Custom hosts
|
|
46
54
|
|
|
47
|
-
|
|
55
|
+
A consumer repo can register its own adapter.
|
|
48
56
|
|
|
49
|
-
|
|
57
|
+
```js
|
|
58
|
+
// agent-test.config.mjs
|
|
59
|
+
import { defineConfig } from "@post-print/agent-test";
|
|
50
60
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
export default defineConfig({
|
|
62
|
+
adapters: [
|
|
63
|
+
{
|
|
64
|
+
host: "gemini",
|
|
65
|
+
missingAuth() {
|
|
66
|
+
return process.env.GEMINI_API_KEY ? undefined : "GEMINI_API_KEY not set";
|
|
67
|
+
},
|
|
68
|
+
classifierHost: "cursor",
|
|
69
|
+
async run(options) {
|
|
70
|
+
return {
|
|
71
|
+
host: "gemini",
|
|
72
|
+
status: "completed",
|
|
73
|
+
durationMs: 0,
|
|
74
|
+
trace: {
|
|
75
|
+
messages: [{ role: "assistant", content: options.prompt }],
|
|
76
|
+
toolCalls: [],
|
|
77
|
+
shellCommands: [],
|
|
78
|
+
artifacts: {},
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
});
|
|
85
|
+
```
|
|
57
86
|
|
|
58
|
-
|
|
87
|
+
Then `--host gemini` and a suite `hosts` list can include `gemini`. You can also pass `--adapter ./hosts/gemini.mjs`. The module can export `{ adapters: [...] }` or call `registerHostAdapter` as a side effect.
|
|
59
88
|
|
|
60
|
-
|
|
89
|
+
Do not reuse `cursor`, `claude`, `openai`, `replay`, or `all` as the slug.
|
|
61
90
|
|
|
62
|
-
|
|
91
|
+
Direct runs need host auth. Cursor uses `CURSOR_API_KEY`, or `CURSOR_AUTH_MODE=subscription` after `Cursor.auth.login()`. The Cursor app login does not count. Claude uses `CLAUDE_AUTH_MODE` plus `ANTHROPIC_API_KEY` or a Claude Code login. OpenAI uses `OPENAI_API_KEY` or `CODEX_API_KEY`, or `OPENAI_AUTH_MODE=subscription` after `codex login`. The judge uses the same host family. It runs when a rubric has judge questions or `mustInvokeSkill`. A `compare` scenario runs two arms. `compare.faster` and `compare.cheaper` pick a metric winner. `rubric.judge` is optional and scores both transcripts. `--no-judge` turns the judge off. The CLI does not load `.env`.
|
|
63
92
|
|
|
64
|
-
|
|
93
|
+
`--allow-user-input` starts a second classifier as the user. That user agent answers AskQuestion-style tools. The test agent then continues with the original task plus the transcript.
|
|
65
94
|
|
|
66
|
-
|
|
67
|
-
| ------------------------------------------- | ------------------------------------------------------------- |
|
|
68
|
-
| `CURSOR_API_KEY` | Required for `--live` Cursor and judge classifiers |
|
|
69
|
-
| `CLAUDE_AUTH_MODE` | Required for `--live --host claude`: `api-key` or `subscription` (no default) |
|
|
70
|
-
| `ANTHROPIC_API_KEY` | Required when `CLAUDE_AUTH_MODE=api-key` |
|
|
71
|
-
| `CLAUDE_CODE_BIN` | Optional path to Claude Code CLI binary |
|
|
72
|
-
| `CLAUDE_AGENT_MODEL` | Optional Claude model override |
|
|
73
|
-
| `CLAUDE_CODE_ALLOWED_TOOLS` | Optional `--allowedTools` list for Claude live runs |
|
|
74
|
-
| `AGENT_TEST_DEBUG` | Same as `--debug` when `1`/`true` |
|
|
75
|
-
| `AGENT_TEST_VERBOSE` | Extra tips (e.g. OOM isolation) when `1` |
|
|
76
|
-
| `AGENT_TEST_VERBOSE_PATHS` | Print full paths when `1` |
|
|
77
|
-
| `AGENT_TEST_QUIET` | Suppress progress when `1` |
|
|
78
|
-
| `AGENT_TEST_TIMEOUT_MS` | Live hard timeout (default 600000; `0` disables) |
|
|
79
|
-
| `AGENT_TEST_LIVE_RETRIES` | Judge infra retry attempts (default 3) |
|
|
80
|
-
| `AGENT_TEST_SCENARIO_RETRIES` | Live announce-stop scenario retries (default 1; `0` disables) |
|
|
81
|
-
| `AGENT_TEST_ALLOW_IN_PLACE` | Allow `--no-worktree` live runs when `1` |
|
|
82
|
-
| `AGENT_TEST_NO_WORKTREE` | Disable worktree isolation when `1`/`true` |
|
|
83
|
-
| `AGENT_TEST_NO_ISOLATE` | Disable isolated subprocesses when `1` |
|
|
84
|
-
| `AGENT_TEST_SCENARIO_SETTLE_MS` | Settle delay between live scenarios |
|
|
85
|
-
| `CURSOR_AGENT_MODEL` / `CURSOR_JUDGE_MODEL` | Optional model overrides |
|
|
86
|
-
| `CURSOR_JUDGE_TEMPERATURE` | Optional judge temperature |
|
|
95
|
+
## Check, rubrics, and compare
|
|
87
96
|
|
|
88
|
-
|
|
97
|
+
`--check` inspects the suite, seeds, package, and host. It does not launch an agent. A live run runs the same check first, then starts the host.
|
|
89
98
|
|
|
90
99
|
```bash
|
|
91
|
-
npx agent-test --suites-dir agent-suites
|
|
92
|
-
npx agent-test --suites-dir agent-suites --live --debug
|
|
93
|
-
npx agent-test --suites-dir agent-suites --live --debug --debug-dir "$TMPDIR/agent-test-debug"
|
|
100
|
+
npx agent-test --check --suites-dir agent-suites
|
|
94
101
|
```
|
|
95
102
|
|
|
96
|
-
|
|
103
|
+
A compare scenario sets `compare.a` and `compare.b`. Each arm can override workspace, prompt, host, skills, or extra rubric checks. Arm rubric arrays append onto the scenario rubric. Do not put `judge` on an arm. `compare.faster` and `compare.cheaper` name the arm that must win on time or tokens. Add `rubric.judge` when you want a pairwise judge. Omit it for a metric-only compare. `--no-judge` skips the judge.
|
|
97
104
|
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"name": "cheaper prompt",
|
|
108
|
+
"prompt": "Read README.txt. Reply with one sentence.",
|
|
109
|
+
"compare": {
|
|
110
|
+
"a": { "label": "verbose", "prompt": "Read README.txt. Write a long summary." },
|
|
111
|
+
"b": { "label": "short" },
|
|
112
|
+
"cheaper": "b"
|
|
113
|
+
},
|
|
114
|
+
"rubric": { "mustReadPath": ["README.txt"] }
|
|
115
|
+
}
|
|
98
116
|
```
|
|
99
|
-
sessions/<id>/<suite>/<scenario>.debug/
|
|
100
|
-
summary.md # verdict + Why (category hint + evidence + trace stats)
|
|
101
|
-
transcript.md # Why, prompt, rubric, interleaved messages/tools (incl. results), failures
|
|
102
|
-
scenario.json # prompt + rubric + seed metadata
|
|
103
|
-
result.json # pass/fail, duration, failures, usage, skillsInvoked, routing, counts
|
|
104
|
-
trace.json
|
|
105
|
-
failures.json # includes category + evidence
|
|
106
|
-
judge-debug.json # when judge criteria ran (SDK status/error, sizes, attempt)
|
|
107
|
-
environment.json # versions/models/timeout/isolation; API keys only as booleans
|
|
108
|
-
rerun.sh # shell-quoted exact re-run command (export API keys yourself)
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
**Debug dir default:** omit `--debug-dir` to stage under `$TMPDIR/agent-spec/sessions/<id>/…` (outside the repo). Passing an in-repo `--debug-dir` (for example `./agent-test-debug`) is supported — harness staging paths under that dir are excluded from worktree leak checks — but prefer `$TMPDIR` so debug artifacts never appear in `git status`.
|
|
112
|
-
|
|
113
|
-
`--debug-dir <path>` replaces `$TMPDIR/agent-spec` as the sessions parent (`<path>/sessions/<id>/…`).
|
|
114
|
-
|
|
115
|
-
Failure categories printed on FAIL lines and in `failures.json`:
|
|
116
|
-
|
|
117
|
-
| Category | Meaning |
|
|
118
|
-
| ----------------- | -------------------------------------------------------------------------------------- |
|
|
119
|
-
| `rubric_miss` | Assertion/judge criterion miss |
|
|
120
|
-
| `judge_infra` | Judge SDK/API failure (not a criterion miss) |
|
|
121
|
-
| `agent_runtime` | Agent session error, timeout, AskQuestion, subprocess exit |
|
|
122
|
-
| `worktree_leak` | Live agent mutated the caller working tree (harness `--debug-dir` staging is excluded) |
|
|
123
|
-
| `recording_error` | Failed to persist a staging/fixture trace |
|
|
124
117
|
|
|
125
|
-
|
|
118
|
+
Use two workspaces when one arm has a skill and the other does not. Put `mustInvokeSkill` on the skill arm only.
|
|
126
119
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"name": "skill vs no skill",
|
|
123
|
+
"prompt": "Read every markdown file. Write a detailed shipping plan.",
|
|
124
|
+
"compare": {
|
|
125
|
+
"a": {
|
|
126
|
+
"label": "no skill",
|
|
127
|
+
"workspace": "workspaces/skill-off",
|
|
128
|
+
"rubric": { "mustNotInvokeSkill": ["brief-ship"] }
|
|
129
|
+
},
|
|
130
|
+
"b": {
|
|
131
|
+
"label": "with skill",
|
|
132
|
+
"workspace": "workspaces/skill-on",
|
|
133
|
+
"skills": [".agents/skills/brief-ship/SKILL.md"],
|
|
134
|
+
"rubric": { "mustInvokeSkill": ["brief-ship"] }
|
|
135
|
+
},
|
|
136
|
+
"cheaper": "b"
|
|
137
|
+
},
|
|
138
|
+
"rubric": {
|
|
139
|
+
"mustReadPath": ["note.md"],
|
|
140
|
+
"judge": ["Did the skill arm stay closer to the note?"]
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
134
144
|
|
|
135
|
-
|
|
145
|
+
`--doctor`, `--validate-only`, `--validate-paths`, and `--validate-seeds` are aliases for `--check`.
|
|
136
146
|
|
|
137
|
-
|
|
138
|
-
- **Worktree does not:** stop context (skills/rules) from loading from the caller checkout by design, or stop Cursor **local** agents from Shell/Read against the IDE-open workspace instead of only `local.cwd`.
|
|
147
|
+
`scenarios.json` can omit inline rubric keys when a sibling `rubrics.json` / `scenarios.rubric.json` or `--rubrics-dir` supplies them.
|
|
139
148
|
|
|
140
|
-
|
|
149
|
+
## Isolation and diagnostics
|
|
141
150
|
|
|
142
|
-
-
|
|
143
|
-
- seeds that only mutate fixtures (not skill bodies)
|
|
144
|
-
- harness-only rubrics (sibling `rubrics.json` / `scenarios.rubric.json`, or `--rubrics-dir` outside the open workspace)
|
|
145
|
-
- consumer orchestrators that park answer keys off the open workspace (toolbox pattern)
|
|
146
|
-
- cloud runtime when true FS isolation is required
|
|
151
|
+
In-repo suites set `workspace` on every scenario. The runner copies that folder into a temp repo. Omit `workspace`, or set `"."`, to copy HEAD plus caller context instead. The folder gets its own `.git`. The runner fails the scenario when tool paths leave that folder. A leftover caller-tree check still restores leaked caller edits.
|
|
147
152
|
|
|
148
|
-
|
|
153
|
+
Host-global user skills stay out of the run by default. Those trees live under `~/.cursor/skills`, `~/.claude/skills`, `~/.codex/skills`, and `~/.agents/skills`. A custom `workspace` is a fixture. Keep `allowUserSkills` false for that case. Set `allowUserSkills` to true on the scenario or suite defaults when the test needs the machine skill set. The `skills` field only overlays repo-relative folders into the sealed workspace.
|
|
149
154
|
|
|
150
|
-
|
|
155
|
+
`contextSources` and `skills` are relative to the workspace root when `workspace` is a subfolder. A bare `contextSources` name is a file in that root. `seedPatch` stays a caller-repo path. Its hunks are relative to that workspace.
|
|
151
156
|
|
|
152
|
-
|
|
157
|
+
`--debug` retains an evidence bundle under `$TMPDIR/agent-spec/sessions/<id>/` by default. Use `--debug-dir` to override the parent directory.
|
|
153
158
|
|
|
154
|
-
|
|
159
|
+
Host SDK INFO lines stay hidden. Set `AGENT_TEST_HOST_LOGS=1` or `--debug` to print them.
|
|
155
160
|
|
|
156
|
-
|
|
157
|
-
- **One-shot live prompt** — instruct the agent to mirror intent and emit the final artifact in a single turn (`no AskQuestion; produce Crystallized idea now`).
|
|
158
|
-
- **Ambient routing** — fuzzy-intent scenarios that only require mirroring + one assumption are naturally one-shot; full crystallize dialogue is not.
|
|
161
|
+
A TTY run prints `agent started`, then updates an `agent` clock every 0.1s. Tool names and a short reply preview print as the host streams them. The clock line stays one row so the terminal can overwrite it. The HTML report line is a localhost link. A click opens the browser. The preview exits after 30 minutes idle. Set `AGENT_TEST_NO_REPORT_PREVIEW=1` to skip the preview.
|
|
159
162
|
|
|
160
|
-
|
|
163
|
+
`Ctrl+C` cancels active host work and deletes the temp folder. `--no-worktree` requires `AGENT_TEST_ALLOW_IN_PLACE=1` because agent edits will persist in the caller checkout.
|
|
161
164
|
|
|
162
165
|
## MCP servers
|
|
163
166
|
|
|
164
|
-
|
|
167
|
+
Scenarios can attach inline stdio or HTTP/SSE MCP servers through suite defaults or scenario overrides. Ambient project/user MCP configuration is not loaded. When `workspace` is a subfolder, stdio MCP cwd is the caller repo. Script args stay caller-relative.
|
|
165
168
|
|
|
166
|
-
|
|
167
|
-
{
|
|
168
|
-
"defaults": {
|
|
169
|
-
"mcpServers": {
|
|
170
|
-
"docs": {
|
|
171
|
-
"type": "http",
|
|
172
|
-
"url": "https://example.com/mcp",
|
|
173
|
-
"headers": { "Authorization": "Bearer ${DOCS_TOKEN}" }
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
"scenarios": [
|
|
178
|
-
{
|
|
179
|
-
"name": "use echo",
|
|
180
|
-
"prompt": "Call the echo tool with text hello.",
|
|
181
|
-
"mcpServers": {
|
|
182
|
-
"echo": {
|
|
183
|
-
"type": "stdio",
|
|
184
|
-
"command": "node",
|
|
185
|
-
"args": ["packages/test/fixtures/mcp-echo/server.mjs"]
|
|
186
|
-
}
|
|
187
|
-
},
|
|
188
|
-
"rubric": {
|
|
189
|
-
"mustCallTool": ["echo:hello"],
|
|
190
|
-
"mustNotCallTool": ["shell"]
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
]
|
|
194
|
-
}
|
|
195
|
-
```
|
|
169
|
+
## In-repo package checks
|
|
196
170
|
|
|
197
|
-
|
|
198
|
-
- `${ENV_VAR}` placeholders expand in `command`, `args`, `env`, `url`, `headers`, and OAuth fields at run time.
|
|
199
|
-
- Rubric `mustCallTool` / `mustNotCallTool` match tool **name** substrings (works with MCP name prefixes). Use `name:argFragment` to also require a substring in JSON args.
|
|
200
|
-
- Rubric `mustReadPath` / `mustNotReadPath` match substrings on **Read** tool JSON args (registry-first / avoid inventing paths). Keep hallucination scoring in live `judge` questions — no heavy factuality engine in v1.
|
|
201
|
-
- Suite defaults may set `profile: "skeleton"` and/or `contextSources` (additive paths / `.skeleton/customize/` basenames). Shared/cursor/claude defaults stay backwards-compatible.
|
|
202
|
-
- Live runs surface provider `usage` on traces/results; suite summary + HTML report include token sum / p50 / p95 when present.
|
|
203
|
-
- `--compare-pairs A:B` (or `agent-test compare --a/--b`) pairs scenarios by **`compareId`** when present, else band-neutral scenario name (`outcome:` / `transfer:` stripped), and writes `compare-report.json` / `.md` / `.html` with pass/fail, tokens, toolCallCount, durationMs, and skill/registry hop proxies. Suite HTML also embeds an A/B table when two reports are present.
|
|
204
|
-
- Replay hosts ignore `mcpServers` but still score recorded `toolCalls` against those matchers.
|
|
171
|
+
Default CI does not launch a paid agent:
|
|
205
172
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
173
|
+
```bash
|
|
174
|
+
bun run build
|
|
175
|
+
node packages/test/dist/cli.js --check --suites-dir packages/test/fixtures --suite smoke
|
|
176
|
+
node packages/test/dist/cli.js --check --suites-dir agent-suites --suite smoke
|
|
210
177
|
```
|
|
178
|
+
|
|
179
|
+
Host-agent acceptance is `bun run test`. That command runs smoke, tools, mcp, judge, and depth on Cursor, Claude, and Codex. `bun run test:smoke`, `bun run test:tools`, `bun run test:mcp`, `bun run test:judge`, and `bun run test:depth` stay on Cursor. A key-gated GitHub Actions job runs the same suites on Cursor when `CURSOR_API_KEY` is present.
|
package/dist/check.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type AgentHost } from "@post-print/agent-harness";
|
|
2
|
+
export interface CheckOptions {
|
|
3
|
+
cwd: string;
|
|
4
|
+
suitesDir: string;
|
|
5
|
+
filter?: string;
|
|
6
|
+
rubricsDir?: string;
|
|
7
|
+
/** CLI host override. Wins over suite defaults when set. */
|
|
8
|
+
host?: AgentHost;
|
|
9
|
+
/** CLI host matrix. Wins over `host` when more than one name is listed. */
|
|
10
|
+
hosts?: readonly AgentHost[];
|
|
11
|
+
cliPath?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface CheckReport {
|
|
14
|
+
/** Package, suite, and seed checks passed. Host readiness is separate. */
|
|
15
|
+
ok: boolean;
|
|
16
|
+
packageOk: boolean;
|
|
17
|
+
suiteOk: boolean;
|
|
18
|
+
seedsOk: boolean;
|
|
19
|
+
hostReady: boolean;
|
|
20
|
+
hosts: AgentHost[];
|
|
21
|
+
messages: string[];
|
|
22
|
+
}
|
|
23
|
+
/** Hosts a live run will launch after suite defaults and an optional CLI override. */
|
|
24
|
+
export declare function collectSuiteHosts(options: {
|
|
25
|
+
cwd: string;
|
|
26
|
+
suitesDir: string;
|
|
27
|
+
filter?: string;
|
|
28
|
+
rubricsDir?: string;
|
|
29
|
+
host?: AgentHost;
|
|
30
|
+
hosts?: readonly AgentHost[];
|
|
31
|
+
}): Promise<AgentHost[]>;
|
|
32
|
+
/** Missing auth for every host this run will launch. Undefined when all hosts are ready. */
|
|
33
|
+
export declare function missingHostsAuth(hosts: readonly AgentHost[]): string | undefined;
|
|
34
|
+
/** Suite, seed, package, and host checks. Does not launch an agent. */
|
|
35
|
+
export declare function runCheck(options: CheckOptions): Promise<CheckReport>;
|
|
36
|
+
export declare function formatCheckReport(report: CheckReport): string;
|
|
37
|
+
export declare function formatCheckSummary(report: CheckReport): string;
|
|
38
|
+
//# sourceMappingURL=check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,2BAA2B,CAAC;AAS7E,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC3B,0EAA0E;IAC1E,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACnB;AAoBD,sFAAsF;AACtF,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;CAC7B,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAmDvB;AAED,4FAA4F;AAC5F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,GAAG,SAAS,CAMhF;AAED,uEAAuE;AACvE,wBAAsB,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAsE1E;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAE7D;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAO9D"}
|
package/dist/check.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { access } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { isKnownAgentHost } from "@post-print/agent-harness";
|
|
4
|
+
import { discoverSuites } from "./discover-suites.js";
|
|
5
|
+
import { missingAgentAuth, runDoctor } from "./doctor.js";
|
|
6
|
+
import { resolveSuiteHosts, uniqueHosts } from "./hosts.js";
|
|
7
|
+
import { loadSuiteFile } from "./load-suite.js";
|
|
8
|
+
import { formatSeedValidationReport, validateSeedPatches } from "./validate-seeds.js";
|
|
9
|
+
import { formatValidationReport, validateSuitePaths } from "./validate-suite.js";
|
|
10
|
+
function filterSuitePaths(suitePaths, filter) {
|
|
11
|
+
if (!filter) {
|
|
12
|
+
return suitePaths;
|
|
13
|
+
}
|
|
14
|
+
return suitePaths.filter((path) => path.includes(`/${filter}/`) || path.endsWith(`/${filter}/scenarios.json`));
|
|
15
|
+
}
|
|
16
|
+
async function suitesDirExists(cwd, suitesDir) {
|
|
17
|
+
try {
|
|
18
|
+
await access(resolve(cwd, suitesDir));
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** Hosts a live run will launch after suite defaults and an optional CLI override. */
|
|
26
|
+
export async function collectSuiteHosts(options) {
|
|
27
|
+
const cliHosts = uniqueHosts(options.hosts ?? (options.host ? [options.host] : undefined));
|
|
28
|
+
if (cliHosts?.length === 1) {
|
|
29
|
+
return cliHosts;
|
|
30
|
+
}
|
|
31
|
+
const root = resolve(options.cwd, options.suitesDir);
|
|
32
|
+
let suitePaths = [];
|
|
33
|
+
try {
|
|
34
|
+
suitePaths = filterSuitePaths(await discoverSuites(root), options.filter);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return cliHosts ?? ["cursor"];
|
|
38
|
+
}
|
|
39
|
+
if (suitePaths.length === 0) {
|
|
40
|
+
return cliHosts ?? ["cursor"];
|
|
41
|
+
}
|
|
42
|
+
const hosts = new Set();
|
|
43
|
+
for (const suitePath of suitePaths) {
|
|
44
|
+
try {
|
|
45
|
+
const suite = await loadSuiteFile(suitePath, { rubricsDir: options.rubricsDir });
|
|
46
|
+
const resolved = resolveSuiteHosts({
|
|
47
|
+
cliHosts,
|
|
48
|
+
suiteHosts: suite.hosts,
|
|
49
|
+
defaultHost: suite.defaults?.host,
|
|
50
|
+
});
|
|
51
|
+
if (resolved.length > 1 || (suite.hosts !== undefined && suite.hosts.length > 0)) {
|
|
52
|
+
for (const host of resolved) {
|
|
53
|
+
hosts.add(host);
|
|
54
|
+
}
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const fallback = suite.defaults?.host ?? "cursor";
|
|
58
|
+
for (const scenario of suite.scenarios) {
|
|
59
|
+
if (scenario.skip) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const host = scenario.host ?? fallback;
|
|
63
|
+
if (isKnownAgentHost(host)) {
|
|
64
|
+
hosts.add(host);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (suite.scenarios.length === 0 && isKnownAgentHost(fallback)) {
|
|
68
|
+
hosts.add(fallback);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Invalid files are reported by suite validation.
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (hosts.size === 0) {
|
|
76
|
+
return cliHosts ?? ["cursor"];
|
|
77
|
+
}
|
|
78
|
+
return [...hosts];
|
|
79
|
+
}
|
|
80
|
+
/** Missing auth for every host this run will launch. Undefined when all hosts are ready. */
|
|
81
|
+
export function missingHostsAuth(hosts) {
|
|
82
|
+
const missing = hosts.map((host) => missingAgentAuth(host)).filter((message) => message);
|
|
83
|
+
if (missing.length === 0) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
return missing.join("\n");
|
|
87
|
+
}
|
|
88
|
+
/** Suite, seed, package, and host checks. Does not launch an agent. */
|
|
89
|
+
export async function runCheck(options) {
|
|
90
|
+
const messages = [];
|
|
91
|
+
const doctor = runDoctor({ cliPath: options.cliPath });
|
|
92
|
+
messages.push("package");
|
|
93
|
+
for (const message of doctor.messages) {
|
|
94
|
+
messages.push(` ${message}`);
|
|
95
|
+
}
|
|
96
|
+
const hosts = await collectSuiteHosts(options);
|
|
97
|
+
const hostError = missingHostsAuth(hosts);
|
|
98
|
+
const hostReady = hostError === undefined;
|
|
99
|
+
messages.push("host");
|
|
100
|
+
messages.push(` ${hosts.join(", ")}: ${hostReady ? "ready" : (hostError ?? "not ready")}`);
|
|
101
|
+
let suiteOk = false;
|
|
102
|
+
const suitesRoot = resolve(options.cwd, options.suitesDir);
|
|
103
|
+
if (!(await suitesDirExists(options.cwd, options.suitesDir))) {
|
|
104
|
+
messages.push("suite");
|
|
105
|
+
messages.push(` missing ${suitesRoot}`);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
const suitePaths = filterSuitePaths(await discoverSuites(suitesRoot), options.filter);
|
|
109
|
+
if (suitePaths.length === 0) {
|
|
110
|
+
messages.push("suite");
|
|
111
|
+
messages.push(` No suites found under ${options.suitesDir}`);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const suiteReport = await validateSuitePaths(suitePaths, {
|
|
115
|
+
validatePaths: true,
|
|
116
|
+
repoRoot: options.cwd,
|
|
117
|
+
rubricsDir: options.rubricsDir,
|
|
118
|
+
});
|
|
119
|
+
suiteOk = suiteReport.ok;
|
|
120
|
+
messages.push("suite");
|
|
121
|
+
for (const line of formatValidationReport(suiteReport).split("\n")) {
|
|
122
|
+
messages.push(` ${line}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const seedReport = await validateSeedPatches({
|
|
127
|
+
cwd: options.cwd,
|
|
128
|
+
suitesDir: options.suitesDir,
|
|
129
|
+
rubricsDir: options.rubricsDir,
|
|
130
|
+
filter: options.filter,
|
|
131
|
+
}).catch((error) => ({
|
|
132
|
+
ok: false,
|
|
133
|
+
issues: [
|
|
134
|
+
{
|
|
135
|
+
suite: options.suitesDir,
|
|
136
|
+
scenario: "*",
|
|
137
|
+
seedPatch: "",
|
|
138
|
+
message: error instanceof Error ? error.message : String(error),
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
checked: 0,
|
|
142
|
+
}));
|
|
143
|
+
const seedsOk = seedReport.ok;
|
|
144
|
+
messages.push("seeds");
|
|
145
|
+
for (const line of formatSeedValidationReport(seedReport).split("\n")) {
|
|
146
|
+
messages.push(` ${line}`);
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
ok: doctor.ok && suiteOk && seedsOk,
|
|
150
|
+
packageOk: doctor.ok,
|
|
151
|
+
suiteOk,
|
|
152
|
+
seedsOk,
|
|
153
|
+
hostReady,
|
|
154
|
+
hosts,
|
|
155
|
+
messages,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
export function formatCheckReport(report) {
|
|
159
|
+
return ["agent-test check", ...report.messages].join("\n");
|
|
160
|
+
}
|
|
161
|
+
export function formatCheckSummary(report) {
|
|
162
|
+
const suite = report.suiteOk ? "suite ok" : "suite failed";
|
|
163
|
+
const pkg = report.packageOk ? "package ok" : "package failed";
|
|
164
|
+
const host = report.hostReady
|
|
165
|
+
? `host ${report.hosts.join(",")} ready`
|
|
166
|
+
: `host ${report.hosts.join(",")} not ready`;
|
|
167
|
+
return `check ${pkg} · ${suite} · ${host}`;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
CHANGED
|
@@ -7,18 +7,24 @@ export interface ParsedCliArgs {
|
|
|
7
7
|
/** Prefer `<rubricsDir>/<suite>/rubrics.json` (harness-only answer keys). */
|
|
8
8
|
rubricsDir?: string;
|
|
9
9
|
host?: AgentHost;
|
|
10
|
+
/** Host matrix when `--host` lists more than one adapter. */
|
|
11
|
+
hosts?: AgentHost[];
|
|
12
|
+
/** True when `--host` included `all`. Re-expand after adapters load. */
|
|
13
|
+
hostAll?: boolean;
|
|
14
|
+
/** Consumer adapter modules (`--adapter`). */
|
|
15
|
+
adapterModules?: string[];
|
|
10
16
|
filter?: string;
|
|
11
17
|
scenarioFilter?: string;
|
|
12
18
|
stagingSessionId?: string;
|
|
13
|
-
record: boolean;
|
|
14
|
-
recordFixtures: boolean;
|
|
15
|
-
live: boolean;
|
|
16
19
|
judge?: boolean;
|
|
17
20
|
worktree?: boolean;
|
|
18
21
|
keepRecordings: boolean;
|
|
19
22
|
timeoutMs?: number;
|
|
20
23
|
noTimeout: boolean;
|
|
21
24
|
allowUserInput: boolean;
|
|
25
|
+
/** Check the suite and host. Do not launch an agent. */
|
|
26
|
+
check: boolean;
|
|
27
|
+
help: boolean;
|
|
22
28
|
doctor: boolean;
|
|
23
29
|
htmlReport: boolean;
|
|
24
30
|
/** Explicit HTML report path (ends in .html) or output directory for all report content. */
|
|
@@ -31,20 +37,12 @@ export interface ParsedCliArgs {
|
|
|
31
37
|
failOn: FailOnMode;
|
|
32
38
|
/** Live announce-stop retries (overrides AGENT_TEST_SCENARIO_RETRIES). */
|
|
33
39
|
scenarioRetries?: number;
|
|
34
|
-
/** Offline compare subcommand (`agent-test compare --a … --b …`). */
|
|
35
|
-
compareMode: boolean;
|
|
36
|
-
compareA?: string;
|
|
37
|
-
compareB?: string;
|
|
38
|
-
/** Live/replay A:B suite dirs or report JSON paths. */
|
|
39
|
-
comparePairs?: string;
|
|
40
|
-
compareOutDir?: string;
|
|
41
40
|
}
|
|
41
|
+
/** Usage text for `--help`. */
|
|
42
|
+
export declare function formatHelp(): string;
|
|
42
43
|
/** Parse agent-test CLI argv (exported for unit tests). */
|
|
43
44
|
export declare function parseCliArgs(argv: string[]): ParsedCliArgs;
|
|
44
|
-
/**
|
|
45
|
-
* Split `--report-out` into an HTML file path and, when a directory was given,
|
|
46
|
-
* the directory every other report artifact is written to.
|
|
47
|
-
*/
|
|
45
|
+
/** Resolve an explicit report target into the HTML path and optional artifact directory. */
|
|
48
46
|
export declare function resolveReportOutput(reportOut?: string): {
|
|
49
47
|
htmlPath?: string;
|
|
50
48
|
outDir?: string;
|