openmerit 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +12 -25
- package/dist/terminal/scout-update.json +1 -1
- package/dist/terminal/src/browser.mjs +2 -4
- package/dist/terminal/src/cli.mjs +4 -56
- package/dist/terminal/src/install.mjs +2 -2
- package/dist/terminal/src/scout-pi.js +1 -1
- package/dist/terminal/src/scout.js +3 -3
- package/dist/terminal/src/telemetry.mjs +8 -60
- package/docs/agent-evaluations.md +8 -148
- package/docs/commands.md +3 -9
- package/docs/getting-started.md +2 -16
- package/docs/index.md +4 -18
- package/docs/inference-terminal.md +13 -594
- package/docs/roadmap.md +2 -2
- package/docs/scout.md +6 -2
- package/docs/security.md +5 -18
- package/docs/testing.md +4 -16
- package/docs/troubleshooting.md +2 -2
- package/package.json +10 -23
- package/dist/eval/src/adapters.mjs +0 -112
- package/dist/eval/src/cli.mjs +0 -151
- package/dist/eval/src/config.mjs +0 -108
- package/dist/eval/src/process.mjs +0 -44
- package/dist/eval/src/report.mjs +0 -59
- package/dist/eval/src/runner.mjs +0 -123
- package/dist/eval/src/scout.mjs +0 -48
- package/dist/terminal/public/app.js +0 -298
- package/dist/terminal/public/brands/anthropic.png +0 -0
- package/dist/terminal/public/brands/baai.png +0 -0
- package/dist/terminal/public/brands/baseten.png +0 -0
- package/dist/terminal/public/brands/cerebras.png +0 -0
- package/dist/terminal/public/brands/cohere.png +0 -0
- package/dist/terminal/public/brands/deepseek.ico +0 -0
- package/dist/terminal/public/brands/google.png +0 -0
- package/dist/terminal/public/brands/groq.ico +0 -0
- package/dist/terminal/public/brands/huggingface.svg +0 -8
- package/dist/terminal/public/brands/lm-studio.png +0 -0
- package/dist/terminal/public/brands/meta.ico +0 -0
- package/dist/terminal/public/brands/mistral.png +0 -0
- package/dist/terminal/public/brands/nomic.png +0 -0
- package/dist/terminal/public/brands/ollama.png +0 -0
- package/dist/terminal/public/brands/openai.png +0 -0
- package/dist/terminal/public/brands/openrouter.png +0 -0
- package/dist/terminal/public/brands/qwen.png +0 -0
- package/dist/terminal/public/brands/vllm.png +0 -0
- package/dist/terminal/public/favicon.svg +0 -1
- package/dist/terminal/public/index.html +0 -22
- package/dist/terminal/public/styles.css +0 -921
- package/dist/terminal/src/activity-merge.mjs +0 -66
- package/dist/terminal/src/collect.mjs +0 -370
- package/dist/terminal/src/coverage.mjs +0 -33
- package/dist/terminal/src/discovery.mjs +0 -99
- package/dist/terminal/src/hardware.mjs +0 -57
- package/dist/terminal/src/history.mjs +0 -32
- package/dist/terminal/src/log-continuity.mjs +0 -26
- package/dist/terminal/src/project-activity.mjs +0 -157
- package/dist/terminal/src/repository-background.mjs +0 -37
- package/dist/terminal/src/repository-index.mjs +0 -267
- package/dist/terminal/src/repository-policy.mjs +0 -3
- package/dist/terminal/src/repository-syntax.mjs +0 -236
- package/dist/terminal/src/repository-worker.mjs +0 -15
- package/dist/terminal/src/sample.mjs +0 -171
- package/dist/terminal/src/scout-credentials.d.ts +0 -12
- package/dist/terminal/src/scout-credentials.ts +0 -44
- package/dist/terminal/src/scout-instructions.d.ts +0 -5
- package/dist/terminal/src/scout-instructions.ts +0 -119
- package/dist/terminal/src/scout-pi.d.ts +0 -44
- package/dist/terminal/src/scout-pi.ts +0 -76
- package/dist/terminal/src/scout.d.ts +0 -77
- package/dist/terminal/src/scout.ts +0 -164
- package/dist/terminal/src/server.mjs +0 -95
- package/dist/terminal/src/service-registry.mjs +0 -78
- package/dist/terminal/src/services.mjs +0 -44
- package/dist/terminal/src/topology.mjs +0 -30
- package/dist/terminal/src/updates.d.ts +0 -62
- package/dist/terminal/src/updates.ts +0 -313
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0 — 2026-11-04
|
|
4
|
+
|
|
5
|
+
- **Breaking:** retire the standalone `openmerit eval` CLI, including `init`, `doctor`, `plan`, `run`, `watch` and `report`. Existing local evaluation files are not deleted. The hosted `/scout/api/recommend` retirement ships separately with the Scout serving Worker.
|
|
6
|
+
- **Breaking:** retire the local Inference Terminal. `openmerit dash` and all of its options, including `--demo`, `--json` and `--diagnostics`, are removed, along with repository indexing, request-log and activity-export import, runtime and hardware discovery, the browser interface and its opt-in terminal analytics events. Existing `.openmerit/terminal.json`, `.openmerit/inference.jsonl` and application logs are not deleted. Scout setup, `openmerit scout` and `openmerit update` are unchanged.
|
|
7
|
+
- Drop the terminal-only runtime dependencies (`@iarna/toml`, `@lezer/python`) and browser bundle dependencies.
|
|
8
|
+
|
|
3
9
|
## 0.2.0 — 2026-11-04
|
|
4
10
|
|
|
5
11
|
- Add `openmerit scout`, a conversation with Scout from the terminal: clarifying questions answered with `--brief` or `--skip`, then up to five models per task, cheapest first among models that reach Scout's quality bar. When you ask for the fastest or newest model, the output names that order and shows each model's time per task or release date. It uses this device's Claude Code or Pi key and limits new conversations to the endpoint IDs in `.openmerit/scout.json`.
|
package/README.md
CHANGED
|
@@ -1,24 +1,8 @@
|
|
|
1
1
|
# OpenMerit
|
|
2
2
|
|
|
3
|
-
OpenMerit provides
|
|
3
|
+
OpenMerit provides Scout guidance for application-model choices: in the browser, from the `openmerit scout` command, and through MCP for Claude Code and Pi.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Open the terminal
|
|
8
|
-
|
|
9
|
-
Requires Node.js 22.19 or newer and npm:
|
|
10
|
-
|
|
11
|
-
```sh
|
|
12
|
-
npm install -g openmerit
|
|
13
|
-
cd /path/to/your/application
|
|
14
|
-
openmerit dash
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
No Pi installation or provider API key is needed. The terminal opens a browser connected to a read-only loopback service. Supported source/configuration declarations establish inventory; existing application logs or exports supply request history. Prompts, responses, and credentials are not retained by terminal collection. Unsupported or missing evidence remains unknown.
|
|
18
|
-
|
|
19
|
-
The terminal follows the device's light/dark preference without a theme control. CLI and terminal product analytics are off unless explicitly enabled; see [the analytics contract](docs/inference-terminal.md#optional-cli-product-analytics).
|
|
20
|
-
|
|
21
|
-
Run `openmerit dash --demo` to explore a fictional sample workspace. See [the terminal guide](docs/inference-terminal.md) for configuration, discovery, diagnostics, history limits, and agent access.
|
|
5
|
+
Scout recommends candidates to evaluate. It is not a request router or proof of application-quality improvements.
|
|
22
6
|
|
|
23
7
|
## Connect Scout to Claude Code
|
|
24
8
|
|
|
@@ -38,17 +22,21 @@ There are no `/openmerit` lifecycle commands, evaluation setup, scheduler, Launc
|
|
|
38
22
|
|
|
39
23
|
Package publication and website deployment are separate releases. Pi setup requires OpenMerit 0.1.12 or newer; check the resolved package version when using `@latest`.
|
|
40
24
|
|
|
41
|
-
##
|
|
25
|
+
## Evaluation CLI retirement — npm 0.3.0
|
|
26
|
+
|
|
27
|
+
OpenMerit 0.3.0 removes the standalone `openmerit eval` commands, including planning. Existing local evaluation files are not deleted. The old Scout JSON recommendation API is retired in source and goes offline with a separate Scout deployment. Scout's conversational agent, MCP, coding-agent setup and catalogue publication remain available; see [retirement details](docs/agent-evaluations.md).
|
|
28
|
+
|
|
29
|
+
## Inference Terminal retirement — npm 0.3.0
|
|
42
30
|
|
|
43
|
-
|
|
31
|
+
OpenMerit 0.3.0 also removes the local Inference Terminal: `openmerit dash`, its `--demo` sample, collectors, repository index and browser interface. Existing `.openmerit/terminal.json`, `.openmerit/inference.jsonl` and application logs are not deleted. Older installed packages keep the command until they are upgraded. See [retirement details](docs/inference-terminal.md).
|
|
44
32
|
|
|
45
33
|
## Documentation
|
|
46
34
|
|
|
47
|
-
The [documentation overview](docs/index.md) links the
|
|
35
|
+
The [documentation overview](docs/index.md) links the maintained Markdown guides. The unpublished `/docs/` website shell is retired; the live Scout data policy and protected memo have separate builds.
|
|
48
36
|
|
|
49
37
|
- [Getting started](docs/getting-started.md) and [troubleshooting](docs/troubleshooting.md)
|
|
50
38
|
- [Scout](docs/scout.md) and [Pi adapter](docs/pi-extension.md)
|
|
51
|
-
- [Inference Terminal](docs/inference-terminal.md) and [agent evaluations](docs/agent-evaluations.md)
|
|
39
|
+
- Retired: [Inference Terminal](docs/inference-terminal.md) and [agent evaluations](docs/agent-evaluations.md)
|
|
52
40
|
- [Security and data handling](docs/security.md)
|
|
53
41
|
- [Testing](docs/testing.md) and [current limitations](docs/roadmap.md)
|
|
54
42
|
|
|
@@ -57,9 +45,8 @@ The [documentation overview](docs/index.md) links the current guides. The websit
|
|
|
57
45
|
```sh
|
|
58
46
|
npm ci
|
|
59
47
|
npm run verify
|
|
60
|
-
npm run dash -- /path/to/application
|
|
61
48
|
```
|
|
62
49
|
|
|
63
|
-
`packages/terminal` contains the CLI,
|
|
50
|
+
`packages/terminal` contains the `openmerit` CLI: Scout setup, updates and the `scout` command; `packages/pi` supplies only the native Scout adapter. The package exports `openmerit/pi` and the `openmerit` command. See the [Pi package README](packages/pi/README.md) for bounded adapter tests. Provider credentials belong to the harness or its environment and must never be committed.
|
|
64
51
|
|
|
65
|
-
Edit documentation in `docs/`, then run `npm run check:docs`.
|
|
52
|
+
Edit documentation in `docs/`, then run `npm run check:docs`. `npm run build:site` builds only the Scout data policy and protected memo, not a docs website. A local build does not publish changes; follow [deployment maintenance](docs/site-deployment.md) before any approved release.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"format":1,"contract":"scout-recommend-v1","version":"0.
|
|
1
|
+
{"format":1,"contract":"scout-recommend-v1","version":"0.3.0","skill":"---\nname: openmerit-scout\ndescription: Consults OpenMerit Scout before choosing, adding, downloading, replacing or configuring any application inference model, including implicit choices while building features, pretrained browser/local models, SDK defaults, embeddings, OCR, speech, classification, detection, segmentation, LLMs and agents. Not for unrelated edits, ordinary inference calls or this coding agent's own model.\n---\n\n# OpenMerit · Scout\n\nBefore introducing, recommending, replacing or configuring an application\ninference model, call the `scout_models` tool on the `openmerit` MCP server.\nThis applies even when the user never mentions models or Scout. Downloading local\nweights, using a pretrained browser model or accepting an SDK default is a model\ndecision: consult Scout before model-specific code, installs or downloads.\nPreserve the user's explicit model choice; assess it rather than silently replacing\nit. Leave unchanged, approved application selections in place.\n\n## Project policy\n\nRead `.openmerit/scout.json` before searching. If it is absent, ask once whether this\nproject uses **existing-only** (only endpoints it can already reach) or\n**existing-first** (prefer them, ask before searching the whole catalogue), and\nwhich public catalogue endpoint IDs it can access. Save the answer:\n\n```sh\nnpx -y openmerit@latest project --policy existing-only --endpoint-id <id> ...\n```\n\nNever infer access from a model name, SDK or environment-variable name. Never\nrecord credentials, private URLs, prompts or customer data. An empty inventory\nis not permission to search all models.\n\n## Searching\n\nCall `scout_models` with a non-confidential task description as `prompt` and\n`endpointIds` set to the saved inventory, including `[]` when empty. Send\nonly task requirements, never source files, secrets or real customer records.\nIf the MCP tool is unavailable, run\n`npx -y openmerit@latest scout \"<task>\" --json`; it applies the saved inventory.\n\nScout is a conversation with the agent behind openmerit.ai/scout. When\n`status` is `needs_answers`, fill in what the user or project already states,\nshow the user Scout's brief and remaining questions, and wait for their answers.\nThen call again with the returned `conversationId` and `brief` set to the\nrewritten components, or `skip: true` if the user wants Scout to assume. Never\nanswer Scout's questions with guesses. Send later refinements to the same\n`conversationId`. A call with only a `conversationId` reads an interrupted turn.\n\nWhen `status` is `recommended`, Scout has split the work into `tasks`, one\nper model, each with up to five ranked `models`; cover every task. Each\nmodel's `cost` names the `endpointId` and `providerModelId` to call.\nExisting-only never broadens. For existing-first, if no existing candidate fits a\ntask, explain the gap and ask before a new conversation without `endpointIds`.\nCompare quality evidence, reference cost/time and watch-outs. Prefer the cheapest\nusable option the evidence supports, without claiming benchmarks prove\napplication accuracy. Use the project's actual SDK and protocol.\n\n## Boundaries\n\nAsk before adding providers or credentials, spending, deploying or external\nwrites. Report recommendation, endpoint connectivity and application checks as\nseparate results, each only after it succeeds. Do not switch this coding agent's\nown model.\n\nIf Scout fails or has no suitable candidate/evidence for the required deployment,\nsay so and pause the model decision; do not substitute a remembered recommendation\nor SDK default. Continue only model-independent work. Local/browser models are not\nexempt when the catalogue lacks coverage. If it reports that the device key is missing,\nexpired or revoked, run `npx -y openmerit@latest login` and then\n`npx -y openmerit@latest install` again. Never ask the user to paste a key.\n","rule":"# Application model decisions · OpenMerit Scout\n\nBefore choosing, recommending, adding, downloading, replacing or configuring\nANY application inference model, load the `openmerit-scout` skill and consult\n`scout_models` on the `openmerit` MCP server before committing to a model.\nThis applies even when the user only asks you to build a feature, never mentions\nmodels or Scout, or names a model themselves (assess it; do not silently replace it).\n\nA pretrained model, local weights, browser inference, an SDK's default model,\nembeddings, OCR, speech, image classification, detection and segmentation all\ncount as model choices, not implementation details. Identify this decision before\nwriting model-specific code, installing a model package or downloading weights.\n\nFollow the skill's project access policy. If it is missing, ask and save it first.\nScout may answer with clarifying questions: relay them to the user and continue\nthe same Scout conversation with their answers before choosing.\nIf Scout is unavailable, fails or has no suitable evidence/candidate, disclose the\ngap and pause the model decision; do not fall back to a remembered or SDK-default\nmodel. You may continue work that does not commit to a model.\n\nDo not consult Scout for unrelated edits, normal inference calls using an unchanged\napproved model, or this coding agent's own model. Do not reselect approved models\nunless the task introduces or changes a model decision.\n\nWhen the user says \"update openmerit\", run\n`npx -y openmerit@latest update --scope user` (use `--scope project` if this\nrule is in the project's .claude/rules directory). Report the result, including\nany conflict or manual-upgrade requirement. Do not delete edited files, bypass\npermissions or rerun login automatically. A new session loads updated instructions.\n"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
const terminalURL = url => { const target = new URL(url); return target.protocol === 'http:' && target.hostname === '127.0.0.1' && /^http:\/\/127\.0\.0\.1:[0-9]+$/.test(url) && !target.username && !target.password && target.pathname === '/' && !target.search && !target.hash; };
|
|
6
|
-
export function browserCommand(url, platform = process.platform, env = process.env, allowed = terminalURL) {
|
|
3
|
+
// Callers decide which URLs may open. Never use a shell.
|
|
4
|
+
export function browserCommand(url, platform = process.platform, env = process.env, allowed) {
|
|
7
5
|
if (!allowed(url)) throw new Error('Refusing to open an unexpected URL.');
|
|
8
6
|
if (env.SSH_CONNECTION || env.SSH_TTY) return null;
|
|
9
7
|
if (platform === 'darwin') return ['open', [url]];
|
|
@@ -1,77 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { resolve } from 'node:path';
|
|
3
|
-
import { stat } from 'node:fs/promises';
|
|
4
|
-
import { startTerminal } from './server.mjs';
|
|
5
|
-
import { createCollector, loadConfig } from './collect.mjs';
|
|
6
|
-
import { sampleSnapshot } from './sample.mjs';
|
|
7
|
-
import { openBrowser } from './browser.mjs';
|
|
8
2
|
import { commandTelemetry } from './telemetry.mjs';
|
|
9
3
|
|
|
10
|
-
const help = `OpenMerit
|
|
4
|
+
const help = `OpenMerit
|
|
11
5
|
|
|
12
|
-
openmerit dash [path] [options]
|
|
13
6
|
openmerit scout --help Ask Scout which models fit your tasks
|
|
14
7
|
openmerit install --help Connect OpenMerit to your coding agent
|
|
15
8
|
openmerit update --help Update installed Scout instructions
|
|
16
|
-
openmerit
|
|
17
|
-
|
|
18
|
-
--port <number> Require a specific local port (default: 4310 or a free port)
|
|
19
|
-
--interval <seconds> Collection interval, 10–30 (default: 15)
|
|
20
|
-
--no-discovery Skip project/log discovery and extra runtime discovery
|
|
21
|
-
--no-open Print the URL without opening a browser
|
|
22
|
-
--json Print one snapshot for an agent, then exit
|
|
23
|
-
--diagnostics Print shareable index coverage counts, then exit
|
|
24
|
-
--demo Explore a clearly labeled fictional environment
|
|
25
|
-
--help Show this help
|
|
26
|
-
|
|
27
|
-
Opens your default browser after the local terminal is ready.
|
|
28
|
-
Reads application metadata and local runtime inventory. Makes no inference calls.
|
|
29
|
-
Coding-harness usage is outside this terminal's scope.
|
|
9
|
+
openmerit --help Show this help
|
|
30
10
|
`;
|
|
31
11
|
|
|
32
12
|
async function main() {
|
|
33
13
|
const args = process.argv.slice(2);
|
|
34
14
|
if (['install', 'status', 'remove', 'login', 'logout', 'project', 'doctor', 'update'].includes(args[0])) { const { main } = await import('./install.mjs'); process.exitCode = await main(args); return; }
|
|
35
15
|
if (args[0] === 'scout') { const { main } = await import('./scout.js'); process.exitCode = await main(args.slice(1)); return; }
|
|
36
|
-
if (args[0] === 'eval') { const { main } = await import('../../eval/src/cli.mjs'); await main(args.slice(1)); return; }
|
|
37
16
|
if (!args.length || args.includes('--help') || args.includes('-h')) { console.log(help); return; }
|
|
38
|
-
|
|
39
|
-
let root = process.cwd(), port = 4310, interval = 15, demo = false, json = false, pathSeen = false, discovery = true, noOpen = false, explicitPort = false, diagnostics = false;
|
|
40
|
-
for (let i = 0; i < args.length; i++) {
|
|
41
|
-
const arg = args[i];
|
|
42
|
-
if (arg === '--port' || arg === '--interval') {
|
|
43
|
-
const value = args[++i];
|
|
44
|
-
if (!/^\d+$/.test(value ?? '')) throw new Error(`${arg} requires an integer.`);
|
|
45
|
-
if (arg === '--port') { port = Number(value); explicitPort = true; } else interval = Number(value);
|
|
46
|
-
} else if (arg === '--no-open') noOpen = true;
|
|
47
|
-
else if (arg === '--no-discovery') discovery = false;
|
|
48
|
-
else if (arg === '--access' || arg === '--revoke-access') throw new Error('Coding-harness history is no longer collected. Saved history permissions are ignored; these access options have been removed.');
|
|
49
|
-
else if (arg === '--demo') demo = true;
|
|
50
|
-
else if (arg === '--json') json = true;
|
|
51
|
-
else if (arg === '--diagnostics') diagnostics = true;
|
|
52
|
-
else if (!arg.startsWith('-') && !pathSeen) { root = resolve(arg); pathSeen = true; }
|
|
53
|
-
else throw new Error(`Unknown argument: ${arg}`);
|
|
54
|
-
}
|
|
55
|
-
if (port < 1 || port > 65535) throw new Error('Port must be between 1 and 65535.');
|
|
56
|
-
if (interval < 10 || interval > 30) throw new Error('Collection interval must be between 10 and 30 seconds.');
|
|
57
|
-
if (!(await stat(root)).isDirectory()) throw new Error('Choose a project directory.');
|
|
58
|
-
const config = demo ? null : await loadConfig(root);
|
|
59
|
-
if (config && !discovery) config.discovery = false;
|
|
60
|
-
if (diagnostics) { const {indexRepository,indexDiagnostics}=await import('./repository-index.mjs'); const index = !demo && config.discovery ? await indexRepository(root) : null; console.log(JSON.stringify(indexDiagnostics(index), null, 2)); return; }
|
|
61
|
-
if (json) { console.log(JSON.stringify(demo ? sampleSnapshot() : await createCollector(root, config, interval)(), null, 2)); return; }
|
|
62
|
-
const terminal = await startTerminal({ root, port, interval, demo, config, fallbackPort: !explicitPort });
|
|
63
|
-
console.log(`\n OpenMerit · Inference Terminal\n\n ${terminal.url}\n\n ${demo ? 'Sample environment · fictional data' : 'Current project · passive collection'}\n Updates every ${interval}s. Press Ctrl+C to close.\n`);
|
|
64
|
-
const close = () => { void terminal.close().then(() => process.exit(0)); };
|
|
65
|
-
process.once('SIGINT', close); process.once('SIGTERM', close);
|
|
66
|
-
if (!demo && config.discovery) {
|
|
67
|
-
console.log(' Automatic discovery: repository code/configuration, saved request logs, and project-linked runtimes.');
|
|
68
|
-
}
|
|
69
|
-
if (!noOpen && !await openBrowser(terminal.url)) console.log(' Open the local URL above in your browser.');
|
|
17
|
+
throw new Error('Unknown command. Run openmerit --help.');
|
|
70
18
|
}
|
|
71
19
|
const completeTelemetry = commandTelemetry(process.argv.slice(2));
|
|
72
20
|
const setupCodes = { 10: 'approval_pending', 11: 'access_denied', 20: 'install_conflict', 30: 'openmerit_unreachable' };
|
|
73
21
|
main().then(() => completeTelemetry(process.exitCode ? 'error' : 'ok', undefined, setupCodes[process.exitCode]), async error => {
|
|
74
|
-
console.error(`\n ${error.
|
|
22
|
+
console.error(`\n ${error.message}\n`);
|
|
75
23
|
process.exitCode = 1;
|
|
76
24
|
await completeTelemetry('error', error);
|
|
77
25
|
});
|
|
@@ -15,13 +15,13 @@ export { rule, skill } from './scout-instructions.js';
|
|
|
15
15
|
// One-command coding-agent setup: device sign-in in the browser, then the MCP
|
|
16
16
|
// server, startup rule and Scout skill. Built to be run by a person or by a coding agent:
|
|
17
17
|
// no interactive prompts, bounded waits, resumable logins and explicit exit codes.
|
|
18
|
-
|
|
18
|
+
const exitCodes = { ok: 0, error: 1, pending: 10, denied: 11, conflict: 20, unreachable: 30 };
|
|
19
19
|
const exec = promisify(execFile);
|
|
20
20
|
const hash = value => createHash('sha256').update(value).digest('hex');
|
|
21
21
|
const policyPath = '.openmerit/scout.json';
|
|
22
22
|
const clients = { 'claude-code': 'Claude Code', pi: 'Pi' };
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
const help = `OpenMerit · coding-agent setup
|
|
25
25
|
|
|
26
26
|
openmerit install [--client claude-code|pi] [--scope user|project] [--setup-id UUID] [--auto-update on|off] [--plan] [--json] [--no-open]
|
|
27
27
|
openmerit status [--client claude-code|pi] [--scope user|project] [--check] [--json]
|
|
@@ -26,7 +26,7 @@ export function piPaths(root, scope) {
|
|
|
26
26
|
const base = scope === 'user' ? agentDir : join(root, '.pi');
|
|
27
27
|
return { skill: join(base, 'skills/openmerit-scout/SKILL.md'), rule: join(base, 'extensions/openmerit-scout.ts'),
|
|
28
28
|
connection: join(base, 'extensions/openmerit-scout.json'), record: join(base, 'openmerit-install.json'),
|
|
29
|
-
|
|
29
|
+
mcpFile: join(base, 'mcp.json'), mcpScope: scope, agentDir };
|
|
30
30
|
}
|
|
31
31
|
export async function inspectPi(root, scope) {
|
|
32
32
|
const paths = piPaths(root, scope);
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
import { readFile } from 'node:fs/promises';
|
|
6
6
|
import { join } from 'node:path';
|
|
7
7
|
import { credentialsPath, readCredentials } from "./scout-credentials.js";
|
|
8
|
-
|
|
8
|
+
const policyFile = '.openmerit/scout.json';
|
|
9
9
|
export const components = ['input', 'work', 'output', 'criteria', 'constraints'];
|
|
10
|
-
|
|
10
|
+
const help = `OpenMerit · Scout
|
|
11
11
|
|
|
12
12
|
openmerit scout "<the work models need to do>" [--all-endpoints] [--json]
|
|
13
13
|
openmerit scout --conversation <id> [--brief <component>=<text> ...] [--skip] ["<follow-up>"] [--json]
|
|
@@ -46,7 +46,7 @@ function deviceKey(root) {
|
|
|
46
46
|
return null;
|
|
47
47
|
}
|
|
48
48
|
// One turn through the scout_models MCP tool. Errors are written for the person or agent running it.
|
|
49
|
-
|
|
49
|
+
async function askScout(root, request, signal) {
|
|
50
50
|
const credentials = deviceKey(root);
|
|
51
51
|
if (!credentials)
|
|
52
52
|
throw new Error('This device is not signed in to OpenMerit. Run: npx -y openmerit@latest install');
|
|
@@ -5,12 +5,8 @@ export let clientVersion;
|
|
|
5
5
|
for (const path of ['../../../package.json', '../../../../package.json']) {
|
|
6
6
|
try { const pkg = JSON.parse(readFileSync(new URL(path, import.meta.url), 'utf8')); if (pkg.name === 'openmerit') { clientVersion = pkg.version; break; } } catch {}
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
const applicationURLs = frameFiles.
|
|
10
|
-
const diagnostics = new WeakMap();
|
|
11
|
-
export function scoutDiagnostic(error, trace, code) {
|
|
12
|
-
if (error && typeof error === 'object' && ['scout_network_error', 'scout_http_error', 'scout_response_error', 'scout_timeout'].includes(code)) diagnostics.set(error, { operation: 'scout_recommend', code, ...(typeof trace === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(trace) ? { trace_id: trace } : {}) });
|
|
13
|
-
}
|
|
8
|
+
const frameFiles = Object.freeze(['cli.mjs', 'install.mjs']);
|
|
9
|
+
const applicationURLs = frameFiles.map(file => new URL(`../../terminal/src/${file}`, import.meta.url).href);
|
|
14
10
|
export function safeFrames(error) {
|
|
15
11
|
try {
|
|
16
12
|
const stack = error?.stack;
|
|
@@ -24,7 +20,7 @@ export function safeFrames(error) {
|
|
|
24
20
|
} catch { return []; }
|
|
25
21
|
}
|
|
26
22
|
export function errorProperties(error) {
|
|
27
|
-
try { return { error_type: errorType(error), frames: safeFrames(error)
|
|
23
|
+
try { return { error_type: errorType(error), frames: safeFrames(error) }; }
|
|
28
24
|
catch { return { error_type: 'Error', frames: [] }; }
|
|
29
25
|
}
|
|
30
26
|
const environment = () => ({ ...(clientVersion ? { client_version: clientVersion } : {}), platform: ['darwin', 'linux', 'win32'].includes(process.platform) ? process.platform : 'unknown', runtime_major: Number(process.versions.node.split('.')[0]) });
|
|
@@ -99,65 +95,17 @@ export async function sendInstallationEvent(input) {
|
|
|
99
95
|
} catch { /* Never affect setup, even if the transport ignores abort. */ }
|
|
100
96
|
finally { clearTimeout(timer); }
|
|
101
97
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const out = {};
|
|
106
|
-
const select = (key, values) => { if (!values.includes(input[key])) return false; out[key] = input[key]; return true; };
|
|
107
|
-
if (event === 'terminal_error') {
|
|
108
|
-
if (!select('code', ['collection_error', 'snapshot_error', 'render_error', 'uncaught_error']) || !select('error_type', ['Error', 'TypeError', 'RangeError', 'SyntaxError', 'ReferenceError', 'URIError', 'EvalError', 'AggregateError', 'AbortError'])) return null;
|
|
109
|
-
if (Array.isArray(input.frames)) out.frames = input.frames.slice(0, 8).filter(f => f && frameFiles.includes(f.filename) && Number.isInteger(f.lineno) && f.lineno > 0 && f.lineno <= 1000000 && Number.isInteger(f.colno) && f.colno > 0 && f.colno <= 1000000).map(f => ({ filename: f.filename, lineno: f.lineno, colno: f.colno }));
|
|
110
|
-
return out;
|
|
111
|
-
}
|
|
112
|
-
if (!select('mode', ['sample', 'live'])) return null;
|
|
113
|
-
if (event === 'terminal_visited') return out;
|
|
114
|
-
if (event === 'terminal_page_viewed') return select('page', ['overview', 'models', 'services', 'activity', 'compute', 'sources', 'connections']) ? out : null;
|
|
115
|
-
if (event === 'terminal_interaction') return select('action', ['inspect', 'filter', 'search', 'map_expand', 'mode', 'command']) && select('kind', ['model', 'agent', 'task', 'service', 'source', 'host', 'deployment', 'pool', 'record', 'path', 'other']) ? out : null;
|
|
116
|
-
if (event !== 'terminal_snapshot') return null;
|
|
117
|
-
for (const key of ['model_count', 'record_count', 'source_count', 'host_count', 'deployment_count', 'agent_count']) {
|
|
118
|
-
if (!Number.isInteger(input[key]) || input[key] < 0 || input[key] > 1000000000) return null;
|
|
119
|
-
out[key] = input[key];
|
|
120
|
-
}
|
|
121
|
-
return out;
|
|
122
|
-
}
|
|
123
|
-
// Shared, process-wide budget; no queue and at most four in-flight requests.
|
|
124
|
-
let windowStart = 0, count = 0, active = 0;
|
|
125
|
-
export function sendTerminalEvent(event, input) {
|
|
126
|
-
if (!telemetryEnabled()) return;
|
|
127
|
-
const properties = terminalProperties(event, input);
|
|
128
|
-
if (!properties) return;
|
|
129
|
-
if (Date.now() - windowStart >= 60000) { windowStart = Date.now(); count = 0; }
|
|
130
|
-
if (count >= 60 || active >= 4) return;
|
|
131
|
-
count++; active++;
|
|
132
|
-
void sendAnalytics(event, properties).finally(() => active--);
|
|
133
|
-
}
|
|
134
|
-
async function sendAnalytics(event, properties) {
|
|
135
|
-
const controller = new AbortController();
|
|
136
|
-
const body = JSON.stringify({ event, event_id: randomUUID(), anonymousId, properties: { ...properties, ...environment() } });
|
|
137
|
-
let timer;
|
|
138
|
-
try {
|
|
139
|
-
await Promise.race([
|
|
140
|
-
Promise.resolve().then(() => fetch('https://openmerit.ai/scout/api/analytics', {
|
|
141
|
-
method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Scout-Client': 'cli', 'X-Scout-Analytics': 'on', ...(process.env.OPENMERIT_ANALYTICS_ACCOUNT === 'off' ? { 'X-Scout-Analytics-Account': 'off' } : {}) },
|
|
142
|
-
body, signal: controller.signal, redirect: 'error',
|
|
143
|
-
})).then(response => response.body?.cancel()),
|
|
144
|
-
new Promise(resolve => { timer = setTimeout(() => { controller.abort(); resolve(); }, 750); timer.unref(); }),
|
|
145
|
-
]);
|
|
146
|
-
} catch { /* Never affect product behavior. */ }
|
|
147
|
-
finally { clearTimeout(timer); }
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Consent is independent of terminal discovery. Command identity is ephemeral;
|
|
151
|
-
// the installer separately manages the owned installation's correlation IDs.
|
|
98
|
+
const errorType = error => ['Error', 'TypeError', 'RangeError', 'SyntaxError', 'ReferenceError', 'URIError', 'EvalError', 'AggregateError', 'AbortError'].includes(error?.name) ? error.name : 'Error';
|
|
99
|
+
// Command identity is ephemeral; the installer separately manages the owned
|
|
100
|
+
// installation's correlation IDs.
|
|
152
101
|
export function commandTelemetry(args) {
|
|
153
102
|
const setup = ['install', 'status', 'remove', 'login', 'logout', 'project', 'doctor'];
|
|
154
103
|
const enabled = () => telemetryEnabled(setup.includes(args[0]));
|
|
155
104
|
if (!enabled()) return async () => {};
|
|
156
105
|
const started = performance.now();
|
|
157
106
|
const command_id = randomUUID();
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
? 'help' : args[0] === 'dash' ? 'dash' : setup.includes(args[0]) ? args[0] : args[0] === 'eval' && actions.includes(args[1]) ? `eval_${args[1]}` : 'unknown';
|
|
107
|
+
const command = !args.length || args.includes('--help') || args.includes('-h')
|
|
108
|
+
? 'help' : setup.includes(args[0]) ? args[0] : 'unknown';
|
|
161
109
|
async function send(event, properties) {
|
|
162
110
|
if (!enabled()) return;
|
|
163
111
|
const controller = new AbortController();
|
|
@@ -1,155 +1,15 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Agent-evaluation CLI retirement
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**npm 0.3.0, 4 November 2026.** The standalone `openmerit eval` CLI is retired in full, including `init`, `doctor`, `plan`, `run`, `watch` and `report`. Older installed packages keep it until they are upgraded. The old Scout JSON recommendation API is retired in unreleased source and goes offline only with a separate Scout deployment.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
After an approved Scout release, `/scout/api/recommend` and its legacy alpha/versioned paths return 404, regardless of authentication. There is no replacement frozen-plan protocol. Use the [Scout conversational agent or MCP](scout.md) for provisional model guidance and your own representative task checks for evaluation. The Inference Terminal is [retired as well](inference-terminal.md); the Pi adapter remains a native Scout MCP integration, not an evaluation runner.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Existing local artifacts
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Upgrading does not delete `.openmerit/eval.json`, reports, budget ledgers, task fixtures or grader files. Review and retain or remove them yourself. Stop any old foreground watcher before upgrading. Instructions previously appended to `AGENTS.md` or `CLAUDE.md` are not automatically rewritten; remove obsolete evaluation instructions deliberately, preserving unrelated project guidance.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Historical reports remain evidence only for the versions and tasks actually tested. Unknown costs do not become known, and past budget reservations are not reconciled provider bills. Retirement does not cancel external agent/provider work, erase historical Scout analytics, change provider retention or enforce billing limits.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## Preserved capabilities
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Scout planning requests carry `X-Scout-Client: cli` and `X-Scout-Analytics: off` unless explicitly opted in without Do Not Track. They always include `X-Scout-Analytics-Content: off`, so task descriptions required for planning are not opted into richer product-analytics content collection even when command analytics is enabled. The server owns search-completion counts; the CLI does not emit another search event. This opt-out affects optional PostHog product events, not task processing or historical private Cloudflare prompt records. Planning still sends the task descriptions and model scope required by its protocol. Evaluation planning requires a current Clerk session token; the separate device key from coding-agent setup grants MCP recommendations only, not JSON API access.
|
|
18
|
-
|
|
19
|
-
## Set up
|
|
20
|
-
|
|
21
|
-
Install the stable release and initialize it inside the project you want to evaluate:
|
|
22
|
-
|
|
23
|
-
```sh
|
|
24
|
-
npm install -g openmerit@latest
|
|
25
|
-
openmerit eval init
|
|
26
|
-
openmerit eval doctor
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
Init creates `.openmerit/eval.json`, a tiny extraction fixture, a tool and a standalone grader. It appends marked instructions to `AGENTS.md` and `CLAUDE.md`, preserving existing contents. Codex/OpenCode can read `AGENTS.md`; Claude Code reads `CLAUDE.md`. The instructions ask the agent to configure representative tasks, choose scope, obtain the user's budget, and rerun after CLI changes. These are instructions the host must follow, not guaranteed hooks. There are no install-time hooks or background services. A second init refuses to overwrite the suite.
|
|
30
|
-
|
|
31
|
-
Replace the starter before drawing product conclusions. Have your agent author representative fixtures and graders with you, and reserve fresh cases for final validation.
|
|
32
|
-
|
|
33
|
-
## Choose scope and connections
|
|
34
|
-
|
|
35
|
-
```sh
|
|
36
|
-
openmerit eval plan
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
The first interactive plan asks: **existing project connections or all models Scout indexes?** It then asks for a **$10, custom or no-fixed-cap budget**. Both choices are saved. Noninteractive agents must ask the user and pass `--scope existing` or `--scope all` together with `--budget <USD|unlimited>` on first setup; missing input never chooses scope or spending automatically.
|
|
40
|
-
|
|
41
|
-
Add explicit routes to `connections` in the config, for example:
|
|
42
|
-
|
|
43
|
-
```json
|
|
44
|
-
{
|
|
45
|
-
"id": "claude-project",
|
|
46
|
-
"agent": "claude",
|
|
47
|
-
"scoutId": "anthropic/claude-haiku-4.5",
|
|
48
|
-
"model": "claude-haiku-4-5-20251001",
|
|
49
|
-
"env": ["ANTHROPIC_API_KEY"]
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
`scoutId` is Scout's catalogue ID. `model` is the native identifier your authenticated agent accepts. `command` optionally selects another executable path. `env` lists environment variable **names**, never values. Only basic OS variables and explicitly listed names pass to child agents. Saved authentication remains available through the normal home directory. No dotenv files are loaded automatically. Configure endpoint details through the native agent or named environment variables.
|
|
54
|
-
|
|
55
|
-
An SDK dependency or key-variable name does not prove access. The agent should inspect the project's intended connections and declare the models they can serve. This preview does not automatically enumerate endpoint catalogues. Multiple connections can test one Scout model through different agents/routes. Prefer pinned model versions; aliases can change.
|
|
56
|
-
|
|
57
|
-
Existing scope sends IDs and requires Scout to acknowledge filtering **before ranking five**. Fewer than five eligible models remain fewer. All scope searches the index, but missing authenticated routes block execution until configured and replanned. Inaccessible candidates are not silently replaced. Unranked Hugging Face specialists are not executed automatically.
|
|
58
|
-
|
|
59
|
-
Scout receives only each task's `description`, plus IDs for existing scope. Scout sends descriptions to OpenAI Decisions. Fixtures, execution prompts, endpoint URLs and credentials stay out of this request. The shortlist, warnings and ranking context are frozen locally. Scout scores are screening evidence, not measured success with your harness.
|
|
60
|
-
|
|
61
|
-
## Tasks and variants
|
|
62
|
-
|
|
63
|
-
Each task needs `id`, `description` (for Scout, at most 4,000 characters), `prompt` (for execution), `fixture` (a project-relative directory) and `grader` (a standalone Node `.mjs` file).
|
|
64
|
-
|
|
65
|
-
Each variant needs `id`, `files` and `instructions`. The starter compares `bare` against `cli`. Bare omits your CLI/docs; native agent tools remain available. Across agents you are comparing different harnesses, with different permission systems. A no-native-tools experiment needs a separately controlled configuration.
|
|
66
|
-
|
|
67
|
-
Selected files, including uncommitted changes, are snapshotted before execution. Variant paths must not overwrite fixture inputs and retain their project-relative locations; fixture contents go at the workspace root. Include self-contained CLI artifacts and lean docs explicitly. Dependencies are not installed automatically; tools must be bundled or have their runtime requirements already available. Symlinks, parent-directory paths, `.env*`, `.git`, `.openmerit` and `node_modules` are rejected. Each selected snapshot is limited to 25 MB. Do not select credentials stored under other filenames.
|
|
68
|
-
|
|
69
|
-
The grader reads `{ "workspace": "/temporary/path", "output": "final response" }` from stdin and prints exactly `{ "quality": 0.0 }`, with a finite score from 0 to 1. It can check generated files using executable assertions. Keep it self-contained: imports beside it are not copied automatically. Graders are copied outside agent workspaces; never also include them or answer keys in fixtures/variant files. Test graders against correct and incorrect answers. A broken grader stops the experiment with unknown quality. Ordinary agent failures/timeouts count as quality zero; recognized budget, environment and connection blocks instead stop with unknown quality. See [failure classification](#accounting-and-blocked-executions).
|
|
70
|
-
|
|
71
|
-
## Run after changes
|
|
72
|
-
|
|
73
|
-
The starter's `budget.maxUsd` is zero. After the user's scope and budget choices, for example:
|
|
74
|
-
|
|
75
|
-
```sh
|
|
76
|
-
openmerit eval plan --scope existing --budget 10
|
|
77
|
-
openmerit eval run
|
|
78
|
-
# Edit your CLI or its documentation.
|
|
79
|
-
openmerit eval run
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
For repeated local development:
|
|
83
|
-
|
|
84
|
-
```sh
|
|
85
|
-
openmerit eval watch
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
Watch runs initially, then after selected source/docs/fixture/grader/config bytes change and remain stable for two polls. Result writes do not trigger it. Runs never overlap; edits during execution become the next revision. Ctrl+C stops the watcher and active child process. No OS schedule or daemon is installed. `OPENMERIT_EVAL=1` tells cooperating agent instructions not to recurse into another evaluation.
|
|
89
|
-
|
|
90
|
-
Every attempt uses a new workspace and agent session. Each task runs balanced rounds across all selected connections and variants; order rotates and reverses. The default is 3–10 repetitions. After three, rounds continue while any group's quality range exceeds 5 percentage points, an attempt failed, or cost, input-token or latency variation has a coefficient of variation above 0.25. Ten is the maximum. Missing metrics cannot establish stability. Set `repeats.min` equal to `repeats.max` for fixed repetitions, useful for holdouts. This heuristic is not a significance test, and repetition is not task diversity.
|
|
91
|
-
|
|
92
|
-
The frozen plan survives CLI changes. Changes to descriptions, scope or connections require replanning. Previous-revision comparisons require matching prompts, fixtures, graders, routes, repeat settings, selected candidates, variant IDs, timeouts, agent versions, runner versions, invocation settings and reported model identities. CLI/docs bytes and variant instructions are the interventions. Keep external services and native agent settings stable too; they are not hermetically captured.
|
|
93
|
-
|
|
94
|
-
## Metrics
|
|
95
|
-
|
|
96
|
-
```sh
|
|
97
|
-
openmerit eval report
|
|
98
|
-
openmerit eval report --json
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
Reports show quality mean/range, failures, mean input/output tokens, mean reported dollars and median full-process seconds per task/connection/variant. They retain Scout ranks but do not force a weighted winner. Lower cost with lower quality is a tradeoff. Matching complete revisions show deltas; partial/invalid experiments do not.
|
|
102
|
-
|
|
103
|
-
Claude provides aggregate and per-model usage and cost estimates, reconciled without counting the same usage twice. Codex JSON events provide tokens but not billed dollars, so cost stays unknown. OpenCode per-step usage/cost is summed across the episode, including tools; missing or zero step pricing leaves full cost unknown and preserves partial estimates. Input totals include separately reported cache reads/writes; cached tokens are retained separately without counting them twice. OpenCode output totals include separately reported reasoning tokens. Agent accounting and subscriptions differ. Reported costs are not reconciled provider bills; zero pricing is treated as unknown. Catalogue prices never replace unknown measured costs.
|
|
104
|
-
|
|
105
|
-
Preflight requires supported noninteractive JSON interfaces: Claude print JSON, Codex `exec --json --ephemeral --sandbox workspace-write`, and OpenCode `run --format json --auto`. OpenCode's auto option approves tool requests that are not explicitly denied, avoiding an interactive approval stall. Claude uses an explicit local tool allowlist without inherited MCP configuration; Codex and OpenCode retain native global settings. Recognized permission failures stop as connection problems, not model-quality evidence. OpenMerit does not add a sandbox around Claude/OpenCode. The old 2025 Codex CLI is unsupported. Native references: [Claude Code](https://code.claude.com/docs/en/headless), [Codex](https://developers.openai.com/codex/noninteractive), [OpenCode](https://opencode.ai/docs/cli/).
|
|
106
|
-
|
|
107
|
-
## Budget and data
|
|
108
|
-
|
|
109
|
-
`budget.maxUsd` applies cumulatively across runs and restarts. Before each attempt the runner persists a reservation. It retains the greater of that reservation and the available full or partial cost estimate; estimates never release reserved allowance. Partial events never count as a complete bill. Insufficient remaining allowance stops a partial run. Raising maxUsd extends the allowance, not resets it. Do not delete unknown spend from the ledger. This is admission control, not a billing cutoff: one attempt may exceed its reservation. Finite budgets also use Claude's native maximum-budget flag. Use provider-side limits for hard monetary caps. Each attempt also has a timeout and 4 MB process-output limit. See [budget selection](#budget-selection) for the three choices and automatic reservations.
|
|
110
|
-
|
|
111
|
-
`.openmerit/eval/` holds `plan.json`, `budget.json`, `latest.json`, `runs/*.json` and `lock/pid`. Init ignores it in Git. Reports contain identities, metrics, hashes and status, not full transcripts or final outputs. Temporary files are removed afterward. Native agents/providers may retain their own data; Claude/Codex receive ephemeral flags, while OpenCode uses native storage. `.openmerit/eval.json` can be versioned without credentials.
|
|
112
|
-
|
|
113
|
-
Fresh workspaces are not security sandboxes. Trusted agents and graders execute with native permissions and user-level resources. Hard kills may leave temporary directories. After a crash, inspect the lock's PID and remove it only if that process is gone. This preview does not change Pi approvals, swap production models or upload results into Scout rankings.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
## VM acceptance limits
|
|
117
|
-
|
|
118
|
-
The published `0.1.7-preview.1` package was tested on an Ubuntu ARM64 VM with Node 22.23.1 on 15 October 2026. Claude Code 2.1.300 and OpenCode 1.19.0 executed a small CSV CLI task before and after a parser change. A separate OpenCode watcher completed three attempts per revision and emitted comparison deltas. Codex 0.162.1 passed interface preflight but could not execute filesystem tools because that VM denied the required Linux user namespaces. CLI flag checks do not establish that the native sandbox works on a host.
|
|
119
|
-
|
|
120
|
-
In that earlier `0.1.7-preview.1` test, a native budget stop could appear as a generic agent failure, and a successful final response explaining a host permission problem could receive zero from the task grader. These did not establish poor model quality; the corrections below address recognized native failures. The combined VM run also stopped before its final repetition because conservative reservations and agent cost estimates exhausted its local allowance; partial reports correctly omitted automatic comparison. Agent-reported cost differed substantially from OpenRouter account usage. This was one integration fixture, not validation of general task quality, exact model order, or billing accuracy.
|
|
121
|
-
|
|
122
|
-
## Accounting and blocked executions
|
|
123
|
-
|
|
124
|
-
Since `0.1.7-preview.2`, recognized budget, sandbox, permission, authentication and model-access blocks are separate from task failures. A blocked attempt has `quality: null`, stops the run and cannot produce a revision comparison. Reports distinguish scored attempts, blocked attempts and task-check failures. Ordinary wrong outputs still receive their grader score; ordinary agent failures and configured timeouts still count as failures. Cancellation, a missing executable and output-limit interruption are unscored. Error classification uses native failure fields and failed-tool diagnostics, not arbitrary task text or model commentary. Unrecognized host failures can still require manual review.
|
|
125
|
-
|
|
126
|
-
On Linux, Codex preflight also runs a local sandbox probe before any model request or budget reservation. It uses the configured executable and the workspace-write policy; it does not weaken sandbox permissions. A failed probe produces `environment_blocked` with no task score. Doctor performs this same probe. Other operating systems still have interface checks only.
|
|
127
|
-
|
|
128
|
-
Claude's per-model totals recover usage omitted from aggregate budget-stop responses, without adding the same aggregate and model counters twice. Costs carry `costBasis` and remain native estimates. Zero or missing pricing is unknown; incomplete OpenCode step pricing stays partial. Partial costs survive into the row, summary and ledger, including failed attempts. No provider bill is reconstructed from these estimates, and no account-wide spend delta is assigned to individual attempts.
|
|
129
|
-
|
|
130
|
-
Budget admission now retains the greater of each reservation and its available full or partial estimate, including old ledger entries. Estimates never release a reservation. This may exhaust an existing allowance earlier; increasing it requires an explicit budget decision. The displayed reserved allowance is not billed spend, and a provider-side limit is still needed for a hard cap. Report version 2 prevents comparisons with the earlier accounting rules. There is no new provider integration, proxy, background service or model-specific rule.
|
|
131
|
-
|
|
132
|
-
## Budget selection
|
|
133
|
-
|
|
134
|
-
After choosing existing connections or all indexed models, the first interactive `eval plan` asks:
|
|
135
|
-
|
|
136
|
-
1. **$10** — a cumulative evaluation allowance for this project.
|
|
137
|
-
2. **Custom amount** — asks how much in USD.
|
|
138
|
-
3. **No fixed cap** — run the configured suite without a monetary admission limit.
|
|
139
|
-
|
|
140
|
-
Nothing is preselected. Blank, invalid or cancelled input cannot enable spending. Init still starts at zero. Newly generated project instructions tell coding agents to ask the same follow-up and pass the answer explicitly, for example:
|
|
141
|
-
|
|
142
|
-
```sh
|
|
143
|
-
openmerit eval plan --scope existing --budget 10
|
|
144
|
-
# Alternatives after the user's choice:
|
|
145
|
-
openmerit eval plan --budget 25.50
|
|
146
|
-
openmerit eval plan --budget unlimited
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
`--budget` belongs to `plan`, accepts positive USD amounts with at most two decimal places or the exact word `unlimited`, and never starts evaluation by itself. Noninteractive planning requires explicit flags when scope or budget has not been chosen. Existing positive budgets are reused. The choices are saved even if Scout subsequently fails, so a retry does not ask again. Init does not rewrite instructions in already-initialized projects; an agent in such a project can use these flags directly.
|
|
150
|
-
|
|
151
|
-
The allowance is cumulative across runs, watched edits, restarts and replanning. Changing from $10 to $20 raises the total allowance to $20; it does not add $20 or erase earlier reservations. Changing to or from no fixed cap also preserves the ledger. A normal `eval plan` reuses the saved choice. To change it, pass a new `--budget` value; setting `budget.maxUsd` back to zero in the config disables paid execution and prompts again on the next interactive plan.
|
|
152
|
-
|
|
153
|
-
Reservations are internal. New suites and budget choices use `reservationUsd: "auto"`: the smaller of $0.25 and the total allowance divided across the minimum planned attempts (tasks × selected connections × variants × minimum repetitions). No fixed cap uses $0.25 for ledger bookkeeping. This is a conservative starting allowance, not a prediction of an attempt's price or a guarantee the suite will finish. Higher reported charges still consume more allowance. Existing explicitly configured numeric reservations remain supported. Finite budgets retain Claude's native per-attempt budget flag; as before, an attempt can exceed its reservation, and provider limits are needed for a hard billing cap.
|
|
154
|
-
|
|
155
|
-
No fixed cap is stored explicitly as `budget.maxUsd: "unlimited"`; missing, null or invalid values never mean unlimited. It also removes Claude's per-attempt dollar limit, while keeping the same task count, 3–10 repetition bounds, timeouts and native permissions. Provider/account limits still apply. Usage and cost estimates remain recorded. `eval watch` can incur further charges after each selected change until stopped; Ctrl+C stops it and the active attempt. No background service or automatic production model change is added.
|
|
15
|
+
Scout's agent, MCP, coding-agent setup, catalogue refresh/publication, status and account/privacy controls remain. Shared evidence preparation and model projections remain available to those consumers. See [commands](commands.md), [security](security.md) and [testing](testing.md) for the remaining interfaces and verification boundary.
|
package/docs/commands.md
CHANGED
|
@@ -2,14 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
**Pi adapter — npm 0.1.12 and later:** Pi 1.5.0 uses only native Scout MCP and shared guidance. Run `npx -y openmerit@latest install --client pi [--scope user|project]` and approve in the browser. Shell `login`, `logout`, `status`, `remove`, and `doctor` accept the same target flags. Updates require explicit reinstall; no Pi update hooks or scheduler are installed. See [Pi setup](pi-extension.md).
|
|
4
4
|
|
|
5
|
-
The
|
|
5
|
+
The Pi 0.87 `/openmerit` slash commands were removed with that adapter and have no replacement.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**Retired in npm 0.3.0:** `openmerit dash` ([details](inference-terminal.md)) and all `openmerit eval` commands, including `plan`. Existing local files are untouched. Unreleased Scout source also retires `/scout/api/recommend`; use Scout's conversational agent or MCP. Hosted Workers change only through separate approved deployments. See [retirement details](agent-evaluations.md).
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
## Inference Terminal
|
|
12
|
-
|
|
13
|
-
Install with `npm install -g openmerit` to use `openmerit dash [path]` for a passive local view of models, connections, usage, and compute. From this checkout, use `npm run dash -- [path]`. It is independent of Pi setup and does not run model comparisons or inference.
|
|
14
|
-
|
|
15
|
-
See the [Inference Terminal guide](inference-terminal.md) for local installation, automatic discovery, `--no-discovery`, `--json`, `--demo`, collection intervals, and data limitations. Discovery is part of `dash` and is scoped to application evidence. Coding-harness histories are not collected.
|
|
9
|
+
The [Scout setup commands](scout.md#commands) remain available, beginning with `npx -y openmerit@latest install --client claude-code`.
|
package/docs/getting-started.md
CHANGED
|
@@ -1,20 +1,6 @@
|
|
|
1
1
|
# Getting started
|
|
2
2
|
|
|
3
|
-
OpenMerit provides
|
|
4
|
-
|
|
5
|
-
## Open your inference environment
|
|
6
|
-
|
|
7
|
-
With Node.js 22.19 or newer and npm installed, run:
|
|
8
|
-
|
|
9
|
-
```sh
|
|
10
|
-
npm install -g openmerit
|
|
11
|
-
cd /path/to/your/application
|
|
12
|
-
openmerit dash
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
The Inference Terminal opens a local, read-only view of the selected application's services, models, recorded requests, and linked compute. It does not require Pi or a provider API key, make inference calls, or change model assignments. Supported code/configuration declarations identify inventory; request history requires existing supported logs or exports. See [the terminal guide](inference-terminal.md) for collection, privacy, configuration, and diagnostics.
|
|
16
|
-
|
|
17
|
-
To inspect fictional data, run `openmerit dash --demo` or choose the sample from the environment selector. Sample data never enters the real snapshot or project files.
|
|
3
|
+
OpenMerit provides Scout model-selection guidance. The Inference Terminal (`openmerit dash`) is [retired in npm 0.3.0](inference-terminal.md). Pi Scout setup requires OpenMerit **0.1.12** or newer and Pi **1.5.0**. Package publication and website deployment are independent releases.
|
|
18
4
|
|
|
19
5
|
## Connect Scout to a coding agent
|
|
20
6
|
|
|
@@ -48,4 +34,4 @@ See [the Pi extension guide](pi-extension.md) for installed paths, migration fro
|
|
|
48
34
|
|
|
49
35
|
## Evaluate application changes
|
|
50
36
|
|
|
51
|
-
The standalone
|
|
37
|
+
The standalone evaluation CLI is retired in npm 0.3.0, and the legacy JSON recommendation API in unreleased Scout source. Scout guidance is not measured application quality; use your own task checks and provider budget controls. See [retirement details](agent-evaluations.md).
|