model-orchestrator 0.1.34 → 1.0.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/AGENTS.md +31 -21
- package/CHANGELOG.md +51 -1
- package/README.md +127 -110
- package/bin/README.md +57 -6
- package/bin/aunx.js +7 -0
- package/bin/cli-run.mjs +21 -15
- package/bin/cli.js +376 -257
- package/docs/README.md +15 -18
- package/docs/catalog.md +228 -38
- package/docs/companions.md +28 -10
- package/docs/guarantees.md +21 -12
- package/docs/how-it-routes.md +49 -42
- package/docs/install.md +135 -33
- package/docs/part-1-beginner.md +37 -45
- package/docs/part-2-intermediate.md +34 -52
- package/docs/part-3-advanced.md +36 -26
- package/docs/security-review-history.md +38 -0
- package/llms.txt +24 -25
- package/package.json +16 -8
- package/proof/README.md +100 -0
- package/proof/gate-demo.cast +9 -0
- package/proof/gate-demo.gif +0 -0
- package/proof/results.json +198 -0
- package/proof/scripts/check-gate.js +26 -0
- package/proof/scripts/install-time.js +16 -0
- package/proof/scripts/lib.js +73 -0
- package/proof/scripts/measure.js +15 -0
- package/proof/scripts/missing-results.js +30 -0
- package/proof/scripts/record-gate.js +38 -0
- package/proof/scripts/render.js +18 -0
- package/proof/scripts/runner-overhead.js +21 -0
- package/src/README.md +9 -3
- package/src/activation-ownership.js +19 -0
- package/src/apply-companions.js +104 -0
- package/src/apply-snippets.js +60 -28
- package/src/aunx.js +262 -0
- package/src/catalog.js +253 -117
- package/src/install.js +478 -209
- package/src/plugin.js +13 -4
- package/src/postinstall.js +57 -0
- package/src/roles.js +184 -0
- package/src/uninstall.js +125 -8
- package/templates/README.md +19 -2
- package/templates/advanced/README.md +2 -2
- package/templates/advanced/vm/PRIVACY_GATES.md +17 -19
- package/templates/advanced/vm/README.md +25 -20
- package/templates/advanced/vm/box-CLAUDE.md +19 -18
- package/templates/advanced/vm/jobs/README.md +3 -1
- package/templates/advanced/vm/jobs/weekly-audit.service +3 -0
- package/templates/advanced/vm/jobs/weekly-audit.sh +2 -2
- package/templates/advanced/vm/setup-vm.sh +49 -2
- package/templates/agents/README.md +2 -2
- package/templates/agents/agy/README.md +20 -3
- package/templates/agents/agy/builder.md +11 -7
- package/templates/agents/agy/bulk-worker.md +9 -7
- package/templates/agents/agy/code-reviewer.md +13 -7
- package/templates/agents/agy/deep-planner.md +10 -7
- package/templates/agents/agy/done-verifier.md +13 -22
- package/templates/agents/agy/finding-verifier.md +14 -22
- package/templates/agents/agy/live-researcher.md +10 -7
- package/templates/agents/agy/reader.md +10 -12
- package/templates/agents/claude-code/README.md +18 -14
- package/templates/agents/claude-code/builder.md +10 -15
- package/templates/agents/claude-code/bulk-worker.md +8 -10
- package/templates/agents/claude-code/code-reviewer.md +11 -17
- package/templates/agents/claude-code/deep-planner.md +9 -11
- package/templates/agents/claude-code/done-verifier.md +12 -33
- package/templates/agents/claude-code/finding-verifier.md +13 -39
- package/templates/agents/claude-code/live-researcher.md +9 -11
- package/templates/agents/claude-code/reader.md +9 -18
- package/templates/agents/snippets/chat.md +9 -10
- package/templates/agents/snippets/claude-code.md +17 -18
- package/templates/agents/snippets/generic.md +9 -11
- package/templates/agents/snippets/route-gate.mjs +2 -2
- package/templates/agents/snippets/route-metrics.mjs +1 -1
- package/templates/agents/snippets/subagent-context.mjs +4 -4
- package/templates/beginner/ORCHESTRATOR.md +31 -36
- package/templates/beginner/README.md +1 -1
- package/templates/common/ACCEPTANCE_CHECKS.json +12 -0
- package/templates/common/CONTEXT.md +37 -0
- package/templates/common/DECISIONS.md +11 -0
- package/templates/common/README.md +24 -11
- package/templates/common/TASK_BRIEF.md +84 -0
- package/templates/common/protocols/README.md +14 -11
- package/templates/common/protocols/acceptance-checks.md +14 -0
- package/templates/common/protocols/build-protocol.md +91 -106
- package/templates/common/protocols/context-file.md +10 -0
- package/templates/common/protocols/decision-log.md +9 -0
- package/templates/common/protocols/deep-research.md +20 -34
- package/templates/common/protocols/docs-then-prove.md +13 -18
- package/templates/common/protocols/gap-analysis.md +15 -21
- package/templates/common/protocols/memory-and-record.md +21 -20
- package/templates/common/protocols/numbers-and-logic.md +20 -26
- package/templates/common/protocols/propagate.md +18 -27
- package/templates/intermediate/CLI-RUN.md +83 -113
- package/templates/intermediate/DELEGATION_MATRIX.md +9 -3
- package/templates/intermediate/README.md +3 -3
- package/templates/intermediate/RESEARCH_TRIAGE.md +23 -15
- package/templates/intermediate/ROUTING.md +54 -51
- package/templates/intermediate/TIERS.md +37 -76
- package/templates/tools/README.md +1 -1
- package/templates/tools/obsidian-tc/OBSIDIAN-TC.md +1 -1
- package/docs/audit-brief.md +0 -148
- package/scripts/README.md +0 -7
- package/scripts/gen-catalog.js +0 -81
- package/scripts/gen-plugin.js +0 -16
- package/scripts/record-demo.sh +0 -45
- package/templates/common/TASK_BUNDLE.md +0 -56
package/bin/README.md
CHANGED
|
@@ -1,10 +1,61 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Commands and lane runner
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Plain Node executables with zero runtime dependencies.
|
|
4
4
|
|
|
5
|
-
| File | What it
|
|
5
|
+
| File | Command | What it gives you |
|
|
6
6
|
|---|---|---|
|
|
7
|
-
| `cli.js` |
|
|
8
|
-
| `
|
|
7
|
+
| `cli.js` | `npx model-orchestrator` | Select a setup and write routing files; print third-party setup commands for you to run |
|
|
8
|
+
| `aunx.js` | `aunx` | Run the installer, dispatch the lane runner, scaffold briefs and checks, summarize metrics or suggest a route |
|
|
9
|
+
| `cli-run.mjs` | `aunx cli-run` | Call an agent CLI and return nonzero when it produces no accepted result |
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
## Lane runner (`aunx cli-run`)
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
aunx cli-run --doctor
|
|
15
|
+
aunx cli-run codex --brief TASK_BRIEF.md --effort high
|
|
16
|
+
# Direct equivalents from the installed rules folder:
|
|
17
|
+
node bin/cli-run.mjs --doctor
|
|
18
|
+
node bin/cli-run.mjs codex --brief TASK_BRIEF.md --effort high
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`aunx` uses the packaged runner by default. Pass `--dir PATH` to use that project's own installed runner under `PATH/bin/`; `aunx` then prints the runner path it is using on stderr. When `--dir` names a folder with no runner, the packaged copy runs instead. Arguments and exit status pass through. `--doctor --run` performs live checks using your own vendor sign-ins and quota.
|
|
22
|
+
|
|
23
|
+
| Exit | Meaning |
|
|
24
|
+
|---|---|
|
|
25
|
+
| 0 | Accepted result |
|
|
26
|
+
| 2 | Invalid usage |
|
|
27
|
+
| 10 | Empty result or unmet output contract |
|
|
28
|
+
| 11 | No output |
|
|
29
|
+
| 12 | Timeout |
|
|
30
|
+
| 13 | Unavailable tool |
|
|
31
|
+
| 14 | Authentication failure |
|
|
32
|
+
| 15 | Quota exhausted |
|
|
33
|
+
| 16 | Request rejected |
|
|
34
|
+
| 17 | Required tool action refused |
|
|
35
|
+
| 18 | Run cut short |
|
|
36
|
+
| 130 / 143 | Interrupted by a signal on POSIX |
|
|
37
|
+
|
|
38
|
+
The local log records requested model and effort, their source, fixed result classes and the vendor exit code. Its existing schema is preserved. It stores no prompt text or provider-supplied failure text.
|
|
39
|
+
|
|
40
|
+
`cli-run.mjs` exports its output judges so `test/judges.test.js` can prove each rejects the failure shapes it exists to catch. Tests use fixture output and stub CLIs.
|
|
41
|
+
|
|
42
|
+
## Acceptance-check runner (`aunx checks run`)
|
|
43
|
+
|
|
44
|
+
Scaffold with `aunx checks ACCEPTANCE_CHECKS.json`, then fill each command and its expected property. `aunx checks run ACCEPTANCE_CHECKS.json` executes the commands and reports PASS or FAIL. Any failure exits 1. These are shell commands with your permissions: run only a reviewed check file. Gate a later action by running it only after exit 0.
|
|
45
|
+
|
|
46
|
+
## Briefs, context and metrics
|
|
47
|
+
|
|
48
|
+
`aunx brief` prints the template; `aunx brief new TASK_BRIEF.md` writes a new file. `aunx context CONTEXT.md` scaffolds shared facts. `aunx route-metrics --summary` reports local routing activity. `aunx route "design the auth system"` prints an explained keyword-based suggestion and launches no worker.
|
|
49
|
+
|
|
50
|
+
## Operation and verification
|
|
51
|
+
|
|
52
|
+
- **What and why:** one command exposes the installer and the tools an agent uses to prepare, route and verify work.
|
|
53
|
+
- **Trigger:** a user or agent invokes a command explicitly. The wrapper registers no background service.
|
|
54
|
+
- **Invocation chain:** npm bin link -> `bin/aunx.js` -> `src/aunx.js` -> the selected Node entry point or local scaffold/check handler.
|
|
55
|
+
- **Dependencies:** Node as declared in `package.json`; a vendor CLI and its sign-in only when calling that vendor. Scaffolds and route suggestions work without companions.
|
|
56
|
+
- **Reads:** package templates, an explicitly selected check file, the project's installed runner, and the existing metrics log for summaries.
|
|
57
|
+
- **Writes:** scaffold files use exclusive creation. Check commands can write whatever their reviewed code requests. The delegated runner and metrics hook retain their documented local logs.
|
|
58
|
+
- **Closed loop:** callers inspect the exit code and the check report. Nothing watches the wrapper as a service; the repository test workflow watches committed changes. Gate a later action on exit 0 when using acceptance checks.
|
|
59
|
+
- **Failure modes:** invalid arguments or check format return 2, failed checks return 1, and dispatched Node commands retain their exit codes. An existing scaffold path is preserved. Without `--dir` the packaged runner always runs; with `--dir`, a missing project runner falls back to the packaged copy.
|
|
60
|
+
- **Run and verify:** `node bin/aunx.js --help`, `node bin/aunx.js route "rename this file"`, and `node --test test/aunx.test.js`. For a real vendor, use the doctor command above with your own authorization and quota.
|
|
61
|
+
- **Source of truth:** `src/aunx.js`, the templates it loads, and the dispatch and exit-code tests in `test/aunx.test.js`.
|
package/bin/aunx.js
ADDED
package/bin/cli-run.mjs
CHANGED
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
// 0 ok: structurally accepted non-empty response (and every --expect-* contract met)
|
|
32
32
|
// 10 empty: ran and delivered nothing, or a contract was not met
|
|
33
33
|
// 11 no_output: produced no output at all
|
|
34
|
-
// 12 timeout: the lane
|
|
34
|
+
// 12 timeout: the lane, and its descendants, are killed as a process group
|
|
35
35
|
// 13 unavailable: missing binary, disabled in lanes.json, or lanes.json malformed
|
|
36
36
|
// 14 auth: the lane's own error says a credential is missing or not logged in
|
|
37
37
|
// 15 quota: the lane's own error says usage limit, credits or rate limit
|
|
38
38
|
// 16 rejected: the upstream rejected the request (bad model id, bad request)
|
|
39
|
-
// 17 refused: no
|
|
39
|
+
// 17 refused: no result, and the lane reports tool calls a hook or deny rule blocked
|
|
40
40
|
// 18 cut_short: no trustworthy finish: a missing or non-success terminal event, a lane
|
|
41
41
|
// killed by a signal, output past the 16 MiB buffer, or a nonzero vendor exit
|
|
42
42
|
// 130 / 143 cli-run itself received SIGINT / SIGTERM: the lane's process group was killed first
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
// was REQUESTED plus where the request came from (flag, lanes.json, or nothing
|
|
61
61
|
// at all). It does not log an "actual". One lane of five (grok) does report a
|
|
62
62
|
// model id in its own output; the other four report none, and a field present
|
|
63
|
-
// for one lane and absent for four is worse than no field. It would also be a
|
|
63
|
+
// for one lane, and absent for four, is worse than no field. It would also be a
|
|
64
64
|
// provider-supplied string, which this log deliberately never holds.
|
|
65
65
|
|
|
66
66
|
import { spawn, spawnSync } from 'node:child_process';
|
|
@@ -821,7 +821,7 @@ export function classifyRun(lane, { rc = 0, out = '', err = '', reason = '', det
|
|
|
821
821
|
// boundary; that is documented, not hidden.
|
|
822
822
|
// Models often wrap JSON in one markdown fence. --expect-json accepts exactly that shape:
|
|
823
823
|
// the whole trimmed response is one fenced block, optionally tagged json. Prose before or
|
|
824
|
-
// after the fence still fails, because then the
|
|
824
|
+
// after the fence still fails, because then the result is not the JSON (#17).
|
|
825
825
|
export function unfence(text) {
|
|
826
826
|
const t = String(text).trim();
|
|
827
827
|
const m = /^```(?:json|JSON)?[ \t]*\r?\n([\s\S]*?)\r?\n?```$/.exec(t);
|
|
@@ -920,7 +920,7 @@ export function windowsSpawnPlan(argv, platform = process.platform, { allowCmdFa
|
|
|
920
920
|
return { command: comspec, args: ['/d', '/s', '/c', buildCmdExeCommand(bin, args)], options: { windowsVerbatimArguments: true } };
|
|
921
921
|
}
|
|
922
922
|
|
|
923
|
-
// Kill a lane and everything it spawned. POSIX: the detached process group.
|
|
923
|
+
// Kill a lane, and everything it spawned. POSIX: the detached process group.
|
|
924
924
|
// Windows has no process groups a signal can reach, so taskkill walks the
|
|
925
925
|
// tree (#18): whether the direct child is node (the resolved-shim path) or
|
|
926
926
|
// cmd.exe (the fallback), taskkill /T reaches every descendant either way.
|
|
@@ -1154,23 +1154,27 @@ function installedPrimary(here = dirname(fileURLToPath(import.meta.url))) {
|
|
|
1154
1154
|
}
|
|
1155
1155
|
|
|
1156
1156
|
// --doctor: the first thing to run after install.
|
|
1157
|
-
export async function doctor(run) {
|
|
1158
|
-
const cfg =
|
|
1157
|
+
export async function doctor(run, { here = dirname(fileURLToPath(import.meta.url)), compact = false, config = laneConfig(here), primary = installedPrimary(here) } = {}) {
|
|
1158
|
+
const cfg = config;
|
|
1159
1159
|
if (cfg === null) {
|
|
1160
1160
|
console.error('doctor: lanes.json exists but is malformed; fix it first');
|
|
1161
1161
|
return USAGE;
|
|
1162
1162
|
}
|
|
1163
1163
|
const { enabled, defaults } = cfg;
|
|
1164
1164
|
let bad = 0;
|
|
1165
|
-
console.log(`doctor: ${enabled.length} enabled lane(s): ${enabled.join(', ') || 'none'}`);
|
|
1166
|
-
|
|
1167
|
-
if (primary && !enabled.includes(primary)) console.log(` note: ${primary} is the primary agent and is not an executable lane`);
|
|
1165
|
+
if (!compact) console.log(`doctor: ${enabled.length} enabled lane(s): ${enabled.join(', ') || 'none'}`);
|
|
1166
|
+
if (!compact && primary && !enabled.includes(primary)) console.log(` note: ${primary} is the main agent and is not an executable lane`);
|
|
1168
1167
|
if (!enabled.length) {
|
|
1168
|
+
if (compact) {
|
|
1169
|
+
console.log('doctor: no executable lanes enabled.');
|
|
1170
|
+
return UNAVAILABLE;
|
|
1171
|
+
}
|
|
1169
1172
|
console.error('doctor: inactive: no executable lanes enabled. Use level 1 for a single-agent setup, or re-run the installer with a supported CLI selected.');
|
|
1170
1173
|
return UNAVAILABLE;
|
|
1171
1174
|
}
|
|
1172
1175
|
for (const lane of LANES) {
|
|
1173
1176
|
const on = enabled.includes(lane);
|
|
1177
|
+
if (compact && !on) continue;
|
|
1174
1178
|
const bin = which(lane);
|
|
1175
1179
|
const d = defaults[lane] || {};
|
|
1176
1180
|
// A disabled lane has no route worth reporting; saying "not pinned" there
|
|
@@ -1183,11 +1187,13 @@ export async function doctor(run) {
|
|
|
1183
1187
|
line += rc === OK ? ' canary ok' : ` canary FAILED rc=${rc}`;
|
|
1184
1188
|
if (rc !== OK) bad++;
|
|
1185
1189
|
}
|
|
1186
|
-
console.log(line);
|
|
1190
|
+
console.log(compact ? ` ${lane}: ${bin ? 'present' : 'MISSING'}` : line);
|
|
1187
1191
|
}
|
|
1188
1192
|
console.log(bad ? `doctor: ${bad} problem(s)` : 'doctor: all enabled lanes ' + (run ? 'answered' : 'present'));
|
|
1189
|
-
|
|
1190
|
-
|
|
1193
|
+
if (!compact) {
|
|
1194
|
+
console.log('doctor checks presence and, with --run, a one-word canary. It does not check vendor versions.');
|
|
1195
|
+
console.log('"route not pinned" means that lane runs on whatever its own config file says, which this tool cannot see. Pin it in lanes.json "defaults" if the route matters.');
|
|
1196
|
+
}
|
|
1191
1197
|
return bad ? NO_DELIVERABLE : OK;
|
|
1192
1198
|
}
|
|
1193
1199
|
|
|
@@ -1216,7 +1222,7 @@ export function checkContracts(opts, text, before) {
|
|
|
1216
1222
|
if (!after.file || after.size === 0) return `--expect-file: ${p} is empty or not a regular file`;
|
|
1217
1223
|
if (before && before.exists) {
|
|
1218
1224
|
const changed = !before.file || after.sha !== before.sha || after.mtimeMs > before.mtimeMs;
|
|
1219
|
-
if (!changed) return `--expect-file: ${p} existed before the run and was not changed by it (same content, same mtime); a pre-existing artifact is not this run's
|
|
1225
|
+
if (!changed) return `--expect-file: ${p} existed before the run and was not changed by it (same content, same mtime); a pre-existing artifact is not this run's result`;
|
|
1220
1226
|
}
|
|
1221
1227
|
}
|
|
1222
1228
|
if (opts.expectJson) {
|
|
@@ -1346,7 +1352,7 @@ export async function main(argv) {
|
|
|
1346
1352
|
verdict = 'unavailable'; reason = 'unavailable'; detail = r.error.message; cls = 'unavailable';
|
|
1347
1353
|
} else if (r.signal || r.status === null) {
|
|
1348
1354
|
// A lane killed by a signal has no honest exit status. Whatever it printed
|
|
1349
|
-
// before dying is not a
|
|
1355
|
+
// before dying is not a result; a null status must never become exit 0.
|
|
1350
1356
|
verdict = 'killed'; reason = 'killed'; detail = `lane killed by ${r.signal || 'unknown signal'}`; cls = 'cut_short';
|
|
1351
1357
|
} else {
|
|
1352
1358
|
const j = safeJudge(lane, r.status, out, err, outFile);
|