vigiles 12.2.0 → 12.4.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/README.md +133 -162
- package/dist/adapters/claude-code/run-scripts.d.ts +41 -0
- package/dist/adapters/claude-code/run-scripts.js +26 -0
- package/dist/cli.js +49 -4
- package/dist/eval.d.ts +15 -0
- package/dist/eval.js +43 -0
- package/dist/experimental.d.ts +27 -0
- package/dist/experimental.js +34 -0
- package/dist/services-docker.d.ts +50 -0
- package/dist/services-docker.js +234 -0
- package/dist/services.d.ts +209 -0
- package/dist/services.js +118 -0
- package/package.json +3 -2
package/dist/services.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* vigiles — R3 disposable-service tier (⚠️ EXPERIMENTAL / UNSTABLE).
|
|
4
|
+
*
|
|
5
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
6
|
+
* EXPERIMENTAL: this surface is a DRAFT. Import it from `vigiles/experimental`,
|
|
7
|
+
* NOT from a stable subpath. It is NOT covered by the stability guarantee and
|
|
8
|
+
* may change shape or be removed WITHOUT a major-version bump. Do not build a
|
|
9
|
+
* production workflow on it yet. See docs/measuring-skills.md § Experimental.
|
|
10
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
11
|
+
*
|
|
12
|
+
* WHAT THIS IS. The free tiers (`runHook`, `measureTriggerRate`, `runEval`)
|
|
13
|
+
* cover a skill's OUTPUT and its side-effect SAFETY (did it call / not call a
|
|
14
|
+
* tool, write / not write a file) with no container. What they do NOT do is let
|
|
15
|
+
* a skill actually PERFORM a side effect against a real service and verify the
|
|
16
|
+
* resulting state — apply a migration to a real Postgres and check the row
|
|
17
|
+
* landed. That is the R3 rung (see research/eval-coverage-and-isolation.md): the
|
|
18
|
+
* REAL system's semantics are the thing under test, so it can't be faked.
|
|
19
|
+
*
|
|
20
|
+
* THE POSTURE. vigiles COMPOSES with a throwaway container; it does not reinvent
|
|
21
|
+
* the sandbox. A {@link ServiceSpec} declares a disposable service; the injected
|
|
22
|
+
* {@link ContainerRuntime} port starts it, and it is force-removed on teardown.
|
|
23
|
+
*
|
|
24
|
+
* ⚠️ SAFETY — the isolation is the DISPOSABLE CONTAINER, nothing more. A skill is
|
|
25
|
+
* model-driven, so the MODEL chooses the actions: it can do anything the run
|
|
26
|
+
* ENVIRONMENT allows. vigiles creates and destroys the container; it does NOT, in
|
|
27
|
+
* this tier, confine the skill's filesystem or block its network. So an R3 run is
|
|
28
|
+
* only as safe as the environment you run it in:
|
|
29
|
+
* - run it in a DISPOSABLE environment — a CI job, a throwaway container/VM, or
|
|
30
|
+
* a dev box with NO production access;
|
|
31
|
+
* - point the task at the disposable service's connection string ONLY;
|
|
32
|
+
* - keep real credentials OUT of the run (prod `DATABASE_URL`, cloud keys,
|
|
33
|
+
* `~/.ssh`) — pair it with the eval tier's `ephemeralEnv` (throwaway HOME +
|
|
34
|
+
* cleared env) to scrub them so the model has no real keys to misuse.
|
|
35
|
+
* Treat it like running an untrusted script. A future increment adds an egress
|
|
36
|
+
* wall (the skill reaches only the model + the service); until then that job is
|
|
37
|
+
* the operator's. See docs/measuring-skills.md § Experimental.
|
|
38
|
+
*
|
|
39
|
+
* WHAT SHIPS TODAY vs LATER. Today: the TYPES, the {@link ContainerRuntime} port,
|
|
40
|
+
* the pure {@link experimental_startServices} / {@link experimental_withServices}
|
|
41
|
+
* orchestration, and a Docker backend (`src/services-docker.ts`). Deferred: the
|
|
42
|
+
* `runEval` / `measureArms` `services` option + `ctx.service(name)`, per-trial
|
|
43
|
+
* reset via an eval-loop hook, and the egress wall. Requires Docker (Linux-first).
|
|
44
|
+
* It is an explicit opt-in and NEVER part of `vigiles audit` (audit stays
|
|
45
|
+
* side-effect-free).
|
|
46
|
+
*
|
|
47
|
+
* @experimental
|
|
48
|
+
* @module vigiles/experimental (services)
|
|
49
|
+
*/
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
exports.experimental_startServices = experimental_startServices;
|
|
52
|
+
exports.experimental_withServices = experimental_withServices;
|
|
53
|
+
/**
|
|
54
|
+
* Start every declared service against an injected {@link ContainerRuntime},
|
|
55
|
+
* returning a {@link ServiceSession}. Pure orchestration over the port — no
|
|
56
|
+
* `docker` is imported here, so this is fully unit-testable with a fake runtime
|
|
57
|
+
* (the `decideSandbox`-is-pure / `runSandboxed`-is-real split). If any service
|
|
58
|
+
* fails to start, the ones already up are torn down before the error propagates,
|
|
59
|
+
* so a partial failure never leaks a container.
|
|
60
|
+
*
|
|
61
|
+
* A Docker-backed `ContainerRuntime` and the `runEval` / `measureArms` wiring are
|
|
62
|
+
* the next increment — until then this is the primitive you compose by hand:
|
|
63
|
+
* start → pin egress to `session.endpoints` → run → read `session.handles` in
|
|
64
|
+
* `measure` → `await session.teardown()`.
|
|
65
|
+
*
|
|
66
|
+
* @experimental — surface may change without a major-version bump.
|
|
67
|
+
*/
|
|
68
|
+
async function experimental_startServices(services, runtime) {
|
|
69
|
+
const handles = {};
|
|
70
|
+
const endpoints = [];
|
|
71
|
+
const started = [];
|
|
72
|
+
const stopAll = async () => {
|
|
73
|
+
await Promise.allSettled(started.map((h) => runtime.stop(h)));
|
|
74
|
+
};
|
|
75
|
+
try {
|
|
76
|
+
for (const [name, spec] of Object.entries(services)) {
|
|
77
|
+
const handle = await runtime.start(name, spec);
|
|
78
|
+
handles[name] = handle;
|
|
79
|
+
started.push(handle);
|
|
80
|
+
// Only a service that published a port has a reachable endpoint.
|
|
81
|
+
if (handle.port !== undefined) {
|
|
82
|
+
endpoints.push(`${handle.host}:${handle.port}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
await stopAll();
|
|
88
|
+
throw err;
|
|
89
|
+
}
|
|
90
|
+
return { handles, endpoints, teardown: stopAll };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Run `fn` with the declared services up, disposing them afterwards — even if
|
|
94
|
+
* `fn` throws. The scope-guard form of {@link experimental_startServices}: it
|
|
95
|
+
* removes the manual `try/finally` so a `measureArms` / `measure` call can be
|
|
96
|
+
* wrapped in one line and its containers are always cleaned up.
|
|
97
|
+
*
|
|
98
|
+
* ⚠️ Read the SAFETY note in this module's header first — the container is the
|
|
99
|
+
* only isolation; keep real credentials out of the run.
|
|
100
|
+
*
|
|
101
|
+
* LIFECYCLE NOTE (honest): the services live for the WHOLE `fn` — i.e. per-RUN,
|
|
102
|
+
* not per-trial. An eval that mutates service state across trials should make its
|
|
103
|
+
* task self-contained (e.g. `drop … if exists; create; migrate`) or run
|
|
104
|
+
* `trials: 1`. True per-trial reset needs an eval-loop hook and is the next
|
|
105
|
+
* increment (research/r3-disposable-services.md).
|
|
106
|
+
*
|
|
107
|
+
* @experimental — surface may change without a major-version bump.
|
|
108
|
+
*/
|
|
109
|
+
async function experimental_withServices(services, runtime, fn) {
|
|
110
|
+
const session = await experimental_startServices(services, runtime);
|
|
111
|
+
try {
|
|
112
|
+
return await fn(session);
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
await session.teardown();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=services.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vigiles",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.4.0",
|
|
4
4
|
"description": "Lint & test the harness your AI agent runs on — verify the references in your CLAUDE.md / AGENTS.md and test that your hooks and skills actually work.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"./claude-code": "./dist/claude-code.js",
|
|
45
45
|
"./codex": "./dist/codex.js",
|
|
46
46
|
"./adapter": "./dist/adapter.js",
|
|
47
|
+
"./experimental": "./dist/experimental.js",
|
|
47
48
|
"./vitest": {
|
|
48
49
|
"types": "./dist/vitest.d.mts",
|
|
49
50
|
"default": "./dist/vitest.mjs"
|
|
@@ -79,7 +80,7 @@
|
|
|
79
80
|
"test:e2e": "npm run build && vitest run --project e2e",
|
|
80
81
|
"test:cli-e2e": "bash test/e2e/run.sh",
|
|
81
82
|
"test:harness": "npm run build && node dist/cli.js test",
|
|
82
|
-
"test:eval": "npm run build && node dist/cli.js eval",
|
|
83
|
+
"test:eval": "npm run build && node dist/cli.js eval --all",
|
|
83
84
|
"test:vitest": "npm run build && vitest run --project runners",
|
|
84
85
|
"test:jest": "npm run build && jest",
|
|
85
86
|
"test:types": "npm run build && tsc --noEmit -p test/types/tsconfig.json",
|