@nodetool-ai/reliability-harness 0.8.1
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 +34 -0
- package/dist/.nodetool-build-stamp +1 -0
- package/dist/cli.d.ts +73 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +201 -0
- package/dist/cli.js.map +1 -0
- package/dist/compare.d.ts +98 -0
- package/dist/compare.d.ts.map +1 -0
- package/dist/compare.js +267 -0
- package/dist/compare.js.map +1 -0
- package/dist/core/diff.d.ts +39 -0
- package/dist/core/diff.d.ts.map +1 -0
- package/dist/core/diff.js +114 -0
- package/dist/core/diff.js.map +1 -0
- package/dist/core/golden.d.ts +50 -0
- package/dist/core/golden.d.ts.map +1 -0
- package/dist/core/golden.js +150 -0
- package/dist/core/golden.js.map +1 -0
- package/dist/core/invariants/index.d.ts +32 -0
- package/dist/core/invariants/index.d.ts.map +1 -0
- package/dist/core/invariants/index.js +44 -0
- package/dist/core/invariants/index.js.map +1 -0
- package/dist/core/invariants/leaks.d.ts +22 -0
- package/dist/core/invariants/leaks.d.ts.map +1 -0
- package/dist/core/invariants/leaks.js +55 -0
- package/dist/core/invariants/leaks.js.map +1 -0
- package/dist/core/invariants/lifecycle.d.ts +19 -0
- package/dist/core/invariants/lifecycle.d.ts.map +1 -0
- package/dist/core/invariants/lifecycle.js +95 -0
- package/dist/core/invariants/lifecycle.js.map +1 -0
- package/dist/core/invariants/protocol-validity.d.ts +4 -0
- package/dist/core/invariants/protocol-validity.d.ts.map +1 -0
- package/dist/core/invariants/protocol-validity.js +131 -0
- package/dist/core/invariants/protocol-validity.js.map +1 -0
- package/dist/core/invariants/state-machine.d.ts +29 -0
- package/dist/core/invariants/state-machine.d.ts.map +1 -0
- package/dist/core/invariants/state-machine.js +79 -0
- package/dist/core/invariants/state-machine.js.map +1 -0
- package/dist/core/invariants/status-sets.d.ts +27 -0
- package/dist/core/invariants/status-sets.d.ts.map +1 -0
- package/dist/core/invariants/status-sets.js +51 -0
- package/dist/core/invariants/status-sets.js.map +1 -0
- package/dist/core/invariants/terminal-uniqueness.d.ts +23 -0
- package/dist/core/invariants/terminal-uniqueness.d.ts.map +1 -0
- package/dist/core/invariants/terminal-uniqueness.js +99 -0
- package/dist/core/invariants/terminal-uniqueness.js.map +1 -0
- package/dist/core/invariants/types.d.ts +25 -0
- package/dist/core/invariants/types.d.ts.map +1 -0
- package/dist/core/invariants/types.js +2 -0
- package/dist/core/invariants/types.js.map +1 -0
- package/dist/core/journey.d.ts +121 -0
- package/dist/core/journey.d.ts.map +1 -0
- package/dist/core/journey.js +166 -0
- package/dist/core/journey.js.map +1 -0
- package/dist/core/normalize.d.ts +86 -0
- package/dist/core/normalize.d.ts.map +1 -0
- package/dist/core/normalize.js +182 -0
- package/dist/core/normalize.js.map +1 -0
- package/dist/core/record.d.ts +160 -0
- package/dist/core/record.d.ts.map +1 -0
- package/dist/core/record.js +74 -0
- package/dist/core/record.js.map +1 -0
- package/dist/core/stable-json.d.ts +13 -0
- package/dist/core/stable-json.d.ts.map +1 -0
- package/dist/core/stable-json.js +28 -0
- package/dist/core/stable-json.js.map +1 -0
- package/dist/drivers/anchors.d.ts +29 -0
- package/dist/drivers/anchors.d.ts.map +1 -0
- package/dist/drivers/anchors.js +48 -0
- package/dist/drivers/anchors.js.map +1 -0
- package/dist/drivers/app-headless.d.ts +39 -0
- package/dist/drivers/app-headless.d.ts.map +1 -0
- package/dist/drivers/app-headless.js +123 -0
- package/dist/drivers/app-headless.js.map +1 -0
- package/dist/drivers/browser.d.ts +34 -0
- package/dist/drivers/browser.d.ts.map +1 -0
- package/dist/drivers/browser.js +176 -0
- package/dist/drivers/browser.js.map +1 -0
- package/dist/drivers/cli.d.ts +13 -0
- package/dist/drivers/cli.d.ts.map +1 -0
- package/dist/drivers/cli.js +82 -0
- package/dist/drivers/cli.js.map +1 -0
- package/dist/drivers/fixture-nodes.d.ts +124 -0
- package/dist/drivers/fixture-nodes.d.ts.map +1 -0
- package/dist/drivers/fixture-nodes.js +189 -0
- package/dist/drivers/fixture-nodes.js.map +1 -0
- package/dist/drivers/index.d.ts +18 -0
- package/dist/drivers/index.d.ts.map +1 -0
- package/dist/drivers/index.js +12 -0
- package/dist/drivers/index.js.map +1 -0
- package/dist/drivers/kernel.d.ts +8 -0
- package/dist/drivers/kernel.d.ts.map +1 -0
- package/dist/drivers/kernel.js +247 -0
- package/dist/drivers/kernel.js.map +1 -0
- package/dist/drivers/packaged.d.ts +28 -0
- package/dist/drivers/packaged.d.ts.map +1 -0
- package/dist/drivers/packaged.js +303 -0
- package/dist/drivers/packaged.js.map +1 -0
- package/dist/drivers/python-bridge.d.ts +22 -0
- package/dist/drivers/python-bridge.d.ts.map +1 -0
- package/dist/drivers/python-bridge.js +48 -0
- package/dist/drivers/python-bridge.js.map +1 -0
- package/dist/drivers/registry.d.ts +11 -0
- package/dist/drivers/registry.d.ts.map +1 -0
- package/dist/drivers/registry.js +18 -0
- package/dist/drivers/registry.js.map +1 -0
- package/dist/drivers/relay-fields.d.ts +70 -0
- package/dist/drivers/relay-fields.d.ts.map +1 -0
- package/dist/drivers/relay-fields.js +104 -0
- package/dist/drivers/relay-fields.js.map +1 -0
- package/dist/drivers/repo-root.d.ts +9 -0
- package/dist/drivers/repo-root.d.ts.map +1 -0
- package/dist/drivers/repo-root.js +39 -0
- package/dist/drivers/repo-root.js.map +1 -0
- package/dist/drivers/spawn-cli.d.ts +8 -0
- package/dist/drivers/spawn-cli.d.ts.map +1 -0
- package/dist/drivers/spawn-cli.js +41 -0
- package/dist/drivers/spawn-cli.js.map +1 -0
- package/dist/drivers/types.d.ts +18 -0
- package/dist/drivers/types.d.ts.map +1 -0
- package/dist/drivers/types.js +2 -0
- package/dist/drivers/types.js.map +1 -0
- package/dist/drivers/ws-server.d.ts +8 -0
- package/dist/drivers/ws-server.d.ts.map +1 -0
- package/dist/drivers/ws-server.js +382 -0
- package/dist/drivers/ws-server.js.map +1 -0
- package/dist/faults/bridge-faults.d.ts +7 -0
- package/dist/faults/bridge-faults.d.ts.map +1 -0
- package/dist/faults/bridge-faults.js +90 -0
- package/dist/faults/bridge-faults.js.map +1 -0
- package/dist/faults/host-faults.d.ts +40 -0
- package/dist/faults/host-faults.d.ts.map +1 -0
- package/dist/faults/host-faults.js +70 -0
- package/dist/faults/host-faults.js.map +1 -0
- package/dist/faults/index.d.ts +21 -0
- package/dist/faults/index.d.ts.map +1 -0
- package/dist/faults/index.js +29 -0
- package/dist/faults/index.js.map +1 -0
- package/dist/faults/net-proxy.d.ts +75 -0
- package/dist/faults/net-proxy.d.ts.map +1 -0
- package/dist/faults/net-proxy.js +305 -0
- package/dist/faults/net-proxy.js.map +1 -0
- package/dist/faults/provider-faults.d.ts +12 -0
- package/dist/faults/provider-faults.d.ts.map +1 -0
- package/dist/faults/provider-faults.js +110 -0
- package/dist/faults/provider-faults.js.map +1 -0
- package/dist/faults/registry.d.ts +17 -0
- package/dist/faults/registry.d.ts.map +1 -0
- package/dist/faults/registry.js +15 -0
- package/dist/faults/registry.js.map +1 -0
- package/dist/faults/types.d.ts +42 -0
- package/dist/faults/types.d.ts.map +1 -0
- package/dist/faults/types.js +2 -0
- package/dist/faults/types.js.map +1 -0
- package/dist/faults/ws-faults.d.ts +6 -0
- package/dist/faults/ws-faults.d.ts.map +1 -0
- package/dist/faults/ws-faults.js +48 -0
- package/dist/faults/ws-faults.js.map +1 -0
- package/dist/faults/ws-proxy.d.ts +36 -0
- package/dist/faults/ws-proxy.d.ts.map +1 -0
- package/dist/faults/ws-proxy.js +40 -0
- package/dist/faults/ws-proxy.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/package.json +75 -0
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# @nodetool-ai/reliability-harness
|
|
2
|
+
|
|
3
|
+
Core of NodeTool's reliability harness: journey manifests, the `RunRecord`
|
|
4
|
+
format, output normalization, and per-channel stream diffing.
|
|
5
|
+
|
|
6
|
+
A journey replays a scripted workload against a driver and records everything
|
|
7
|
+
it emitted as a `RunRecord`. Normalization strips the parts that legitimately
|
|
8
|
+
change between runs (ids, timestamps, durations) so two records compare on
|
|
9
|
+
behavior alone; the diff is per channel, so a change in log output does not
|
|
10
|
+
mask a change in results.
|
|
11
|
+
|
|
12
|
+
## Layout
|
|
13
|
+
|
|
14
|
+
| Path | Holds |
|
|
15
|
+
|---|---|
|
|
16
|
+
| `core/journey.ts` | Journey manifest schema and loading |
|
|
17
|
+
| `core/record.ts` | `RunRecord` — what one replay captured |
|
|
18
|
+
| `core/normalize.ts` | Run-to-run variance stripped before comparison |
|
|
19
|
+
| `core/diff.ts` | Per-channel stream diff |
|
|
20
|
+
| `core/golden.ts` | Golden-record read/write |
|
|
21
|
+
| `core/invariants/` | Assertions that must hold across every journey |
|
|
22
|
+
| `drivers/` | What a journey drives |
|
|
23
|
+
| `faults/` | Fault injection |
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @nodetool-ai/reliability-harness
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The package also ships a CLI entry (`cli.ts`) used by the repo's Ring 0
|
|
32
|
+
reliability journeys, which `nodetool harness gate` selects for diffs touching
|
|
33
|
+
`packages/kernel/`.
|
|
34
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2026-09-28T09:19:18.697Z
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { formatCompareReport, type CompareDriver, type CompareReport } from "./compare.js";
|
|
2
|
+
import "./faults/index.js";
|
|
3
|
+
/** Every surface `nodetool reliability run --surface` accepts, keyed to a
|
|
4
|
+
* fresh driver instance — fresh per call so two `runJourney` calls (e.g. the
|
|
5
|
+
* CLI's own `--json` and human-readable paths, or a test loop) never share
|
|
6
|
+
* driver-local state. */
|
|
7
|
+
export declare const DRIVER_FACTORIES: Readonly<Record<string, () => CompareDriver>>;
|
|
8
|
+
/**
|
|
9
|
+
* §9's fault seams, named — the full target vocabulary across D1 (provider,
|
|
10
|
+
* shipped)/D2 (ws)/D3 (bridge, host, client). `--faults` validates a
|
|
11
|
+
* requested name against this list (a typo is a CLI error, not a silent
|
|
12
|
+
* no-op); whether the name actually does anything at runtime depends on
|
|
13
|
+
* whether a `FaultModule` is registered for it (`faults/registry.ts`) — see
|
|
14
|
+
* `runJourney`'s `unknownFaults` handling for names in this list a module
|
|
15
|
+
* hasn't shipped for yet.
|
|
16
|
+
*/
|
|
17
|
+
export declare const KNOWN_FAULT_TYPES: readonly string[];
|
|
18
|
+
export declare class ReliabilityCliError extends Error {
|
|
19
|
+
}
|
|
20
|
+
/** Walks up from this module to the checkout's `reliability/journeys` — works
|
|
21
|
+
* from both `src/` (tsx dev) and `dist/` (built) locations. */
|
|
22
|
+
export declare function findJourneysDir(): string;
|
|
23
|
+
interface JourneySummary {
|
|
24
|
+
name: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
surfaces: string[];
|
|
27
|
+
invariants: string[];
|
|
28
|
+
timeoutMs: number;
|
|
29
|
+
}
|
|
30
|
+
/** Every journey directory under `journeysDir` (default: the repo's
|
|
31
|
+
* `reliability/journeys`), loaded and summarized for `nodetool reliability
|
|
32
|
+
* list`. */
|
|
33
|
+
export declare function listJourneys(journeysDir?: string): Promise<JourneySummary[]>;
|
|
34
|
+
interface RunJourneyOptions {
|
|
35
|
+
journeysDir?: string;
|
|
36
|
+
/** Overrides the journey manifest's own `surfaces` list. The oracle
|
|
37
|
+
* (`kernel`) is always included even if omitted — `compareJourney` needs it
|
|
38
|
+
* present to diff against. */
|
|
39
|
+
surfaces?: string[];
|
|
40
|
+
/**
|
|
41
|
+
* Fault names to inject (§9), replacing the journey's own declared `faults`
|
|
42
|
+
* block for this run — validated against `KNOWN_FAULT_TYPES`, then resolved
|
|
43
|
+
* to `FaultModule`s by `compareJourney` (task D1). A name the journey
|
|
44
|
+
* already declares (with a `surface` restriction or `params`) is reused
|
|
45
|
+
* as-is; a name given here that the journey doesn't declare runs
|
|
46
|
+
* unrestricted (every surface) with no params.
|
|
47
|
+
*/
|
|
48
|
+
faults?: string[];
|
|
49
|
+
}
|
|
50
|
+
/** Runs one journey's differential compare across its (or the caller's
|
|
51
|
+
* override) surfaces. This is what `nodetool reliability run <journey>`
|
|
52
|
+
* calls. */
|
|
53
|
+
export declare function runJourney(journeyName: string, options?: RunJourneyOptions): Promise<CompareReport>;
|
|
54
|
+
/**
|
|
55
|
+
* Rewrites a journey's `expected/` fixtures from a fresh, unfaulted oracle
|
|
56
|
+
* (kernel) run — the maintainer path for a golden that legitimately moved.
|
|
57
|
+
*
|
|
58
|
+
* Only writes the fixtures the journey declares, and refuses a run that
|
|
59
|
+
* didn't complete: a golden captured from a broken run bakes the breakage in.
|
|
60
|
+
* Review the diff — that is what makes the fixture an assertion rather than a
|
|
61
|
+
* transcript.
|
|
62
|
+
*/
|
|
63
|
+
export declare function updateJourneyGoldens(journeyName: string, options?: {
|
|
64
|
+
journeysDir?: string;
|
|
65
|
+
}): Promise<{
|
|
66
|
+
written: string[];
|
|
67
|
+
}>;
|
|
68
|
+
/** Every fault name a `FaultModule` is actually registered for right now —
|
|
69
|
+
* a subset of `KNOWN_FAULT_TYPES` until D2/D3 ship their seams. Exposed for
|
|
70
|
+
* `nodetool reliability list --faults`-style introspection. */
|
|
71
|
+
export declare function listImplementedFaultTypes(): string[];
|
|
72
|
+
export { formatCompareReport, type CompareReport };
|
|
73
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAYA,OAAO,EAAkB,mBAAmB,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAY3G,OAAO,mBAAmB,CAAC;AAE3B;;;yBAGyB;AACzB,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,aAAa,CAAC,CAO1E,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,MAAM,EA0B9C,CAAC;AAEF,qBAAa,mBAAoB,SAAQ,KAAK;CAAG;AAEjD;+DAC+D;AAC/D,wBAAgB,eAAe,IAAI,MAAM,CAaxC;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;YAEY;AACZ,wBAAsB,YAAY,CAAC,WAAW,GAAE,MAA0B,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAiBrG;AAED,UAAU,iBAAiB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;kCAE8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AA2BD;;YAEY;AACZ,wBAAsB,UAAU,CAC9B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,aAAa,CAAC,CA6BxB;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACrC,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA+BhC;AAED;;+DAE+D;AAC/D,wBAAgB,yBAAyB,IAAI,MAAM,EAAE,CAEpD;AAED,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,CAAC"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nodetool reliability` orchestration (§12's package-diagram `cli.ts`).
|
|
3
|
+
* `packages/cli/src/commands/reliability.ts` is a thin Commander wrapper over
|
|
4
|
+
* this module — same split as the debug harness (`packages/cli/src/debug/`
|
|
5
|
+
* does the work, `commands/debug.ts` just parses flags and prints).
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
8
|
+
import { readdir, writeFile } from "node:fs/promises";
|
|
9
|
+
import { dirname, join } from "node:path";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
import { loadJourney } from "./core/journey.js";
|
|
12
|
+
import { streamShapeOf, terminalOutputsOf } from "./core/golden.js";
|
|
13
|
+
import { compareJourney, formatCompareReport } from "./compare.js";
|
|
14
|
+
import { KernelDriver } from "./drivers/kernel.js";
|
|
15
|
+
import { WsServerDriver } from "./drivers/ws-server.js";
|
|
16
|
+
import { CliDriver } from "./drivers/cli.js";
|
|
17
|
+
import { BrowserDriver } from "./drivers/browser.js";
|
|
18
|
+
import { AppHeadlessDriver } from "./drivers/app-headless.js";
|
|
19
|
+
import { PackagedDriver } from "./drivers/packaged.js";
|
|
20
|
+
import { listFaultModuleNames } from "./faults/registry.js";
|
|
21
|
+
// Side-effecting import: registers every built-in fault module, same
|
|
22
|
+
// contract as `compare.ts`'s own import — needed here too since
|
|
23
|
+
// `listFaultModuleNames()`/name validation below run before `compareJourney`
|
|
24
|
+
// would otherwise trigger it.
|
|
25
|
+
import "./faults/index.js";
|
|
26
|
+
/** Every surface `nodetool reliability run --surface` accepts, keyed to a
|
|
27
|
+
* fresh driver instance — fresh per call so two `runJourney` calls (e.g. the
|
|
28
|
+
* CLI's own `--json` and human-readable paths, or a test loop) never share
|
|
29
|
+
* driver-local state. */
|
|
30
|
+
export const DRIVER_FACTORIES = {
|
|
31
|
+
kernel: () => new KernelDriver(),
|
|
32
|
+
"ws-server": () => new WsServerDriver(),
|
|
33
|
+
cli: () => new CliDriver(),
|
|
34
|
+
browser: () => new BrowserDriver(),
|
|
35
|
+
"app-headless": () => new AppHeadlessDriver(),
|
|
36
|
+
packaged: () => new PackagedDriver()
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* §9's fault seams, named — the full target vocabulary across D1 (provider,
|
|
40
|
+
* shipped)/D2 (ws)/D3 (bridge, host, client). `--faults` validates a
|
|
41
|
+
* requested name against this list (a typo is a CLI error, not a silent
|
|
42
|
+
* no-op); whether the name actually does anything at runtime depends on
|
|
43
|
+
* whether a `FaultModule` is registered for it (`faults/registry.ts`) — see
|
|
44
|
+
* `runJourney`'s `unknownFaults` handling for names in this list a module
|
|
45
|
+
* hasn't shipped for yet.
|
|
46
|
+
*/
|
|
47
|
+
export const KNOWN_FAULT_TYPES = [
|
|
48
|
+
"provider-429",
|
|
49
|
+
"provider-500",
|
|
50
|
+
"provider-timeout",
|
|
51
|
+
"provider-truncated-stream",
|
|
52
|
+
"provider-malformed-sse",
|
|
53
|
+
"provider-slow-drip",
|
|
54
|
+
"provider-cost-omission",
|
|
55
|
+
"ws-drop-no-fin",
|
|
56
|
+
"ws-delay",
|
|
57
|
+
"ws-reorder",
|
|
58
|
+
"ws-fragment",
|
|
59
|
+
"ws-stall-reads",
|
|
60
|
+
"ws-abrupt-close",
|
|
61
|
+
"bridge-exit-mid-request",
|
|
62
|
+
"bridge-framing-violation",
|
|
63
|
+
"bridge-never-ready",
|
|
64
|
+
"bridge-epipe",
|
|
65
|
+
"bridge-version-mismatch",
|
|
66
|
+
"host-sigkill-restart",
|
|
67
|
+
"host-disk-full",
|
|
68
|
+
"host-db-locked",
|
|
69
|
+
"client-cancel-storm",
|
|
70
|
+
"client-reconnect-storm",
|
|
71
|
+
"client-duplicate-command",
|
|
72
|
+
"client-out-of-order-end-stream"
|
|
73
|
+
];
|
|
74
|
+
export class ReliabilityCliError extends Error {
|
|
75
|
+
}
|
|
76
|
+
/** Walks up from this module to the checkout's `reliability/journeys` — works
|
|
77
|
+
* from both `src/` (tsx dev) and `dist/` (built) locations. */
|
|
78
|
+
export function findJourneysDir() {
|
|
79
|
+
const start = dirname(fileURLToPath(import.meta.url));
|
|
80
|
+
let dir = start;
|
|
81
|
+
for (let i = 0; i < 12; i++) {
|
|
82
|
+
const candidate = join(dir, "reliability", "journeys");
|
|
83
|
+
if (existsSync(candidate))
|
|
84
|
+
return candidate;
|
|
85
|
+
const parent = dirname(dir);
|
|
86
|
+
if (parent === dir)
|
|
87
|
+
break;
|
|
88
|
+
dir = parent;
|
|
89
|
+
}
|
|
90
|
+
throw new ReliabilityCliError(`could not locate reliability/journeys above ${start} — pass journeysDir explicitly`);
|
|
91
|
+
}
|
|
92
|
+
/** Every journey directory under `journeysDir` (default: the repo's
|
|
93
|
+
* `reliability/journeys`), loaded and summarized for `nodetool reliability
|
|
94
|
+
* list`. */
|
|
95
|
+
export async function listJourneys(journeysDir = findJourneysDir()) {
|
|
96
|
+
const entries = await readdir(journeysDir, { withFileTypes: true });
|
|
97
|
+
const names = entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
98
|
+
const summaries = [];
|
|
99
|
+
for (const name of names) {
|
|
100
|
+
const dir = join(journeysDir, name);
|
|
101
|
+
if (!existsSync(join(dir, "journey.json")))
|
|
102
|
+
continue;
|
|
103
|
+
const journey = await loadJourney(dir);
|
|
104
|
+
summaries.push({
|
|
105
|
+
name: journey.manifest.name,
|
|
106
|
+
description: journey.manifest.description,
|
|
107
|
+
surfaces: journey.manifest.surfaces,
|
|
108
|
+
invariants: journey.manifest.assertions.invariants,
|
|
109
|
+
timeoutMs: journey.manifest.timeoutMs
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return summaries;
|
|
113
|
+
}
|
|
114
|
+
/** Resolves `--faults` names against the journey's own declared `faults`
|
|
115
|
+
* block: reuse a matching entry (keeping its `surface`/`params`) when one
|
|
116
|
+
* exists, else synthesize an unrestricted, param-less entry. Passing no
|
|
117
|
+
* `--faults` at all keeps the journey's full declared matrix unchanged. */
|
|
118
|
+
function resolveFaultSelection(journey, requestedNames) {
|
|
119
|
+
if (!requestedNames || requestedNames.length === 0) {
|
|
120
|
+
return journey.manifest.faults;
|
|
121
|
+
}
|
|
122
|
+
return requestedNames.map((type) => {
|
|
123
|
+
const declared = journey.manifest.faults.find((f) => f.type === type);
|
|
124
|
+
return declared ?? { type };
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
async function resolveJourney(journeyName, journeysDir) {
|
|
128
|
+
const dir = join(journeysDir, journeyName);
|
|
129
|
+
if (!existsSync(join(dir, "journey.json"))) {
|
|
130
|
+
throw new ReliabilityCliError(`no journey named "${journeyName}" in ${journeysDir}`);
|
|
131
|
+
}
|
|
132
|
+
return loadJourney(dir);
|
|
133
|
+
}
|
|
134
|
+
/** Runs one journey's differential compare across its (or the caller's
|
|
135
|
+
* override) surfaces. This is what `nodetool reliability run <journey>`
|
|
136
|
+
* calls. */
|
|
137
|
+
export async function runJourney(journeyName, options = {}) {
|
|
138
|
+
const journeysDir = options.journeysDir ?? findJourneysDir();
|
|
139
|
+
const journey = await resolveJourney(journeyName, journeysDir);
|
|
140
|
+
const requested = options.surfaces && options.surfaces.length > 0
|
|
141
|
+
? options.surfaces
|
|
142
|
+
: journey.manifest.surfaces;
|
|
143
|
+
const surfaceNames = requested.includes("kernel") ? requested : ["kernel", ...requested];
|
|
144
|
+
for (const name of surfaceNames) {
|
|
145
|
+
if (!DRIVER_FACTORIES[name]) {
|
|
146
|
+
throw new ReliabilityCliError(`unknown surface "${name}" — valid surfaces: ${Object.keys(DRIVER_FACTORIES).join(", ")}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
for (const fault of options.faults ?? []) {
|
|
150
|
+
if (!KNOWN_FAULT_TYPES.includes(fault)) {
|
|
151
|
+
throw new ReliabilityCliError(`unknown fault "${fault}" — known fault names: ${KNOWN_FAULT_TYPES.join(", ")}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const drivers = surfaceNames.map((name) => DRIVER_FACTORIES[name]());
|
|
155
|
+
const faults = resolveFaultSelection(journey, options.faults);
|
|
156
|
+
const report = await compareJourney(journey, drivers, { faults });
|
|
157
|
+
return report;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Rewrites a journey's `expected/` fixtures from a fresh, unfaulted oracle
|
|
161
|
+
* (kernel) run — the maintainer path for a golden that legitimately moved.
|
|
162
|
+
*
|
|
163
|
+
* Only writes the fixtures the journey declares, and refuses a run that
|
|
164
|
+
* didn't complete: a golden captured from a broken run bakes the breakage in.
|
|
165
|
+
* Review the diff — that is what makes the fixture an assertion rather than a
|
|
166
|
+
* transcript.
|
|
167
|
+
*/
|
|
168
|
+
export async function updateJourneyGoldens(journeyName, options = {}) {
|
|
169
|
+
const journeysDir = options.journeysDir ?? findJourneysDir();
|
|
170
|
+
const journey = await resolveJourney(journeyName, journeysDir);
|
|
171
|
+
const { assertions } = journey.manifest;
|
|
172
|
+
if (!assertions.outputs && !assertions.streamShape) {
|
|
173
|
+
throw new ReliabilityCliError(`journey "${journeyName}" declares no golden assertions to update`);
|
|
174
|
+
}
|
|
175
|
+
const record = await new KernelDriver().run(journey);
|
|
176
|
+
if (record.status !== "completed") {
|
|
177
|
+
throw new ReliabilityCliError(`journey "${journeyName}" ended "${record.status}" (${record.error ?? "no error"}) — ` +
|
|
178
|
+
"refusing to capture goldens from a run that didn't complete");
|
|
179
|
+
}
|
|
180
|
+
const expectedDir = join(journeysDir, journeyName, "expected");
|
|
181
|
+
const written = [];
|
|
182
|
+
if (assertions.outputs) {
|
|
183
|
+
const file = join(expectedDir, "outputs.json");
|
|
184
|
+
await writeFile(file, `${JSON.stringify(terminalOutputsOf(record), null, 2)}\n`);
|
|
185
|
+
written.push(file);
|
|
186
|
+
}
|
|
187
|
+
if (assertions.streamShape) {
|
|
188
|
+
const file = join(expectedDir, "stream.shape.json");
|
|
189
|
+
await writeFile(file, `${JSON.stringify(streamShapeOf(record), null, 2)}\n`);
|
|
190
|
+
written.push(file);
|
|
191
|
+
}
|
|
192
|
+
return { written };
|
|
193
|
+
}
|
|
194
|
+
/** Every fault name a `FaultModule` is actually registered for right now —
|
|
195
|
+
* a subset of `KNOWN_FAULT_TYPES` until D2/D3 ship their seams. Exposed for
|
|
196
|
+
* `nodetool reliability list --faults`-style introspection. */
|
|
197
|
+
export function listImplementedFaultTypes() {
|
|
198
|
+
return listFaultModuleNames();
|
|
199
|
+
}
|
|
200
|
+
export { formatCompareReport };
|
|
201
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-surface differential compare (§12): runs one journey on N drivers,
|
|
3
|
+
* normalizes every record, diffs each non-oracle surface against the kernel
|
|
4
|
+
* oracle (§12: "the kernel surface is the oracle... every-surface-vs-kernel,
|
|
5
|
+
* not all-pairs"), and aggregates the journey's declared §6 invariant checks
|
|
6
|
+
* per surface. Produces one structured report plus a human-readable
|
|
7
|
+
* formatter for `nodetool reliability run`.
|
|
8
|
+
*/
|
|
9
|
+
import type { Journey, JourneyFault } from "./core/journey.js";
|
|
10
|
+
import { type StreamDiff } from "./core/diff.js";
|
|
11
|
+
import { type GoldenCheckResult } from "./core/golden.js";
|
|
12
|
+
import { type Violation } from "./core/invariants/index.js";
|
|
13
|
+
import type { RunDriver } from "./drivers/types.js";
|
|
14
|
+
import "./faults/index.js";
|
|
15
|
+
/** A `RunDriver` that additionally knows whether it applies to a given
|
|
16
|
+
* journey (added additively by C4 — `supports` is optional on the base
|
|
17
|
+
* `RunDriver` interface so C2's kernel/ws-server drivers need no change). */
|
|
18
|
+
export interface CompareDriver extends RunDriver {
|
|
19
|
+
supports?(journey: Journey): boolean;
|
|
20
|
+
}
|
|
21
|
+
interface SurfaceCompareResult {
|
|
22
|
+
surface: string;
|
|
23
|
+
/** False when the driver declared (via `supports`) that this journey does
|
|
24
|
+
* not apply to it, or when the driver's `run()` threw. */
|
|
25
|
+
ran: boolean;
|
|
26
|
+
/** Why this surface didn't run — either "not applicable" (`supports`
|
|
27
|
+
* returned false) or the driver's thrown error. Only set when `!ran`. */
|
|
28
|
+
skipReason?: string;
|
|
29
|
+
status?: string;
|
|
30
|
+
error?: string | null;
|
|
31
|
+
/** §6 invariant violations from the journey's declared `assertions.invariants`. */
|
|
32
|
+
violations: Violation[];
|
|
33
|
+
/**
|
|
34
|
+
* Golden comparisons the journey declared (`assertions.outputs`,
|
|
35
|
+
* `assertions.streamShape`), one entry each. A skipped entry (faulted run)
|
|
36
|
+
* carries its reason — the fixtures are never silently ignored.
|
|
37
|
+
*/
|
|
38
|
+
goldens: GoldenCheckResult[];
|
|
39
|
+
/** Diff against the oracle's normalized `server_to_client` frames — `null`
|
|
40
|
+
* for the oracle surface itself, or when the surface didn't run. */
|
|
41
|
+
diffVsOracle: StreamDiff | null;
|
|
42
|
+
diffVsOracleEmpty: boolean;
|
|
43
|
+
/** True when this surface is not applicable to the journey (a `supports`
|
|
44
|
+
* check said no) — distinct from a real failure so a report can render it
|
|
45
|
+
* as "n/a" rather than "FAIL". */
|
|
46
|
+
notApplicable: boolean;
|
|
47
|
+
/** Fault names actually configured for this surface's run (task D1) — a
|
|
48
|
+
* subset of the journey's declared/`--faults`-selected faults, filtered by
|
|
49
|
+
* each fault's optional `surface` restriction and by module availability. */
|
|
50
|
+
faultsApplied: string[];
|
|
51
|
+
ok: boolean;
|
|
52
|
+
}
|
|
53
|
+
export interface CompareReport {
|
|
54
|
+
journeyId: string;
|
|
55
|
+
oracle: string;
|
|
56
|
+
/** Invariant names the journey declared that no `INVARIANT_CHECKS` entry
|
|
57
|
+
* recognizes — a journey-authoring mistake, surfaced instead of silently
|
|
58
|
+
* skipped. */
|
|
59
|
+
unknownInvariants: string[];
|
|
60
|
+
/** Fault names requested (via the journey's `faults` block or `--faults`)
|
|
61
|
+
* that no `FaultModule` is registered for (task D1) — surfaced the same
|
|
62
|
+
* way `unknownInvariants` is, instead of silently no-oping the fault. */
|
|
63
|
+
unknownFaults: string[];
|
|
64
|
+
surfaces: SurfaceCompareResult[];
|
|
65
|
+
verdict: {
|
|
66
|
+
ok: boolean;
|
|
67
|
+
issues: string[];
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Runs `journey` on every driver in `drivers`, diffing each non-oracle
|
|
72
|
+
* surface's normalized `server_to_client` stream against the oracle's (the
|
|
73
|
+
* one driver named `options.oracleName`, default `"kernel"` — §12's "the
|
|
74
|
+
* kernel surface is the oracle"). `drivers` must include the oracle driver
|
|
75
|
+
* itself; it both anchors the diff and is reported as its own (trivially
|
|
76
|
+
* clean) surface.
|
|
77
|
+
*
|
|
78
|
+
* `options.faults` (task D1) selects the fault matrix for this run — default
|
|
79
|
+
* is the journey's own declared `faults` block (`journey.json`), so callers
|
|
80
|
+
* that don't care about fault injection get the journey's authored behavior
|
|
81
|
+
* unchanged. Each applicable fault (its `surface` restriction, if any,
|
|
82
|
+
* matched against the driver about to run) is configured immediately before
|
|
83
|
+
* that driver's `run()` and torn down immediately after, so faults never
|
|
84
|
+
* leak across drivers or across `compareJourney` calls.
|
|
85
|
+
*/
|
|
86
|
+
export declare function compareJourney(journey: Journey, drivers: CompareDriver[], options?: {
|
|
87
|
+
oracleName?: string;
|
|
88
|
+
faults?: JourneyFault[];
|
|
89
|
+
}): Promise<CompareReport>;
|
|
90
|
+
/** Human-readable rendering of a `CompareReport` for `nodetool reliability run`.
|
|
91
|
+
* `showDiff` (default `true`) controls whether a diverging surface's full
|
|
92
|
+
* per-channel stream diff is inlined under its summary line, or just noted —
|
|
93
|
+
* `nodetool reliability run`'s `--diff` flag maps straight to this. */
|
|
94
|
+
export declare function formatCompareReport(report: CompareReport, options?: {
|
|
95
|
+
showDiff?: boolean;
|
|
96
|
+
}): string;
|
|
97
|
+
export {};
|
|
98
|
+
//# sourceMappingURL=compare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../src/compare.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAA8D,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC7G,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAG9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAOpD,OAAO,mBAAmB,CAAC;AAE3B;;6EAE6E;AAC7E,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,QAAQ,CAAC,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;CACtC;AAED,UAAU,oBAAoB;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB;8DAC0D;IAC1D,GAAG,EAAE,OAAO,CAAC;IACb;6EACyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,mFAAmF;IACnF,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB;;;;OAIG;IACH,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B;wEACoE;IACpE,YAAY,EAAE,UAAU,GAAG,IAAI,CAAC;IAChC,iBAAiB,EAAE,OAAO,CAAC;IAC3B;;sCAEkC;IAClC,aAAa,EAAE,OAAO,CAAC;IACvB;;iFAE6E;IAC7E,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,EAAE,EAAE,OAAO,CAAC;CACb;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf;;kBAEc;IACd,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B;;6EAEyE;IACzE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,EAAE,oBAAoB,EAAE,CAAC;IACjC,OAAO,EAAE;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAC5C;AAqDD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,aAAa,EAAE,EACxB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,YAAY,EAAE,CAAA;CAAO,GAC7D,OAAO,CAAC,aAAa,CAAC,CA0JxB;AAED;;;uEAGuE;AACvE,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GACnC,MAAM,CAwDR"}
|