model-orchestrator 1.0.1 → 1.0.2
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
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to this project are documented here. The format follows [Kee
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.0.2] - 2026-09-28
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- A refused symlinked or changing file (such as `MANIFEST.json`) now names its path and the fix: replace the link with the file it points to. Since 1.0.1, rerunning the installer over a symlinked manifest stops instead of treating it as a fresh install.
|
|
12
|
+
- A path shown in a refusal escapes control characters, so a crafted file name cannot write terminal escape sequences; a directory or other non-file gets "expected a regular file" without symlink advice.
|
|
13
|
+
- The acceptance-check protocol states the timeout's reach: it stops the command's process group, and a descendant that starts its own session (for example with `setsid`) keeps running.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Product website at `model-orchestrator.aunysillyme.dev`, with repository-generated documentation, changelog, and the model-orchestrator trailer. Main-branch pushes rebuild the site through Vercel; the published version is checked against npm.
|
|
18
|
+
|
|
7
19
|
## [1.0.1] - 2026-09-27
|
|
8
20
|
|
|
9
21
|
### Security
|
|
@@ -513,7 +525,8 @@ First release.
|
|
|
513
525
|
- Tests: a case per fix, judges proven to go red, mutation checks; `npm test` prints the current count.
|
|
514
526
|
- Adversarial audit: two Codex rounds plus a two-engine review (Codex, Antigravity); findings and fixes in `docs/audit-brief.md`. After the review: subagents go to the project root (`--project`), snippet paths computed from `--dir`, lane sections rendered from the selection, a primary agent required, level 3 asks for API keys separately from CLIs, images and CLI installs pinned, an activation summary at the end of every install.
|
|
515
527
|
|
|
516
|
-
[Unreleased]: https://github.com/aunysillyme/model-orchestrator/compare/v1.0.
|
|
528
|
+
[Unreleased]: https://github.com/aunysillyme/model-orchestrator/compare/v1.0.2...HEAD
|
|
529
|
+
[1.0.2]: https://github.com/aunysillyme/model-orchestrator/compare/v1.0.1...v1.0.2
|
|
517
530
|
[1.0.1]: https://github.com/aunysillyme/model-orchestrator/compare/v1.0.0...v1.0.1
|
|
518
531
|
[1.0.0]: https://github.com/aunysillyme/model-orchestrator/compare/v0.1.35...v1.0.0
|
|
519
532
|
[0.1.35]: https://github.com/aunysillyme/model-orchestrator/compare/v0.1.34...v0.1.35
|
package/README.md
CHANGED
|
@@ -209,7 +209,7 @@ Run `npx model-orchestrator --uninstall --dir ./ai-orchestrator --project .` (ad
|
|
|
209
209
|
|
|
210
210
|
Node 18 or newer, with zero runtime dependencies. Works on macOS and Linux; the level 3 box templates assume Ubuntu. Windows: CI runs the suite on `windows-latest` (Node 18, 20, 22), including lane execution end to end through `cli-run` against a fake CLI installed the same way npm installs a real one (a `.cmd` shim). `cli-run` never runs a lane through `cmd.exe`: it resolves the shim to the Node script underneath and spawns Node directly, so a prompt reaching a real lane never passes through a Windows shell. A `.cmd` or `.bat` lane that cannot be resolved that way (an old or hand-edited shim) is refused with exit 13 and a message saying how to fix it, rather than run through `cmd.exe`: a batch file re-reads its arguments after `cmd.exe` has parsed them once, and no escaping fully contains a prompt through both passes. Install, detection, the hooks and `cli-run`'s `taskkill` tree kill are tested on Windows too, including SIGTERM/SIGINT to the wrapper (Windows has no OS-level signals: both terminate it unconditionally, verified there rather than treated the same as POSIX). The Windows skip list covers POSIX behavior, with each skip pinned by `test/prose.test.js`: `statSync().mode`'s executable bit (NTFS has none, so that one assertion is conditional inside a test that otherwise runs everywhere); a lane dying mid-run from a real POSIX signal (a real Windows lane cannot die "by signal"); running `weekly-audit.sh`'s watchdog functions for real under Git Bash's job control, both the end-to-end run and the `bounded()` timeout check (the script itself only ever runs on the Ubuntu box it targets); and a `mkfifo` FIFO at the rules path, the one case that proves `route-gate.mjs` cannot HANG on a non-regular file, since Windows has no `mkfifo` to build one (the guard behind it is covered on every OS by a directory at the same path); and an untracked `mkfifo` FIFO in the repository `cli-run --audit` sizes, the case that proves `--effort auto` never opens a non-regular file (the symlink half of that test runs on every OS). `test/prose.test.js` counts every `skip:` in the suite and requires this list to document each one.
|
|
211
211
|
|
|
212
|
-
Additional security regressions skip Windows for the project-hook symlink and manifest FIFO fixtures (symlink privileges and POSIX special files), the POSIX shell descendant timeout fixture (the argv equivalent still runs on Windows), and four weekly credential and report lifecycle runtime checks (the Ubuntu watchdog requires POSIX process-tree semantics). Their configuration and generated syntax remain covered on every platform.
|
|
212
|
+
Additional security regressions skip Windows for the project-hook symlink and manifest FIFO fixtures and the symlinked-manifest refusal message (symlink privileges and POSIX special files), the POSIX shell descendant timeout fixture (the argv equivalent still runs on Windows), and four weekly credential and report lifecycle runtime checks (the Ubuntu watchdog requires POSIX process-tree semantics). Their configuration and generated syntax remain covered on every platform.
|
|
213
213
|
|
|
214
214
|
**Privacy.** The installer sends no telemetry and makes no network call of its own once it is running. Two things around that are worth being exact about:
|
|
215
215
|
|
|
@@ -6,6 +6,7 @@ This page summarizes completed reviews recorded in the [changelog](../CHANGELOG.
|
|
|
6
6
|
|
|
7
7
|
| Release | Review recorded | What the review found | What changed and where it is checked |
|
|
8
8
|
|---|---|---|---|
|
|
9
|
+
| 1.0.2 | Independent review of 1.0.1 by a second model family, then an audit of its fix | A detached check descendant outlived the timeout while the notes said descendants stop; a symlinked-manifest refusal named no file or fix; refusal paths could carry terminal escapes; a directory got symlink advice | The protocol states the process-group limit; refusals name the path, escape control characters and give advice by file type; `test/security-messages.test.js` |
|
|
9
10
|
| 1.0.1 | Codex Security scan and regression-backed remediation | A metrics summary executed project code; manifest reads and check descendants needed bounds; weekly jobs inherited gateway credentials | Packaged metrics dispatch, bounded file readers, check process-tree cleanup, stdin-only gateway probe and separate audit environment; `test/security-cli.test.js`, `test/security-vm.test.js`, `test/security-pins.test.js` |
|
|
10
11
|
| 0.1.0 | Initial review and follow-up round, with a second model-family review | Paths could escape the write roots, partial writes could remain, malformed arguments could proceed, and empty results could appear successful | Containment preflight, exclusive writes with rollback, strict flag parsing and vendor-specific result checks; `test/install.test.js`, `test/cli.test.js`, `test/judges.test.js` |
|
|
11
12
|
| 0.1.1 | Follow-up on issues #1 through #10 | Child processes could survive timeouts; a failed scheduled run could replace a good report; logs could contain provider text | Process-group cleanup, temporary report plus rename, bounded probes and fixed log codes; `test/cli.test.js`, `test/install.test.js` |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "model-orchestrator",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Model router for AI coding agents: installs routing rules, 8 subagents, hooks and a CLI runner so your AI picks model and effort per task and saves tokens",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/bounded-file.js
CHANGED
|
@@ -2,6 +2,8 @@ import { closeSync, constants, fstatSync, lstatSync, openSync, readSync } from '
|
|
|
2
2
|
|
|
3
3
|
export const MANIFEST_BYTE_CAP = 1024 * 1024;
|
|
4
4
|
const refused = message => Object.assign(new Error(message), { code: 'UNSAFE_FILE' });
|
|
5
|
+
// A path is printed to a terminal; control characters (escape sequences) are shown escaped.
|
|
6
|
+
const shown = path => String(path).replace(/[\u0000-\u001f\u007f-\u009f]/g, c => `\\x${c.charCodeAt(0).toString(16).padStart(2, '0')}`);
|
|
5
7
|
|
|
6
8
|
// A fixed buffer also bounds files that grow after the initial size check.
|
|
7
9
|
export function readBounded(fd, maxBytes) {
|
|
@@ -21,11 +23,12 @@ export function readBounded(fd, maxBytes) {
|
|
|
21
23
|
|
|
22
24
|
export function readRegularFile(path, maxBytes) {
|
|
23
25
|
const before = lstatSync(path);
|
|
24
|
-
if (
|
|
26
|
+
if (before.isSymbolicLink()) throw refused(`${shown(path)}: expected a regular file, not a symlink; replace the link with the file it points to, then run the command again`);
|
|
27
|
+
if (!before.isFile()) throw refused(`${shown(path)}: expected a regular file; point the command at a file`);
|
|
25
28
|
const fd = openSync(path, constants.O_RDONLY | (constants.O_NOFOLLOW || 0) | (constants.O_NONBLOCK || 0));
|
|
26
29
|
try {
|
|
27
30
|
const after = fstatSync(fd);
|
|
28
|
-
if (!after.isFile() || after.dev !== before.dev || after.ino !== before.ino) throw refused(
|
|
31
|
+
if (!after.isFile() || after.dev !== before.dev || after.ino !== before.ino) throw refused(`${shown(path)}: file changed during inspection; run the command again`);
|
|
29
32
|
return readBounded(fd, maxBytes);
|
|
30
33
|
} finally { closeSync(fd); }
|
|
31
34
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
- Scaffold a checks file with `aunx checks`. Replace the intentionally failing example with a real verifier before using the file.
|
|
5
5
|
- Prefer an argv array for `command`, for example `["node", "--test", "test/example.test.js"]`. String commands run through the local shell, so review them as executable code before running a checks file.
|
|
6
6
|
- Set `cwd` relative to the checks file. Keep checks inside the task's authorized scope.
|
|
7
|
-
- Checks run sequentially with inherited terminal output. A timeout stops the command and its ordinary descendants; interrupts stop the run. A finished check must not leave a background service running. This lifecycle cleanup is not a sandbox for
|
|
7
|
+
- Checks run sequentially with inherited terminal output. A timeout stops the command and its ordinary descendants; interrupts stop the run. A finished check must not leave a background service running. This lifecycle cleanup is not a sandbox: a descendant that starts its own session (for example with `setsid`) leaves the process group and keeps running after the timeout.
|
|
8
8
|
- Demonstrate a failing case for each new gate before trusting a passing result.
|
|
9
9
|
- Include availability facts when later work depends on a tool, permission or service remaining accessible.
|
|
10
10
|
- Run `aunx checks run ACCEPTANCE_CHECKS.json` against the final artifact. A failed command gives the gate exit code 1.
|