@lannguyensi/harness 0.40.0 → 0.42.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 +68 -0
- package/README.md +9 -0
- package/dist/cli/adopt/derive.d.ts +15 -0
- package/dist/cli/adopt/derive.js +34 -7
- package/dist/cli/adopt/derive.js.map +1 -1
- package/dist/cli/adopt/index.d.ts +30 -0
- package/dist/cli/adopt/index.js +23 -3
- package/dist/cli/adopt/index.js.map +1 -1
- package/dist/cli/apply/generate-settings.d.ts +14 -1
- package/dist/cli/apply/generate-settings.js +7 -3
- package/dist/cli/apply/generate-settings.js.map +1 -1
- package/dist/cli/approve/stdin-report.js +2 -0
- package/dist/cli/approve/stdin-report.js.map +1 -1
- package/dist/cli/approve/understanding.js +28 -0
- package/dist/cli/approve/understanding.js.map +1 -1
- package/dist/cli/doctor/claude-mcp.d.ts +50 -0
- package/dist/cli/doctor/claude-mcp.js +170 -0
- package/dist/cli/doctor/claude-mcp.js.map +1 -0
- package/dist/cli/doctor/codex.d.ts +8 -0
- package/dist/cli/doctor/codex.js +8 -1
- package/dist/cli/doctor/codex.js.map +1 -1
- package/dist/cli/doctor/format.js +60 -11
- package/dist/cli/doctor/format.js.map +1 -1
- package/dist/cli/doctor/index.d.ts +46 -0
- package/dist/cli/doctor/index.js +155 -29
- package/dist/cli/doctor/index.js.map +1 -1
- package/dist/cli/doctor/npm-bin-path.js +42 -0
- package/dist/cli/doctor/npm-bin-path.js.map +1 -1
- package/dist/cli/doctor/types.d.ts +37 -0
- package/dist/cli/doctor/types.js.map +1 -1
- package/dist/cli/dry-run.js +5 -0
- package/dist/cli/dry-run.js.map +1 -1
- package/dist/cli/explain.js +16 -3
- package/dist/cli/explain.js.map +1 -1
- package/dist/cli/index.js +328 -11
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/agent-tasks-auth.js +32 -0
- package/dist/cli/init/agent-tasks-auth.js.map +1 -1
- package/dist/cli/init/composer.js +13 -40
- package/dist/cli/init/composer.js.map +1 -1
- package/dist/cli/init/dependencies.js +21 -0
- package/dist/cli/init/dependencies.js.map +1 -1
- package/dist/cli/init/detect.d.ts +20 -3
- package/dist/cli/init/detect.js +34 -36
- package/dist/cli/init/detect.js.map +1 -1
- package/dist/cli/init/index.d.ts +18 -0
- package/dist/cli/init/index.js +28 -2
- package/dist/cli/init/index.js.map +1 -1
- package/dist/cli/init/interactive.d.ts +41 -0
- package/dist/cli/init/interactive.js +421 -6
- package/dist/cli/init/interactive.js.map +1 -1
- package/dist/cli/init/profiles.d.ts +2 -2
- package/dist/cli/init/profiles.js +10 -1
- package/dist/cli/init/profiles.js.map +1 -1
- package/dist/cli/init/templates.d.ts +1 -1
- package/dist/cli/init/templates.js +217 -8
- package/dist/cli/init/templates.js.map +1 -1
- package/dist/cli/list.js +3 -1
- package/dist/cli/list.js.map +1 -1
- package/dist/cli/main.js +10 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/pack/hook-bootstrap.d.ts +24 -0
- package/dist/cli/pack/hook-bootstrap.js +47 -1
- package/dist/cli/pack/hook-bootstrap.js.map +1 -1
- package/dist/cli/pack/hook-branch-protection.js +9 -1
- package/dist/cli/pack/hook-branch-protection.js.map +1 -1
- package/dist/cli/pack/hook-codex-post-tool-use.d.ts +25 -0
- package/dist/cli/pack/hook-codex-post-tool-use.js +160 -0
- package/dist/cli/pack/hook-codex-post-tool-use.js.map +1 -0
- package/dist/cli/pack/hook-codex-pre-tool-use.d.ts +1 -0
- package/dist/cli/pack/hook-codex-pre-tool-use.js +43 -10
- package/dist/cli/pack/hook-codex-pre-tool-use.js.map +1 -1
- package/dist/cli/pack/hook-codex-stop.js +1 -8
- package/dist/cli/pack/hook-codex-stop.js.map +1 -1
- package/dist/cli/pack/hook-post-merge-gate-record.d.ts +30 -0
- package/dist/cli/pack/hook-post-merge-gate-record.js +153 -0
- package/dist/cli/pack/hook-post-merge-gate-record.js.map +1 -0
- package/dist/cli/pack/hook-post-merge-gate.d.ts +28 -0
- package/dist/cli/pack/hook-post-merge-gate.js +244 -0
- package/dist/cli/pack/hook-post-merge-gate.js.map +1 -0
- package/dist/cli/pack/hook-post-tool-use.js +16 -131
- package/dist/cli/pack/hook-post-tool-use.js.map +1 -1
- package/dist/cli/pack/hook-pre-tool-use.js +54 -2
- package/dist/cli/pack/hook-pre-tool-use.js.map +1 -1
- package/dist/cli/pack/hook-solution-acceptance-writeguard.js +148 -2
- package/dist/cli/pack/hook-solution-acceptance-writeguard.js.map +1 -1
- package/dist/cli/pack/hook-stay-in-scope.js +63 -20
- package/dist/cli/pack/hook-stay-in-scope.js.map +1 -1
- package/dist/cli/pack/hook-track-active-claim.js +33 -9
- package/dist/cli/pack/hook-track-active-claim.js.map +1 -1
- package/dist/cli/pack/index.d.ts +2 -1
- package/dist/cli/pack/index.js +2 -1
- package/dist/cli/pack/index.js.map +1 -1
- package/dist/cli/pack/mutate.d.ts +19 -0
- package/dist/cli/pack/mutate.js +38 -0
- package/dist/cli/pack/mutate.js.map +1 -1
- package/dist/cli/pack/reseed.d.ts +19 -0
- package/dist/cli/pack/reseed.js +118 -0
- package/dist/cli/pack/reseed.js.map +1 -0
- package/dist/cli/pack/understanding-report-schema-hint.js +1 -1
- package/dist/cli/pack/understanding-report-schema-hint.js.map +1 -1
- package/dist/cli/pause/index.js +12 -3
- package/dist/cli/pause/index.js.map +1 -1
- package/dist/cli/record/index.d.ts +64 -0
- package/dist/cli/record/index.js +211 -0
- package/dist/cli/record/index.js.map +1 -0
- package/dist/cli/session-start/index.d.ts +21 -0
- package/dist/cli/session-start/index.js +160 -25
- package/dist/cli/session-start/index.js.map +1 -1
- package/dist/cli/session-start/toolchain-parity.d.ts +149 -0
- package/dist/cli/session-start/toolchain-parity.js +618 -0
- package/dist/cli/session-start/toolchain-parity.js.map +1 -0
- package/dist/cli/uninstall/index.d.ts +73 -1
- package/dist/cli/uninstall/index.js +134 -2
- package/dist/cli/uninstall/index.js.map +1 -1
- package/dist/cli/validate/checks.js +8 -0
- package/dist/cli/validate/checks.js.map +1 -1
- package/dist/io/claude-mcp.d.ts +258 -0
- package/dist/io/claude-mcp.js +544 -0
- package/dist/io/claude-mcp.js.map +1 -0
- package/dist/policies/ledger-client.d.ts +34 -1
- package/dist/policies/ledger-client.js +21 -16
- package/dist/policies/ledger-client.js.map +1 -1
- package/dist/policy-packs/builtin/branch-protection-runtime.d.ts +4 -2
- package/dist/policy-packs/builtin/branch-protection-runtime.js +4 -2
- package/dist/policy-packs/builtin/branch-protection-runtime.js.map +1 -1
- package/dist/policy-packs/builtin/branch-protection.d.ts +10 -1
- package/dist/policy-packs/builtin/branch-protection.js +17 -0
- package/dist/policy-packs/builtin/branch-protection.js.map +1 -1
- package/dist/policy-packs/builtin/post-merge-gate-runtime.d.ts +195 -0
- package/dist/policy-packs/builtin/post-merge-gate-runtime.js +290 -0
- package/dist/policy-packs/builtin/post-merge-gate-runtime.js.map +1 -0
- package/dist/policy-packs/builtin/post-merge-gate.d.ts +56 -0
- package/dist/policy-packs/builtin/post-merge-gate.js +291 -0
- package/dist/policy-packs/builtin/post-merge-gate.js.map +1 -0
- package/dist/policy-packs/builtin/solution-acceptance-runtime.js +28 -13
- package/dist/policy-packs/builtin/solution-acceptance-runtime.js.map +1 -1
- package/dist/policy-packs/builtin/understanding-before-execution-runtime.d.ts +197 -24
- package/dist/policy-packs/builtin/understanding-before-execution-runtime.js +342 -40
- package/dist/policy-packs/builtin/understanding-before-execution-runtime.js.map +1 -1
- package/dist/policy-packs/builtin/understanding-before-execution.d.ts +26 -1
- package/dist/policy-packs/builtin/understanding-before-execution.js +302 -17
- package/dist/policy-packs/builtin/understanding-before-execution.js.map +1 -1
- package/dist/policy-packs/registry.d.ts +23 -2
- package/dist/policy-packs/registry.js +31 -2
- package/dist/policy-packs/registry.js.map +1 -1
- package/dist/policy-packs/ux-compare.d.ts +14 -0
- package/dist/policy-packs/ux-compare.js +58 -0
- package/dist/policy-packs/ux-compare.js.map +1 -0
- package/dist/policy-packs/ux-drift-check.d.ts +27 -0
- package/dist/policy-packs/ux-drift-check.js +78 -0
- package/dist/policy-packs/ux-drift-check.js.map +1 -0
- package/dist/probes/mcp.d.ts +13 -0
- package/dist/probes/mcp.js +57 -0
- package/dist/probes/mcp.js.map +1 -1
- package/dist/runtime/approval-signing.d.ts +82 -0
- package/dist/runtime/approval-signing.js +275 -0
- package/dist/runtime/approval-signing.js.map +1 -0
- package/dist/runtime/git-context.d.ts +50 -0
- package/dist/runtime/git-context.js +108 -1
- package/dist/runtime/git-context.js.map +1 -1
- package/dist/runtime/hermetic-spawn-guard.d.ts +25 -0
- package/dist/runtime/hermetic-spawn-guard.js +136 -0
- package/dist/runtime/hermetic-spawn-guard.js.map +1 -0
- package/dist/runtime/intercept.js +62 -5
- package/dist/runtime/intercept.js.map +1 -1
- package/dist/runtime/ledger-writer.d.ts +27 -0
- package/dist/runtime/ledger-writer.js +46 -0
- package/dist/runtime/ledger-writer.js.map +1 -0
- package/dist/runtime/pause-sentinel.js +14 -3
- package/dist/runtime/pause-sentinel.js.map +1 -1
- package/dist/runtime/read-only-bash.js +118 -0
- package/dist/runtime/read-only-bash.js.map +1 -1
- package/dist/runtime/recovery-git-commit.d.ts +22 -0
- package/dist/runtime/recovery-git-commit.js +284 -0
- package/dist/runtime/recovery-git-commit.js.map +1 -0
- package/dist/runtime/tool-name-aliases.d.ts +1 -0
- package/dist/runtime/tool-name-aliases.js +7 -1
- package/dist/runtime/tool-name-aliases.js.map +1 -1
- package/dist/schema/index.d.ts +94 -42
- package/dist/schema/index.js +5 -0
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/policies.d.ts +56 -44
- package/dist/schema/policies.js +79 -9
- package/dist/schema/policies.js.map +1 -1
- package/dist/schema/toolchain-parity.d.ts +18 -0
- package/dist/schema/toolchain-parity.js +35 -0
- package/dist/schema/toolchain-parity.js.map +1 -0
- package/package.json +4 -2
|
@@ -0,0 +1,618 @@
|
|
|
1
|
+
// `harness session-start toolchain-parity` — SessionStart hook entrypoint,
|
|
2
|
+
// third sibling of `harness session-start preflight` / `branch-check`.
|
|
3
|
+
//
|
|
4
|
+
// Anlass: the 2026-07-22 PATH-shim incident, where a machine ran an entire
|
|
5
|
+
// session unnoticed on Node 22 + understanding-gate 0.4.6 instead of the
|
|
6
|
+
// intended Node 26 + 0.4.9 — nothing on that machine ever compared its own
|
|
7
|
+
// toolchain against any other machine's. This producer closes that gap,
|
|
8
|
+
// purely advisorily:
|
|
9
|
+
//
|
|
10
|
+
// (a) writes a toolchain snapshot of THIS machine to
|
|
11
|
+
// `<machineStateDir>/<ownProfile>.json` (owner-writes-only — every
|
|
12
|
+
// OTHER `*.json` in that directory is read-only input, never
|
|
13
|
+
// touched);
|
|
14
|
+
// (b) compares the local LIVE toolchain state against every peer
|
|
15
|
+
// snapshot file already in that directory;
|
|
16
|
+
// (c) reports drift as stderr warning lines plus a single
|
|
17
|
+
// `toolchain-parity:ok` / `toolchain-parity:drift:<n>` ledger fact.
|
|
18
|
+
//
|
|
19
|
+
// Transport of the snapshot files BETWEEN machines is entirely
|
|
20
|
+
// agent-memory-sync's job (agent-memory PR #64, already shipped) — this
|
|
21
|
+
// module only ever reads/writes the local directory.
|
|
22
|
+
//
|
|
23
|
+
// SessionStart contract, same as the two siblings: `blocking:false`. Every
|
|
24
|
+
// failure path (not configured, mkdir/write/read failure, a broken peer
|
|
25
|
+
// file, a spawn timeout, a ledger-write failure) logs one line to stderr
|
|
26
|
+
// and exits 0. There is no "gate" this producer can leave closed — it is
|
|
27
|
+
// purely advisory, so degrading silently (well, LOUDLY on stderr, just
|
|
28
|
+
// never blocking) is always the right move.
|
|
29
|
+
import { execFile } from "node:child_process";
|
|
30
|
+
import * as fs from "node:fs";
|
|
31
|
+
import * as os from "node:os";
|
|
32
|
+
import * as path from "node:path";
|
|
33
|
+
import { readTopLevelMcpServers, resolveClaudeUserRegistryPath, } from "../../io/claude-mcp.js";
|
|
34
|
+
import { assertNoRealSpawnInTests } from "../../runtime/hermetic-spawn-guard.js";
|
|
35
|
+
import { resolveManifestLedgerWriter } from "../../runtime/ledger-writer.js";
|
|
36
|
+
import { resolveReadSessionId, } from "../../runtime/session-id.js";
|
|
37
|
+
import { loadManifest } from "../loader.js";
|
|
38
|
+
const FALLBACK_SESSION = "default";
|
|
39
|
+
const LEDGER_SOURCE = "harness-session-start-toolchain-parity";
|
|
40
|
+
const SNAPSHOT_SCHEMA_VERSION = 1;
|
|
41
|
+
// Individual spawn ceilings, not the expected duration: `node --version`
|
|
42
|
+
// and `npm ls -g --depth=0 --json` run IN PARALLEL (Promise.all in
|
|
43
|
+
// collectLocalSnapshot below), so the wall-time contribution of the two
|
|
44
|
+
// spawns together is max(nodeTimeoutMs, npmTimeoutMs), not their sum.
|
|
45
|
+
// Combined with two near-instant fs reads (OW-Kit version, MCP registry)
|
|
46
|
+
// and a ledger write, normal-case wall time targets well under 5s, matching
|
|
47
|
+
// the fast-path budget the `branch-check` sibling runs at (git-preflight's
|
|
48
|
+
// 70s budget is the outlier — it wraps a full external test-suite run,
|
|
49
|
+
// which this producer never does).
|
|
50
|
+
const DEFAULT_NODE_TIMEOUT_MS = 2_000;
|
|
51
|
+
const DEFAULT_NPM_GLOBALS_TIMEOUT_MS = 4_000;
|
|
52
|
+
async function readStdin(stream) {
|
|
53
|
+
return new Promise((resolve, reject) => {
|
|
54
|
+
let data = "";
|
|
55
|
+
stream.setEncoding("utf8");
|
|
56
|
+
stream.on("data", (chunk) => {
|
|
57
|
+
data += chunk;
|
|
58
|
+
});
|
|
59
|
+
stream.on("end", () => resolve(data));
|
|
60
|
+
stream.on("error", reject);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/** Profile names land in a filename; strip anything not filename-safe. */
|
|
64
|
+
function sanitizeProfileName(value) {
|
|
65
|
+
const cleaned = value.replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
66
|
+
return cleaned.length > 0 ? cleaned : "profile";
|
|
67
|
+
}
|
|
68
|
+
function isRecordOfStrings(x) {
|
|
69
|
+
return (typeof x === "object" &&
|
|
70
|
+
x !== null &&
|
|
71
|
+
!Array.isArray(x) &&
|
|
72
|
+
Object.values(x).every((v) => typeof v === "string"));
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Parse a stored snapshot JSON. Rejects (`ok:false`) only on the shapes
|
|
76
|
+
* that make comparison meaningless — not valid JSON, not an object,
|
|
77
|
+
* missing/invalid `profile` or `timestamp`. Every other field degrades
|
|
78
|
+
* leniently (missing/malformed -> empty/absent) rather than rejecting the
|
|
79
|
+
* whole file, since a peer snapshot written by a future schema version
|
|
80
|
+
* should still compare on the fields this version understands.
|
|
81
|
+
*/
|
|
82
|
+
export function parseSnapshotJson(raw) {
|
|
83
|
+
let parsed;
|
|
84
|
+
try {
|
|
85
|
+
parsed = JSON.parse(raw);
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
return { ok: false, reason: `not valid JSON: ${err.message}` };
|
|
89
|
+
}
|
|
90
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
91
|
+
return { ok: false, reason: "not a JSON object" };
|
|
92
|
+
}
|
|
93
|
+
const p = parsed;
|
|
94
|
+
if (typeof p["profile"] !== "string" || p["profile"].length === 0) {
|
|
95
|
+
return { ok: false, reason: "missing or invalid `profile` field" };
|
|
96
|
+
}
|
|
97
|
+
if (typeof p["timestamp"] !== "string" || Number.isNaN(Date.parse(p["timestamp"]))) {
|
|
98
|
+
return { ok: false, reason: "missing or invalid `timestamp` field" };
|
|
99
|
+
}
|
|
100
|
+
const snapshot = {
|
|
101
|
+
schemaVersion: SNAPSHOT_SCHEMA_VERSION,
|
|
102
|
+
profile: p["profile"],
|
|
103
|
+
timestamp: p["timestamp"],
|
|
104
|
+
npmGlobals: isRecordOfStrings(p["npmGlobals"]) ? p["npmGlobals"] : {},
|
|
105
|
+
mcpServers: Array.isArray(p["mcpServers"]) && p["mcpServers"].every((v) => typeof v === "string")
|
|
106
|
+
? p["mcpServers"]
|
|
107
|
+
: [],
|
|
108
|
+
};
|
|
109
|
+
if (typeof p["node"] === "string")
|
|
110
|
+
snapshot.node = p["node"];
|
|
111
|
+
if (typeof p["nodeError"] === "string")
|
|
112
|
+
snapshot.nodeError = p["nodeError"];
|
|
113
|
+
if (typeof p["npmGlobalsError"] === "string")
|
|
114
|
+
snapshot.npmGlobalsError = p["npmGlobalsError"];
|
|
115
|
+
if (typeof p["owKitVersion"] === "string")
|
|
116
|
+
snapshot.owKitVersion = p["owKitVersion"];
|
|
117
|
+
if (typeof p["owKitError"] === "string")
|
|
118
|
+
snapshot.owKitError = p["owKitError"];
|
|
119
|
+
if (typeof p["mcpServersError"] === "string")
|
|
120
|
+
snapshot.mcpServersError = p["mcpServersError"];
|
|
121
|
+
return { ok: true, snapshot };
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Hermetic guard (mirrors `realNpmExec` in src/cli/doctor/npm-bin-path.ts):
|
|
125
|
+
* asserts BEFORE touching `child_process` that we are not running under
|
|
126
|
+
* vitest without a test having injected `runNodeVersion`. This function has
|
|
127
|
+
* no try/catch around the assertion, and its only caller,
|
|
128
|
+
* `collectLocalSnapshot`, calls it (via the `runNodeVersion` param, defaulted
|
|
129
|
+
* to this function in `runSessionStartToolchainParity`) with no surrounding
|
|
130
|
+
* try/catch either — see src/runtime/hermetic-spawn-guard.ts for why that
|
|
131
|
+
* matters (a thrown `HermeticSpawnViolationError` must propagate, not be
|
|
132
|
+
* folded into an ordinary "collection failed" outcome).
|
|
133
|
+
*
|
|
134
|
+
* PATH-resolved deliberately: `execFile("node", ...)` does a PATH lookup for
|
|
135
|
+
* the literal string "node", NOT `process.execPath` — the entire point of
|
|
136
|
+
* this collector is capturing the PATH state of the *shell* the session
|
|
137
|
+
* runs in (the PATH-shim incident this task follows up on was exactly a
|
|
138
|
+
* PATH pointing at the wrong node), which `process.version` (the node
|
|
139
|
+
* running THIS harness process) would silently paper over.
|
|
140
|
+
*/
|
|
141
|
+
function realNodeVersionSpawn(timeoutMs) {
|
|
142
|
+
assertNoRealSpawnInTests("node --version", "Inject a fake `runNodeVersion` (SessionStartToolchainParityOptions.runNodeVersion) instead of exercising the real spawn path.");
|
|
143
|
+
return new Promise((resolve) => {
|
|
144
|
+
execFile("node", ["--version"], { timeout: timeoutMs, encoding: "utf8" }, (err, stdout) => {
|
|
145
|
+
const text = (stdout ?? "").trim();
|
|
146
|
+
if (text.length > 0) {
|
|
147
|
+
resolve({ ok: true, version: text });
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (err) {
|
|
151
|
+
const e = err;
|
|
152
|
+
if (e.code === "ENOENT") {
|
|
153
|
+
resolve({ ok: false, reason: "`node` not on PATH" });
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (e.killed) {
|
|
157
|
+
resolve({ ok: false, reason: `\`node --version\` timed out after ${timeoutMs}ms` });
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
resolve({ ok: false, reason: `\`node --version\` failed: ${e.message}` });
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
resolve({ ok: false, reason: "`node --version` produced no output" });
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Hermetic guard, same shape/rationale as {@link realNodeVersionSpawn} —
|
|
169
|
+
* see that function's doc. Tolerant of a non-zero exit the same way
|
|
170
|
+
* `spawnPreflight` (session-start/index.ts) is tolerant of `preflight run`'s
|
|
171
|
+
* exit code: `npm ls -g` can exit non-zero on an unrelated extraneous/
|
|
172
|
+
* invalid global entry while still emitting a perfectly parseable
|
|
173
|
+
* `dependencies` JSON block, so a parseable stdout wins over the exit code.
|
|
174
|
+
*/
|
|
175
|
+
function realNpmGlobalsSpawn(timeoutMs) {
|
|
176
|
+
assertNoRealSpawnInTests("npm ls -g --depth=0 --json", "Inject a fake `runNpmGlobals` (SessionStartToolchainParityOptions.runNpmGlobals) instead of exercising the real spawn path.");
|
|
177
|
+
return new Promise((resolve) => {
|
|
178
|
+
execFile("npm", ["ls", "-g", "--depth=0", "--json"], { timeout: timeoutMs, maxBuffer: 8 * 1024 * 1024, encoding: "utf8" }, (err, stdout) => {
|
|
179
|
+
const text = (stdout ?? "").trim();
|
|
180
|
+
if (text.length > 0) {
|
|
181
|
+
try {
|
|
182
|
+
const parsed = JSON.parse(text);
|
|
183
|
+
const packages = {};
|
|
184
|
+
for (const [name, entry] of Object.entries(parsed.dependencies ?? {})) {
|
|
185
|
+
if (typeof entry?.version === "string")
|
|
186
|
+
packages[name] = entry.version;
|
|
187
|
+
}
|
|
188
|
+
resolve({ ok: true, packages });
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
/* fall through to the error path */
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (err) {
|
|
196
|
+
const e = err;
|
|
197
|
+
if (e.code === "ENOENT") {
|
|
198
|
+
resolve({ ok: false, reason: "`npm` not on PATH" });
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (e.killed) {
|
|
202
|
+
resolve({
|
|
203
|
+
ok: false,
|
|
204
|
+
reason: `\`npm ls -g --depth=0 --json\` timed out after ${timeoutMs}ms`,
|
|
205
|
+
});
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
resolve({ ok: false, reason: `\`npm ls -g\` failed: ${e.message}` });
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
resolve({ ok: false, reason: "`npm ls -g --depth=0 --json` produced no parseable JSON" });
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Read `<workspaceRoot>/.ai/workflow/manifest.json`'s `version` field
|
|
217
|
+
* (the orchestrator-workflow kit's own version marker). A missing file is
|
|
218
|
+
* the expected common case (most repos are not OW-kit-managed) and is
|
|
219
|
+
* NOT an error — it degrades silently to `{}`. Malformed JSON or a
|
|
220
|
+
* non-string `version` field on a manifest that DOES exist is noteworthy
|
|
221
|
+
* (something is there but broken), so that degrades to `{ error }`.
|
|
222
|
+
*/
|
|
223
|
+
function realReadOwKitVersion(workspaceRoot) {
|
|
224
|
+
const manifestPath = path.join(workspaceRoot, ".ai", "workflow", "manifest.json");
|
|
225
|
+
let raw;
|
|
226
|
+
try {
|
|
227
|
+
raw = fs.readFileSync(manifestPath, "utf8");
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
const e = err;
|
|
231
|
+
if (e.code === "ENOENT")
|
|
232
|
+
return {};
|
|
233
|
+
return { error: `cannot read ${manifestPath}: ${e.message}` };
|
|
234
|
+
}
|
|
235
|
+
let parsed;
|
|
236
|
+
try {
|
|
237
|
+
parsed = JSON.parse(raw);
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
return { error: `${manifestPath} is not valid JSON: ${err.message}` };
|
|
241
|
+
}
|
|
242
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
243
|
+
return { error: `${manifestPath} is not a JSON object` };
|
|
244
|
+
}
|
|
245
|
+
const version = parsed["version"];
|
|
246
|
+
if (typeof version !== "string" || version.length === 0) {
|
|
247
|
+
return { error: `${manifestPath} has no string \`version\` field` };
|
|
248
|
+
}
|
|
249
|
+
return { version };
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* MCP server names from Claude Code's user-scope registry — a pure FILE
|
|
253
|
+
* READ (never a spawn), reusing the exact primitive `harness doctor`'s
|
|
254
|
+
* claude-mcp check ultimately compares against
|
|
255
|
+
* (`resolveClaudeUserRegistryPath` + `readTopLevelMcpServers` in
|
|
256
|
+
* src/io/claude-mcp.ts — the same functions `adopt`/`detect` use for the
|
|
257
|
+
* same "read the effective registration from outside io/claude-mcp.ts"
|
|
258
|
+
* purpose). Deliberately NOT `claude mcp list` (a spawn): the brief calls
|
|
259
|
+
* for a file-read source for the NAMES here, and this is it.
|
|
260
|
+
*/
|
|
261
|
+
function realReadMcpServerNames() {
|
|
262
|
+
const registryPath = resolveClaudeUserRegistryPath();
|
|
263
|
+
const { servers, error } = readTopLevelMcpServers(registryPath);
|
|
264
|
+
if (error !== null)
|
|
265
|
+
return { names: [], error };
|
|
266
|
+
return { names: Object.keys(servers).sort() };
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Collect the local, LIVE toolchain snapshot. Never throws (every
|
|
270
|
+
* collector above degrades to `{ok:false,reason}` / `{error}` instead of
|
|
271
|
+
* rejecting/throwing) — a collection failure is reported both inline on
|
|
272
|
+
* the returned snapshot (the matching `*Error` field) AND as a `notes`
|
|
273
|
+
* line for the caller to log, but never stops the other collectors from
|
|
274
|
+
* running. node/npm run in PARALLEL (see the timeout constants' comment
|
|
275
|
+
* above for why).
|
|
276
|
+
*/
|
|
277
|
+
async function collectLocalSnapshot(opts) {
|
|
278
|
+
const notes = [];
|
|
279
|
+
const [nodeResult, npmResult] = await Promise.all([
|
|
280
|
+
opts.runNodeVersion(opts.nodeTimeoutMs),
|
|
281
|
+
opts.runNpmGlobals(opts.npmTimeoutMs),
|
|
282
|
+
]);
|
|
283
|
+
const owKit = opts.readOwKitVersion(opts.workspaceRoot);
|
|
284
|
+
const mcp = opts.readMcpServerNames();
|
|
285
|
+
const snapshot = {
|
|
286
|
+
schemaVersion: SNAPSHOT_SCHEMA_VERSION,
|
|
287
|
+
profile: opts.profile,
|
|
288
|
+
timestamp: opts.now.toISOString(),
|
|
289
|
+
npmGlobals: {},
|
|
290
|
+
mcpServers: [],
|
|
291
|
+
};
|
|
292
|
+
if (nodeResult.ok) {
|
|
293
|
+
snapshot.node = nodeResult.version;
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
snapshot.nodeError = nodeResult.reason;
|
|
297
|
+
notes.push(`node --version: ${nodeResult.reason}`);
|
|
298
|
+
}
|
|
299
|
+
if (npmResult.ok) {
|
|
300
|
+
snapshot.npmGlobals = npmResult.packages;
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
snapshot.npmGlobalsError = npmResult.reason;
|
|
304
|
+
notes.push(`npm ls -g: ${npmResult.reason}`);
|
|
305
|
+
}
|
|
306
|
+
if (owKit.version !== undefined)
|
|
307
|
+
snapshot.owKitVersion = owKit.version;
|
|
308
|
+
if (owKit.error !== undefined) {
|
|
309
|
+
snapshot.owKitError = owKit.error;
|
|
310
|
+
notes.push(`OW-Kit version: ${owKit.error}`);
|
|
311
|
+
}
|
|
312
|
+
if (mcp.error !== undefined) {
|
|
313
|
+
snapshot.mcpServersError = mcp.error;
|
|
314
|
+
notes.push(`MCP server names: ${mcp.error}`);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
snapshot.mcpServers = mcp.names;
|
|
318
|
+
}
|
|
319
|
+
return { snapshot, notes };
|
|
320
|
+
}
|
|
321
|
+
// ---------------------------------------------------------------------
|
|
322
|
+
// Snapshot write (own profile only) + peer comparison
|
|
323
|
+
// ---------------------------------------------------------------------
|
|
324
|
+
/**
|
|
325
|
+
* Write ONLY `<machineStateDir>/<ownFileName>` (mkdir -p first). Never
|
|
326
|
+
* touches any other file in the directory — the caller passes exactly
|
|
327
|
+
* `sanitizeProfileName(profile) + ".json"`, so there is no path this
|
|
328
|
+
* function could take that reaches a peer's file.
|
|
329
|
+
*/
|
|
330
|
+
function writeOwnSnapshot(machineStateDir, ownFileName, snapshot) {
|
|
331
|
+
const filePath = path.join(machineStateDir, ownFileName);
|
|
332
|
+
try {
|
|
333
|
+
fs.writeFileSync(filePath, `${JSON.stringify(snapshot, null, 2)}\n`, "utf8");
|
|
334
|
+
return { ok: true, path: filePath };
|
|
335
|
+
}
|
|
336
|
+
catch (err) {
|
|
337
|
+
return { ok: false, reason: err.message };
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
/** `"just now"` / `"<n>m"` / `"<n>h"` / `"<n>d"` — coarse, human-scannable. */
|
|
341
|
+
export function formatSnapshotAge(ageMs) {
|
|
342
|
+
if (ageMs < 60_000)
|
|
343
|
+
return "just now";
|
|
344
|
+
const minutes = Math.floor(ageMs / 60_000);
|
|
345
|
+
if (minutes < 60)
|
|
346
|
+
return `${minutes}m`;
|
|
347
|
+
const hours = Math.floor(minutes / 60);
|
|
348
|
+
if (hours < 48)
|
|
349
|
+
return `${hours}h`;
|
|
350
|
+
return `${Math.floor(hours / 24)}d`;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Compare the local LIVE snapshot against one peer's stored snapshot.
|
|
354
|
+
* Node / OW-Kit drift only fires when BOTH sides collected that field
|
|
355
|
+
* successfully (an unavailable field reads as "unknown", not "match" or
|
|
356
|
+
* "drift"). The npm-globals and MCP-name comparisons additionally gate on
|
|
357
|
+
* the WHOLE field having collected without error on both sides — an
|
|
358
|
+
* `npmGlobalsError`/`mcpServersError` on either side means that side's map
|
|
359
|
+
* is "unknown", not "empty", and treating it as empty would fabricate a
|
|
360
|
+
* wall of "missing on N packages" drift instead of the real gap (which the
|
|
361
|
+
* caller's own note()s already surface separately, from collectLocalSnapshot's
|
|
362
|
+
* `notes` and the peer-unreadable path).
|
|
363
|
+
*/
|
|
364
|
+
export function compareToPeer(local, peer, now) {
|
|
365
|
+
const drift = [];
|
|
366
|
+
const peerProfile = peer.profile;
|
|
367
|
+
if (local.node !== undefined && peer.node !== undefined && local.node !== peer.node) {
|
|
368
|
+
drift.push({
|
|
369
|
+
kind: "node",
|
|
370
|
+
message: `node version: local ${local.node} vs peer ${peerProfile} ${peer.node}`,
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
if (local.owKitVersion !== undefined &&
|
|
374
|
+
peer.owKitVersion !== undefined &&
|
|
375
|
+
local.owKitVersion !== peer.owKitVersion) {
|
|
376
|
+
drift.push({
|
|
377
|
+
kind: "ow_kit",
|
|
378
|
+
message: `orchestrator-workflow kit version: local ${local.owKitVersion} vs peer ${peerProfile} ${peer.owKitVersion}`,
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
if (local.npmGlobalsError === undefined && peer.npmGlobalsError === undefined) {
|
|
382
|
+
const names = [...new Set([...Object.keys(local.npmGlobals), ...Object.keys(peer.npmGlobals)])].sort();
|
|
383
|
+
for (const name of names) {
|
|
384
|
+
const lv = local.npmGlobals[name];
|
|
385
|
+
const pv = peer.npmGlobals[name];
|
|
386
|
+
if (lv !== undefined && pv !== undefined) {
|
|
387
|
+
if (lv !== pv) {
|
|
388
|
+
drift.push({
|
|
389
|
+
kind: "npm_package_version",
|
|
390
|
+
message: `npm global \`${name}\`: local ${lv} vs peer ${peerProfile} ${pv}`,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
else if (lv !== undefined) {
|
|
395
|
+
drift.push({
|
|
396
|
+
kind: "npm_package_missing_peer",
|
|
397
|
+
message: `npm global \`${name}\`: local ${lv}, missing on peer ${peerProfile}`,
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
else if (pv !== undefined) {
|
|
401
|
+
drift.push({
|
|
402
|
+
kind: "npm_package_missing_local",
|
|
403
|
+
message: `npm global \`${name}\`: missing locally, peer ${peerProfile} has ${pv}`,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (local.mcpServersError === undefined && peer.mcpServersError === undefined) {
|
|
409
|
+
const localSet = new Set(local.mcpServers);
|
|
410
|
+
const peerSet = new Set(peer.mcpServers);
|
|
411
|
+
const names = [...new Set([...localSet, ...peerSet])].sort();
|
|
412
|
+
for (const name of names) {
|
|
413
|
+
if (localSet.has(name) && !peerSet.has(name)) {
|
|
414
|
+
drift.push({
|
|
415
|
+
kind: "mcp_missing_peer",
|
|
416
|
+
message: `mcp server \`${name}\`: registered locally, missing on peer ${peerProfile}`,
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
else if (!localSet.has(name) && peerSet.has(name)) {
|
|
420
|
+
drift.push({
|
|
421
|
+
kind: "mcp_missing_local",
|
|
422
|
+
message: `mcp server \`${name}\`: missing locally, registered on peer ${peerProfile}`,
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
const peerTimeMs = Date.parse(peer.timestamp);
|
|
428
|
+
const ageMs = Number.isFinite(peerTimeMs) ? Math.max(0, now.getTime() - peerTimeMs) : 0;
|
|
429
|
+
return { peerProfile, ageMs, drift };
|
|
430
|
+
}
|
|
431
|
+
function defaultMachineStateDir() {
|
|
432
|
+
return path.join(os.homedir(), ".harness", "machine-state");
|
|
433
|
+
}
|
|
434
|
+
export async function runSessionStartToolchainParity(opts = {}) {
|
|
435
|
+
const stdin = opts.stdin ?? process.stdin;
|
|
436
|
+
const stderr = opts.stderr ?? process.stderr;
|
|
437
|
+
const now = opts.now ?? new Date();
|
|
438
|
+
const nodeTimeoutMs = opts.nodeTimeoutMs ?? DEFAULT_NODE_TIMEOUT_MS;
|
|
439
|
+
const npmTimeoutMs = opts.npmTimeoutMs ?? DEFAULT_NPM_GLOBALS_TIMEOUT_MS;
|
|
440
|
+
const note = (msg) => {
|
|
441
|
+
stderr.write(`harness session-start toolchain-parity: ${msg}\n`);
|
|
442
|
+
};
|
|
443
|
+
const done = (wrote, profile, peersCompared, driftCount, sessionId, sessionSource, reason) => ({
|
|
444
|
+
exitCode: 0,
|
|
445
|
+
wrote,
|
|
446
|
+
profile,
|
|
447
|
+
peersCompared,
|
|
448
|
+
driftCount,
|
|
449
|
+
sessionId,
|
|
450
|
+
sessionSource,
|
|
451
|
+
...(reason !== undefined && { reason }),
|
|
452
|
+
});
|
|
453
|
+
let event;
|
|
454
|
+
try {
|
|
455
|
+
event = JSON.parse((await readStdin(stdin)).trim() || "{}");
|
|
456
|
+
}
|
|
457
|
+
catch (err) {
|
|
458
|
+
const reason = `malformed event JSON: ${err.message}`;
|
|
459
|
+
note(reason);
|
|
460
|
+
return done(false, "", 0, 0, FALLBACK_SESSION, "default", reason);
|
|
461
|
+
}
|
|
462
|
+
const cwd = typeof opts.cwd === "string" && opts.cwd.length > 0
|
|
463
|
+
? opts.cwd
|
|
464
|
+
: typeof event.cwd === "string" && event.cwd.length > 0
|
|
465
|
+
? event.cwd
|
|
466
|
+
: process.cwd();
|
|
467
|
+
// Session id resolution: same precedence chain as the two siblings, so
|
|
468
|
+
// all three producers stay symmetric.
|
|
469
|
+
const explicit = typeof opts.session === "string" && opts.session.length > 0
|
|
470
|
+
? opts.session
|
|
471
|
+
: typeof event.session_id === "string" && event.session_id.length > 0
|
|
472
|
+
? event.session_id
|
|
473
|
+
: undefined;
|
|
474
|
+
const resolveSession = opts.resolveSession ?? resolveReadSessionId;
|
|
475
|
+
const sessionId = resolveSession(explicit, {});
|
|
476
|
+
const sessionSource = typeof opts.session === "string" && opts.session.length > 0
|
|
477
|
+
? "flag"
|
|
478
|
+
: typeof event.session_id === "string" && event.session_id.length > 0
|
|
479
|
+
? "stdin"
|
|
480
|
+
: sessionId === FALLBACK_SESSION
|
|
481
|
+
? "default"
|
|
482
|
+
: (typeof process.env.CLAUDE_CODE_SESSION_ID === "string" &&
|
|
483
|
+
process.env.CLAUDE_CODE_SESSION_ID === sessionId) ||
|
|
484
|
+
(typeof process.env.CLAUDE_SESSION_ID === "string" &&
|
|
485
|
+
process.env.CLAUDE_SESSION_ID === sessionId)
|
|
486
|
+
? "env"
|
|
487
|
+
: "transcript";
|
|
488
|
+
let manifest;
|
|
489
|
+
if (opts.manifest) {
|
|
490
|
+
manifest = opts.manifest;
|
|
491
|
+
}
|
|
492
|
+
else {
|
|
493
|
+
try {
|
|
494
|
+
manifest = loadManifest(opts).manifest;
|
|
495
|
+
}
|
|
496
|
+
catch (err) {
|
|
497
|
+
const reason = `manifest load failed: ${err.message}`;
|
|
498
|
+
note(reason);
|
|
499
|
+
return done(false, "", 0, 0, sessionId, sessionSource, reason);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
const config = manifest.toolchain_parity;
|
|
503
|
+
if (!config.enabled) {
|
|
504
|
+
const reason = "not configured (add `toolchain_parity: { enabled: true }` to harness.yaml); skipping";
|
|
505
|
+
note(reason);
|
|
506
|
+
return done(false, "", 0, 0, sessionId, sessionSource, reason);
|
|
507
|
+
}
|
|
508
|
+
const machineStateDir = config.machine_state_dir ?? defaultMachineStateDir();
|
|
509
|
+
const profile = config.profile ?? sanitizeProfileName(os.hostname());
|
|
510
|
+
const workspaceRoot = config.workspace_root ?? cwd;
|
|
511
|
+
const ownFileName = `${sanitizeProfileName(profile)}.json`;
|
|
512
|
+
try {
|
|
513
|
+
fs.mkdirSync(machineStateDir, { recursive: true });
|
|
514
|
+
}
|
|
515
|
+
catch (err) {
|
|
516
|
+
const reason = `cannot create/access machine-state dir ${machineStateDir}: ${err.message}`;
|
|
517
|
+
note(reason);
|
|
518
|
+
return done(false, profile, 0, 0, sessionId, sessionSource, reason);
|
|
519
|
+
}
|
|
520
|
+
const runNodeVersion = opts.runNodeVersion ?? realNodeVersionSpawn;
|
|
521
|
+
const runNpmGlobals = opts.runNpmGlobals ?? realNpmGlobalsSpawn;
|
|
522
|
+
const readOwKitVersion = opts.readOwKitVersion ?? realReadOwKitVersion;
|
|
523
|
+
const readMcpServerNames = opts.readMcpServerNames ?? realReadMcpServerNames;
|
|
524
|
+
const { snapshot: localSnapshot, notes } = await collectLocalSnapshot({
|
|
525
|
+
profile,
|
|
526
|
+
now,
|
|
527
|
+
workspaceRoot,
|
|
528
|
+
nodeTimeoutMs,
|
|
529
|
+
npmTimeoutMs,
|
|
530
|
+
runNodeVersion,
|
|
531
|
+
runNpmGlobals,
|
|
532
|
+
readOwKitVersion,
|
|
533
|
+
readMcpServerNames,
|
|
534
|
+
});
|
|
535
|
+
for (const n of notes)
|
|
536
|
+
note(n);
|
|
537
|
+
const written = writeOwnSnapshot(machineStateDir, ownFileName, localSnapshot);
|
|
538
|
+
if (!written.ok) {
|
|
539
|
+
note(`could not write own snapshot: ${written.reason}`);
|
|
540
|
+
}
|
|
541
|
+
let entries;
|
|
542
|
+
try {
|
|
543
|
+
entries = fs.readdirSync(machineStateDir);
|
|
544
|
+
}
|
|
545
|
+
catch (err) {
|
|
546
|
+
const reason = `cannot list machine-state dir ${machineStateDir}: ${err.message}`;
|
|
547
|
+
note(reason);
|
|
548
|
+
return done(false, profile, 0, 0, sessionId, sessionSource, reason);
|
|
549
|
+
}
|
|
550
|
+
const peerFiles = entries.filter((name) => name.endsWith(".json") && name !== ownFileName).sort();
|
|
551
|
+
if (peerFiles.length === 0) {
|
|
552
|
+
const reason = `no peer snapshots found in ${machineStateDir}; nothing to compare (normal for the first machine, or before any peer has run this companion)`;
|
|
553
|
+
note(reason);
|
|
554
|
+
return done(false, profile, 0, 0, sessionId, sessionSource, reason);
|
|
555
|
+
}
|
|
556
|
+
let peersCompared = 0;
|
|
557
|
+
let driftTotal = 0;
|
|
558
|
+
for (const fileName of peerFiles) {
|
|
559
|
+
const filePath = path.join(machineStateDir, fileName);
|
|
560
|
+
let raw;
|
|
561
|
+
try {
|
|
562
|
+
raw = fs.readFileSync(filePath, "utf8");
|
|
563
|
+
}
|
|
564
|
+
catch (err) {
|
|
565
|
+
note(`peer snapshot ${fileName} unreadable: ${err.message}`);
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
const parsed = parseSnapshotJson(raw);
|
|
569
|
+
if (!parsed.ok) {
|
|
570
|
+
note(`peer snapshot ${fileName} is corrupt: ${parsed.reason}`);
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
573
|
+
const comparison = compareToPeer(localSnapshot, parsed.snapshot, now);
|
|
574
|
+
peersCompared += 1;
|
|
575
|
+
driftTotal += comparison.drift.length;
|
|
576
|
+
const age = formatSnapshotAge(comparison.ageMs);
|
|
577
|
+
if (comparison.drift.length === 0) {
|
|
578
|
+
note(`ok against ${comparison.peerProfile} (snapshot age ${age})`);
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
note(`drift:${comparison.drift.length} against ${comparison.peerProfile} (snapshot age ${age})`);
|
|
582
|
+
for (const item of comparison.drift)
|
|
583
|
+
note(`drift — ${item.message}`);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
if (peersCompared === 0) {
|
|
587
|
+
const reason = `no comparable peer snapshots (all ${peerFiles.length} peer file(s) in ${machineStateDir} were unreadable/corrupt)`;
|
|
588
|
+
note(reason);
|
|
589
|
+
return done(false, profile, 0, 0, sessionId, sessionSource, reason);
|
|
590
|
+
}
|
|
591
|
+
const content = driftTotal === 0 ? "toolchain-parity:ok" : `toolchain-parity:drift:${driftTotal}`;
|
|
592
|
+
let writeLedger = opts.writeLedger;
|
|
593
|
+
if (!writeLedger) {
|
|
594
|
+
const resolved = resolveManifestLedgerWriter(manifest, {
|
|
595
|
+
...(opts.ledgerTimeoutMs !== undefined ? { ledgerTimeoutMs: opts.ledgerTimeoutMs } : {}),
|
|
596
|
+
});
|
|
597
|
+
if (!resolved.ok) {
|
|
598
|
+
const reason = `${resolved.reason}; cannot record ${content}`;
|
|
599
|
+
note(reason);
|
|
600
|
+
return done(false, profile, peersCompared, driftTotal, sessionId, sessionSource, reason);
|
|
601
|
+
}
|
|
602
|
+
writeLedger = resolved.write;
|
|
603
|
+
}
|
|
604
|
+
const result = await writeLedger({ sessionId, content, source: LEDGER_SOURCE });
|
|
605
|
+
if (!result.ok) {
|
|
606
|
+
const reason = `ledger write failed: ${result.reason ?? "unknown error"}`;
|
|
607
|
+
note(reason);
|
|
608
|
+
return done(false, profile, peersCompared, driftTotal, sessionId, sessionSource, reason);
|
|
609
|
+
}
|
|
610
|
+
note(`recorded ${content} for session ${sessionId}`);
|
|
611
|
+
if (sessionSource === "default") {
|
|
612
|
+
note("WARNING: session resolved to the literal \"default\". This tag is audit-only (no gate " +
|
|
613
|
+
"consumes toolchain-parity: yet), but pipe SessionStart event JSON on stdin, export " +
|
|
614
|
+
"$CLAUDE_SESSION_ID, or pass --session <id> for manual / scripted use to keep the audit trail useful.");
|
|
615
|
+
}
|
|
616
|
+
return done(true, profile, peersCompared, driftTotal, sessionId, sessionSource);
|
|
617
|
+
}
|
|
618
|
+
//# sourceMappingURL=toolchain-parity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolchain-parity.js","sourceRoot":"","sources":["../../../src/cli/session-start/toolchain-parity.ts"],"names":[],"mappings":"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"}
|