patchwork-os 1.2.0-beta.2.canary.849 → 1.2.0-beta.2.canary.850
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.
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `patchwork doctor acceptance` — does the INSTALLED package BEHAVE?
|
|
3
|
+
*
|
|
4
|
+
* `patchwork doctor` answers "is the running code the installed code?" by
|
|
5
|
+
* comparing timestamps. That is necessary and not sufficient: deploys were
|
|
6
|
+
* verified by grepping `dist/` for one symbol, and a deploy that silently did
|
|
7
|
+
* not happen (a git ref-lock race) was only noticed later. A string being
|
|
8
|
+
* present in a file is not a behaviour being present in a process.
|
|
9
|
+
*
|
|
10
|
+
* This runs the real runtime entrypoints — the flat runner (`runYamlRecipe`),
|
|
11
|
+
* the policy matrix, the profile-aware kill switch, `http.post`'s uncertain-
|
|
12
|
+
* outcome contract, `replayFlatMockedRun` and `RecipeRunLog.getByTaskId` —
|
|
13
|
+
* in-process, and asserts what they DO.
|
|
14
|
+
*
|
|
15
|
+
* ## Safe on a live production machine, by construction
|
|
16
|
+
*
|
|
17
|
+
* - Every behavioural check runs against a fresh temp `PATCHWORK_HOME` (and a
|
|
18
|
+
* temp `HOME`, so anything resolving `os.homedir()` lands in the sandbox
|
|
19
|
+
* too). The operator's config, flags and ledgers are never read or written;
|
|
20
|
+
* the identity check runs FIRST, before the swap, and reads only lock files
|
|
21
|
+
* and one mtime.
|
|
22
|
+
* - Network is loopback only: a server this command starts on 127.0.0.1.
|
|
23
|
+
* No connector, no model call, no git remote.
|
|
24
|
+
* - Approvals are answered by an in-process recorder, never the bridge queue.
|
|
25
|
+
* - Everything is restored and the sandbox removed in `finally`, including
|
|
26
|
+
* on failure.
|
|
27
|
+
*
|
|
28
|
+
* A separate subcommand from `doctor` for the same reason `doctor health` is:
|
|
29
|
+
* `patchwork doctor && echo deployed` is a real shape, and its exit code must
|
|
30
|
+
* not change meaning.
|
|
31
|
+
*/
|
|
32
|
+
export interface AcceptanceCheck {
|
|
33
|
+
name: string;
|
|
34
|
+
ok: boolean;
|
|
35
|
+
detail: string;
|
|
36
|
+
}
|
|
37
|
+
export interface AcceptanceReport {
|
|
38
|
+
ok: boolean;
|
|
39
|
+
total: number;
|
|
40
|
+
passed: number;
|
|
41
|
+
checks: AcceptanceCheck[];
|
|
42
|
+
}
|
|
43
|
+
export interface AcceptanceOptions {
|
|
44
|
+
/** Lock directory for the identity check (default: the real bridge lock dir). */
|
|
45
|
+
lockDir?: string;
|
|
46
|
+
/** Override the installed build time (tests). */
|
|
47
|
+
buildTimeMs?: number;
|
|
48
|
+
/** Parent directory for the sandbox (default: os.tmpdir()). */
|
|
49
|
+
tmpRoot?: string;
|
|
50
|
+
}
|
|
51
|
+
export declare function runAcceptance(opts?: AcceptanceOptions): Promise<AcceptanceReport>;
|
|
52
|
+
export declare function formatAcceptance(r: AcceptanceReport): string;
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `patchwork doctor acceptance` — does the INSTALLED package BEHAVE?
|
|
3
|
+
*
|
|
4
|
+
* `patchwork doctor` answers "is the running code the installed code?" by
|
|
5
|
+
* comparing timestamps. That is necessary and not sufficient: deploys were
|
|
6
|
+
* verified by grepping `dist/` for one symbol, and a deploy that silently did
|
|
7
|
+
* not happen (a git ref-lock race) was only noticed later. A string being
|
|
8
|
+
* present in a file is not a behaviour being present in a process.
|
|
9
|
+
*
|
|
10
|
+
* This runs the real runtime entrypoints — the flat runner (`runYamlRecipe`),
|
|
11
|
+
* the policy matrix, the profile-aware kill switch, `http.post`'s uncertain-
|
|
12
|
+
* outcome contract, `replayFlatMockedRun` and `RecipeRunLog.getByTaskId` —
|
|
13
|
+
* in-process, and asserts what they DO.
|
|
14
|
+
*
|
|
15
|
+
* ## Safe on a live production machine, by construction
|
|
16
|
+
*
|
|
17
|
+
* - Every behavioural check runs against a fresh temp `PATCHWORK_HOME` (and a
|
|
18
|
+
* temp `HOME`, so anything resolving `os.homedir()` lands in the sandbox
|
|
19
|
+
* too). The operator's config, flags and ledgers are never read or written;
|
|
20
|
+
* the identity check runs FIRST, before the swap, and reads only lock files
|
|
21
|
+
* and one mtime.
|
|
22
|
+
* - Network is loopback only: a server this command starts on 127.0.0.1.
|
|
23
|
+
* No connector, no model call, no git remote.
|
|
24
|
+
* - Approvals are answered by an in-process recorder, never the bridge queue.
|
|
25
|
+
* - Everything is restored and the sandbox removed in `finally`, including
|
|
26
|
+
* on failure.
|
|
27
|
+
*
|
|
28
|
+
* A separate subcommand from `doctor` for the same reason `doctor health` is:
|
|
29
|
+
* `patchwork doctor && echo deployed` is a real shape, and its exit code must
|
|
30
|
+
* not change meaning.
|
|
31
|
+
*/
|
|
32
|
+
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync, } from "node:fs";
|
|
33
|
+
import { createServer } from "node:http";
|
|
34
|
+
import os from "node:os";
|
|
35
|
+
import path from "node:path";
|
|
36
|
+
const RECIPE_PREFIX = "acceptance-probe";
|
|
37
|
+
async function startTarget() {
|
|
38
|
+
const t = { received: 0, sockets: new Set() };
|
|
39
|
+
t.server = createServer((req, res) => {
|
|
40
|
+
t.sockets.add(req.socket);
|
|
41
|
+
req.resume();
|
|
42
|
+
req.on("end", () => {
|
|
43
|
+
t.received++;
|
|
44
|
+
if (req.url === "/lost") {
|
|
45
|
+
// Accepted the write, then the response is lost.
|
|
46
|
+
req.socket.destroy();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
res.writeHead(200, { "content-type": "application/json" });
|
|
50
|
+
res.end('{"id":"acc-0001"}');
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
await new Promise((resolve) => t.server.listen(0, "127.0.0.1", () => resolve()));
|
|
54
|
+
t.url = `http://127.0.0.1:${t.server.address().port}`;
|
|
55
|
+
return t;
|
|
56
|
+
}
|
|
57
|
+
async function stopTarget(t) {
|
|
58
|
+
if (!t)
|
|
59
|
+
return;
|
|
60
|
+
for (const s of t.sockets)
|
|
61
|
+
s.destroy();
|
|
62
|
+
await new Promise((resolve) => t.server.close(() => resolve()));
|
|
63
|
+
}
|
|
64
|
+
async function identityCheck(opts) {
|
|
65
|
+
const { assessDeploymentFreshness, discoverLocks, installedBuildTimeMs } = await import("../deploymentFreshness.js");
|
|
66
|
+
const { PACKAGE_VERSION } = await import("../version.js");
|
|
67
|
+
const buildTimeMs = opts.buildTimeMs ?? installedBuildTimeMs();
|
|
68
|
+
if (buildTimeMs === undefined) {
|
|
69
|
+
return {
|
|
70
|
+
name: "identity",
|
|
71
|
+
ok: false,
|
|
72
|
+
detail: `version ${PACKAGE_VERSION}; no installed build could be located`,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const report = assessDeploymentFreshness({
|
|
76
|
+
locks: discoverLocks(opts.lockDir),
|
|
77
|
+
buildTimeMs,
|
|
78
|
+
isAlive: (pid) => {
|
|
79
|
+
try {
|
|
80
|
+
process.kill(pid, 0);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
const stale = report.findings.filter((f) => f.state === "stale-code").length;
|
|
89
|
+
const live = report.findings.filter((f) => f.state === "fresh" || f.state === "stale-code").length;
|
|
90
|
+
const detail = `version ${PACKAGE_VERSION}; built ${new Date(buildTimeMs).toISOString()}; ` +
|
|
91
|
+
"commit not recorded (the package carries no build commit); " +
|
|
92
|
+
`${live} live bridge(s), ${stale} predating the install`;
|
|
93
|
+
return { name: "identity", ok: !report.unhealthy, detail };
|
|
94
|
+
}
|
|
95
|
+
export async function runAcceptance(opts = {}) {
|
|
96
|
+
const checks = [];
|
|
97
|
+
const record = (name, ok, detail) => checks.push({ name, ok, detail });
|
|
98
|
+
const guard = async (name, fn) => {
|
|
99
|
+
try {
|
|
100
|
+
const [ok, detail] = await fn();
|
|
101
|
+
record(name, ok, detail);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
record(name, false, `threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
// 1. Identity — BEFORE the sandbox swap, since it reads real lock files.
|
|
108
|
+
try {
|
|
109
|
+
checks.push(await identityCheck(opts));
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
record("identity", false, `threw: ${String(err)}`);
|
|
113
|
+
}
|
|
114
|
+
const root = mkdtempSync(path.join(opts.tmpRoot ?? os.tmpdir(), "patchwork-acceptance-"));
|
|
115
|
+
const home = path.join(root, "patchwork-home");
|
|
116
|
+
const osHome = path.join(root, "os-home");
|
|
117
|
+
const ws = path.join(root, "workspace");
|
|
118
|
+
for (const d of [home, osHome, ws, path.join(home, "config")]) {
|
|
119
|
+
mkdirSync(d, { recursive: true });
|
|
120
|
+
}
|
|
121
|
+
const ENV_KEYS = [
|
|
122
|
+
"PATCHWORK_HOME",
|
|
123
|
+
"HOME",
|
|
124
|
+
"CLAUDE_CONFIG_DIR",
|
|
125
|
+
"PATCHWORK_FLAG_KILL_SWITCH_WRITES",
|
|
126
|
+
];
|
|
127
|
+
const savedEnv = new Map(ENV_KEYS.map((k) => [k, process.env[k]]));
|
|
128
|
+
process.env.PATCHWORK_HOME = home;
|
|
129
|
+
process.env.HOME = osHome;
|
|
130
|
+
process.env.CLAUDE_CONFIG_DIR = path.join(osHome, ".claude");
|
|
131
|
+
delete process.env.PATCHWORK_FLAG_KILL_SWITCH_WRITES;
|
|
132
|
+
const profileMod = await import("../governance/profile.js");
|
|
133
|
+
const flags = await import("../featureFlags.js");
|
|
134
|
+
const prevProfile = profileMod.activeProfile();
|
|
135
|
+
const flagsFile = path.join(home, "config", "flags.json");
|
|
136
|
+
const setKillSwitch = (engaged) => {
|
|
137
|
+
writeFileSync(flagsFile, JSON.stringify({ [flags.KILL_SWITCH_WRITES]: engaged }));
|
|
138
|
+
flags.loadFlags();
|
|
139
|
+
};
|
|
140
|
+
let target;
|
|
141
|
+
try {
|
|
142
|
+
setKillSwitch(false);
|
|
143
|
+
writeFileSync(path.join(home, "config.json"), JSON.stringify({
|
|
144
|
+
profile: "governed",
|
|
145
|
+
privacy: {
|
|
146
|
+
destinations: {
|
|
147
|
+
"acceptance-local": {
|
|
148
|
+
type: "local",
|
|
149
|
+
classifications: ["public", "internal"],
|
|
150
|
+
drivers: ["ollama"],
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
}));
|
|
155
|
+
const forbiddenDir = path.join(ws, "forbidden");
|
|
156
|
+
writeFileSync(path.join(ws, "patchwork.policy.yml"), `version: 1\ndefaults:\n forbiddenPaths:\n - "${forbiddenDir.replace(/\\/g, "/")}/**"\n`);
|
|
157
|
+
const { loadConfig } = await import("../patchworkConfig.js");
|
|
158
|
+
const config = loadConfig(path.join(home, "config.json"));
|
|
159
|
+
const profile = profileMod.resolveProfile(config);
|
|
160
|
+
profileMod.setActiveProfile(profile);
|
|
161
|
+
const { runYamlRecipe } = await import("../recipes/yamlRunner.js");
|
|
162
|
+
await import("../recipes/tools/http.js");
|
|
163
|
+
const { replayFlatMockedRun } = await import("../recipes/replayRun.js");
|
|
164
|
+
const { RecipeRunLog } = await import("../runLog.js");
|
|
165
|
+
const runLog = new RecipeRunLog({ dir: home });
|
|
166
|
+
target = await startTarget();
|
|
167
|
+
const tgt = target;
|
|
168
|
+
const approvals = [];
|
|
169
|
+
const approve = async (input) => {
|
|
170
|
+
approvals.push(input.toolId);
|
|
171
|
+
return true;
|
|
172
|
+
};
|
|
173
|
+
const deps = () => ({
|
|
174
|
+
workdir: ws,
|
|
175
|
+
logDir: home,
|
|
176
|
+
runLog,
|
|
177
|
+
testMode: false,
|
|
178
|
+
governance: profile,
|
|
179
|
+
requireApprovalFn: approve,
|
|
180
|
+
});
|
|
181
|
+
const recipe = (name, steps) => ({
|
|
182
|
+
name: `${RECIPE_PREFIX}-${name}`,
|
|
183
|
+
trigger: { type: "manual" },
|
|
184
|
+
steps,
|
|
185
|
+
});
|
|
186
|
+
// 2. Effective policy.
|
|
187
|
+
await guard("effective-policy", async () => {
|
|
188
|
+
const { governanceReport } = await import("../governance/doctorReport.js");
|
|
189
|
+
const r = governanceReport({
|
|
190
|
+
config,
|
|
191
|
+
isFlagOn: flags.isEnabled,
|
|
192
|
+
recipesDir: path.join(home, "recipes"),
|
|
193
|
+
workersDir: path.join(home, "workers"),
|
|
194
|
+
});
|
|
195
|
+
return [
|
|
196
|
+
r.governed && profile.mode === "governed",
|
|
197
|
+
r.governed
|
|
198
|
+
? "temp governed config reports GOVERNED"
|
|
199
|
+
: `NOT GOVERNED: ${r.reasons.join("; ")}`,
|
|
200
|
+
];
|
|
201
|
+
});
|
|
202
|
+
// 3. Refusal by the policy matrix.
|
|
203
|
+
await guard("policy-refusal", async () => {
|
|
204
|
+
const file = path.join(forbiddenDir, "probe.txt");
|
|
205
|
+
const res = await runYamlRecipe(recipe("policy", [{ tool: "file.write", path: file, content: "x" }]), deps());
|
|
206
|
+
const err = res.stepResults[0]?.error ?? "";
|
|
207
|
+
const refused = /policy_denied/.test(err);
|
|
208
|
+
const exists = existsSync(file);
|
|
209
|
+
return [
|
|
210
|
+
refused && !exists,
|
|
211
|
+
`step ${res.stepResults[0]?.status ?? "missing"}${refused ? " (policy_denied)" : ` (${err || "no error"})`}; file ${exists ? "WRITTEN" : "absent"}`,
|
|
212
|
+
];
|
|
213
|
+
});
|
|
214
|
+
// 4. Kill switch.
|
|
215
|
+
await guard("kill-switch", async () => {
|
|
216
|
+
const file = path.join(ws, "allowed", "ks.txt");
|
|
217
|
+
setKillSwitch(true);
|
|
218
|
+
let res;
|
|
219
|
+
try {
|
|
220
|
+
res = await runYamlRecipe(recipe("killswitch", [
|
|
221
|
+
{ tool: "file.write", path: file, content: "x" },
|
|
222
|
+
]), deps());
|
|
223
|
+
}
|
|
224
|
+
finally {
|
|
225
|
+
setKillSwitch(false);
|
|
226
|
+
}
|
|
227
|
+
const text = `${res.errorMessage ?? ""} ${res.stepResults.map((s) => s.error ?? "").join(" ")}`;
|
|
228
|
+
const blocked = /kill_switch_blocked|kill switch/i.test(text);
|
|
229
|
+
const exists = existsSync(file);
|
|
230
|
+
return [
|
|
231
|
+
blocked && !exists,
|
|
232
|
+
`${blocked ? "refused (kill_switch_blocked)" : `NOT refused (${text.trim() || "ran"})`}; file ${exists ? "WRITTEN" : "absent"}`,
|
|
233
|
+
];
|
|
234
|
+
});
|
|
235
|
+
// 5. Uncertain delivery (row 6): accepted, response lost, never resent.
|
|
236
|
+
await guard("uncertain-delivery", async () => {
|
|
237
|
+
tgt.received = 0;
|
|
238
|
+
const res = await runYamlRecipe(recipe("uncertain", [
|
|
239
|
+
{
|
|
240
|
+
tool: "http.post",
|
|
241
|
+
url: `${tgt.url}/lost`,
|
|
242
|
+
body: '{"probe":1}',
|
|
243
|
+
allowPrivate: true,
|
|
244
|
+
timeoutMs: 2000,
|
|
245
|
+
retry: 2,
|
|
246
|
+
retryDelay: 1,
|
|
247
|
+
},
|
|
248
|
+
]), deps());
|
|
249
|
+
const step = res.stepResults[0];
|
|
250
|
+
const uncertain = /outcome_uncertain/.test(step?.error ?? "");
|
|
251
|
+
return [
|
|
252
|
+
step?.status === "error" && uncertain && tgt.received === 1,
|
|
253
|
+
`step ${step?.status ?? "missing"}${uncertain ? " (outcome_uncertain)" : ""}; server received ${tgt.received} request(s), expected 1`,
|
|
254
|
+
];
|
|
255
|
+
});
|
|
256
|
+
// 6 + 7. Replay by taskId, and the lookup the HTTP route uses.
|
|
257
|
+
let originalTaskId;
|
|
258
|
+
await guard("run-lookup", async () => {
|
|
259
|
+
tgt.received = 0;
|
|
260
|
+
approvals.length = 0;
|
|
261
|
+
const name = "replay";
|
|
262
|
+
const res = await runYamlRecipe(recipe(name, [
|
|
263
|
+
{
|
|
264
|
+
tool: "http.post",
|
|
265
|
+
url: `${tgt.url}/ok`,
|
|
266
|
+
body: '{"probe":2}',
|
|
267
|
+
into: "posted",
|
|
268
|
+
allowPrivate: true,
|
|
269
|
+
timeoutMs: 2000,
|
|
270
|
+
},
|
|
271
|
+
]), deps());
|
|
272
|
+
if (res.stepResults[0]?.status !== "ok" || tgt.received !== 1) {
|
|
273
|
+
return [
|
|
274
|
+
false,
|
|
275
|
+
`original run did not complete (step ${res.stepResults[0]?.status}: ${res.stepResults[0]?.error ?? ""})`,
|
|
276
|
+
];
|
|
277
|
+
}
|
|
278
|
+
const listed = runLog.query({ recipe: `${RECIPE_PREFIX}-${name}` });
|
|
279
|
+
originalTaskId = listed[0]?.taskId;
|
|
280
|
+
const found = originalTaskId ? runLog.getByTaskId(originalTaskId) : null;
|
|
281
|
+
return [
|
|
282
|
+
found !== null && found.taskId === originalTaskId,
|
|
283
|
+
found ? "original run resolves by taskId" : "run NOT found by taskId",
|
|
284
|
+
];
|
|
285
|
+
});
|
|
286
|
+
await guard("replay", async () => {
|
|
287
|
+
if (!originalTaskId)
|
|
288
|
+
return [false, "no original run to replay"];
|
|
289
|
+
const original = runLog.getByTaskId(originalTaskId);
|
|
290
|
+
if (!original)
|
|
291
|
+
return [false, "original run not found by taskId"];
|
|
292
|
+
const before = tgt.received;
|
|
293
|
+
approvals.length = 0;
|
|
294
|
+
const r = await replayFlatMockedRun({
|
|
295
|
+
originalRun: original,
|
|
296
|
+
recipe: recipe("replay", [
|
|
297
|
+
{
|
|
298
|
+
tool: "http.post",
|
|
299
|
+
url: `${tgt.url}/ok`,
|
|
300
|
+
body: '{"probe":2}',
|
|
301
|
+
into: "posted",
|
|
302
|
+
allowPrivate: true,
|
|
303
|
+
timeoutMs: 2000,
|
|
304
|
+
},
|
|
305
|
+
]),
|
|
306
|
+
deps: {
|
|
307
|
+
runLog,
|
|
308
|
+
runnerDeps: {
|
|
309
|
+
workdir: ws,
|
|
310
|
+
logDir: home,
|
|
311
|
+
governance: profile,
|
|
312
|
+
requireApprovalFn: approve,
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
});
|
|
316
|
+
const newRequests = tgt.received - before;
|
|
317
|
+
const rows = runLog.query({ recipe: `${RECIPE_PREFIX}-replay` });
|
|
318
|
+
const replayRow = rows.find((row) => row.taskId !== originalTaskId &&
|
|
319
|
+
row.replay === true);
|
|
320
|
+
return [
|
|
321
|
+
r.ok && newRequests === 0 && approvals.length === 0 && !!replayRow,
|
|
322
|
+
`replay ${r.ok ? "ok" : `failed (${r.error ?? "?"})`}; ${newRequests} new request(s); ${approvals.length} approval(s) requested; replay row ${replayRow ? "stamped replay: true" : "MISSING"}`,
|
|
323
|
+
];
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
finally {
|
|
327
|
+
await stopTarget(target).catch(() => { });
|
|
328
|
+
try {
|
|
329
|
+
setKillSwitch(false);
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
// sandbox may already be unusable; env restore below still runs
|
|
333
|
+
}
|
|
334
|
+
profileMod.setActiveProfile(prevProfile);
|
|
335
|
+
for (const [k, v] of savedEnv) {
|
|
336
|
+
if (v === undefined)
|
|
337
|
+
delete process.env[k];
|
|
338
|
+
else
|
|
339
|
+
process.env[k] = v;
|
|
340
|
+
}
|
|
341
|
+
rmSync(root, { recursive: true, force: true });
|
|
342
|
+
}
|
|
343
|
+
// Order the report as documented: identity, policy, refusal, kill switch,
|
|
344
|
+
// uncertain, replay, lookup.
|
|
345
|
+
const order = [
|
|
346
|
+
"identity",
|
|
347
|
+
"effective-policy",
|
|
348
|
+
"policy-refusal",
|
|
349
|
+
"kill-switch",
|
|
350
|
+
"uncertain-delivery",
|
|
351
|
+
"replay",
|
|
352
|
+
"run-lookup",
|
|
353
|
+
];
|
|
354
|
+
checks.sort((a, b) => order.indexOf(a.name) - order.indexOf(b.name));
|
|
355
|
+
const passed = checks.filter((c) => c.ok).length;
|
|
356
|
+
return {
|
|
357
|
+
ok: passed === checks.length && checks.length === order.length,
|
|
358
|
+
total: checks.length,
|
|
359
|
+
passed,
|
|
360
|
+
checks,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
export function formatAcceptance(r) {
|
|
364
|
+
const out = [`${r.total} checks`];
|
|
365
|
+
for (const c of r.checks) {
|
|
366
|
+
out.push(` ${c.ok ? "PASS" : "FAIL"} ${c.name.padEnd(20)}${c.detail}`);
|
|
367
|
+
}
|
|
368
|
+
out.push(r.ok
|
|
369
|
+
? `ACCEPTED: ${r.passed}/${r.total} passed`
|
|
370
|
+
: `NOT ACCEPTED: ${r.total - r.passed} of ${r.total} failed`);
|
|
371
|
+
return out.join("\n");
|
|
372
|
+
}
|
|
373
|
+
//# sourceMappingURL=doctorAcceptance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctorAcceptance.js","sourceRoot":"","sources":["../../src/commands/doctorAcceptance.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -4138,6 +4138,40 @@ if (process.argv[2] === "doctor" && process.argv[3] === "health") {
|
|
|
4138
4138
|
}
|
|
4139
4139
|
})();
|
|
4140
4140
|
}
|
|
4141
|
+
// `doctor acceptance` — does the INSTALLED package BEHAVE? Runs the real
|
|
4142
|
+
// runtime entrypoints in-process against a throwaway PATCHWORK_HOME and
|
|
4143
|
+
// asserts refusals, kill switch, no-resend on uncertain delivery, replay and
|
|
4144
|
+
// run lookup. A separate subcommand for the reason `doctor health` is: plain
|
|
4145
|
+
// `doctor`'s exit code is load-bearing and must not change meaning.
|
|
4146
|
+
if (process.argv[2] === "doctor" && process.argv[3] === "acceptance") {
|
|
4147
|
+
const args = process.argv.slice(4);
|
|
4148
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
4149
|
+
process.stdout.write("Usage: patchwork doctor acceptance [--json]\n\n" +
|
|
4150
|
+
"Proves the INSTALLED package behaves, not merely that a symbol is in dist/.\n" +
|
|
4151
|
+
"Seven checks: identity (version, build time, running bridges vs install),\n" +
|
|
4152
|
+
"effective governed policy, policy-matrix refusal, kill switch, uncertain\n" +
|
|
4153
|
+
"delivery is never resent, mocked replay dispatches nothing, run lookup by\n" +
|
|
4154
|
+
"taskId. Exits 1 if any check fails.\n\n" +
|
|
4155
|
+
"Safe on a live machine: every behavioural check runs in-process against a\n" +
|
|
4156
|
+
"fresh temp PATCHWORK_HOME and HOME (removed afterwards), loopback only, no\n" +
|
|
4157
|
+
"connectors, no model calls, and the real ledgers are never read or written.\n");
|
|
4158
|
+
process.exit(0);
|
|
4159
|
+
}
|
|
4160
|
+
(async () => {
|
|
4161
|
+
try {
|
|
4162
|
+
const { formatAcceptance, runAcceptance } = await import("./commands/doctorAcceptance.js");
|
|
4163
|
+
const report = await runAcceptance();
|
|
4164
|
+
process.stdout.write(args.includes("--json")
|
|
4165
|
+
? `${JSON.stringify(report, null, 2)}\n`
|
|
4166
|
+
: `${formatAcceptance(report)}\n`);
|
|
4167
|
+
process.exit(report.ok ? 0 : 1);
|
|
4168
|
+
}
|
|
4169
|
+
catch (err) {
|
|
4170
|
+
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
4171
|
+
process.exit(1);
|
|
4172
|
+
}
|
|
4173
|
+
})();
|
|
4174
|
+
}
|
|
4141
4175
|
// `patchwork codex doctor` — diagnose whether ~/.codex/config.toml is
|
|
4142
4176
|
// correctly (and currently) wired up to this bridge.
|
|
4143
4177
|
if (process.argv[2] === "codex" && process.argv[3] === "doctor") {
|
|
@@ -4939,7 +4973,9 @@ if (process.argv[2] === "members") {
|
|
|
4939
4973
|
// installed? Every check in this repo verifies the repository. On 2026-08-19
|
|
4940
4974
|
// both live bridges were found running neither the privacy code nor `butler`,
|
|
4941
4975
|
// merged and wired and green throughout.
|
|
4942
|
-
if (process.argv[2] === "doctor" &&
|
|
4976
|
+
if (process.argv[2] === "doctor" &&
|
|
4977
|
+
process.argv[3] !== "health" &&
|
|
4978
|
+
process.argv[3] !== "acceptance") {
|
|
4943
4979
|
const args = process.argv.slice(3);
|
|
4944
4980
|
if (args.includes("--help") || args.includes("-h")) {
|
|
4945
4981
|
// Previously this block had no --help of its own, so the OTHER doctor
|
|
@@ -4957,7 +4993,8 @@ if (process.argv[2] === "doctor" && process.argv[3] !== "health") {
|
|
|
4957
4993
|
" --require-governed ALSO exit 1 when the governance posture is NOT GOVERNED\n" +
|
|
4958
4994
|
" (the posture is always printed; see `patchwork profile`)\n\n" +
|
|
4959
4995
|
"For workspace / git / lock-file / automation-policy checks, use\n" +
|
|
4960
|
-
"`patchwork doctor health
|
|
4996
|
+
"`patchwork doctor health`. For 'does the installed package behave?',\n" +
|
|
4997
|
+
"use `patchwork doctor acceptance` (safe on a live machine).\n");
|
|
4961
4998
|
process.exit(0);
|
|
4962
4999
|
}
|
|
4963
5000
|
(async () => {
|