patchwork-os 1.2.0-beta.2.canary.670 → 1.2.0-beta.2.canary.673

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/dist/index.js CHANGED
@@ -222,6 +222,7 @@ const KNOWN_SUBCOMMANDS = [
222
222
  "gate",
223
223
  "outcomes",
224
224
  "butler",
225
+ "privacy",
225
226
  "members",
226
227
  // Dispatched at `process.argv[2] === "tools"` (and `help`) but absent from
227
228
  // this array until 2026-08. The comment below calls this "the dispatch
@@ -301,6 +302,7 @@ if (process.argv[2] === "--help" ||
301
302
  `Diagnose\n` +
302
303
  ` halts [--window 1h|24h|overnight|7d] Morning summary of recent recipe halts\n` +
303
304
  ` judgments [--window ...] [--recipe N] Recent judge-step verdicts across runs\n` +
305
+ ` privacy shadow [--since-days N] What a candidate privacy policy would have stopped\n` +
304
306
  ` suggest [--since-days N] Recipe + unused-tool suggestions\n` +
305
307
  ` token-efficiency benchmark Measure token cost across tool sets\n` +
306
308
  ` traces export Bundle approval / recipe / decision traces\n` +
@@ -4389,6 +4391,38 @@ if (process.argv[2] === "members") {
4389
4391
  // runs AS the worker, so grading reachable from one would let a worker
4390
4392
  // manufacture the evidence that raises its own trust dial. Nothing here writes
4391
4393
  // the trust ledger — rows go to the Butler shadow ledger and move nothing.
4394
+ // --- privacy shadow (ADR-0021) ---
4395
+ // Reports what a CANDIDATE policy would have done, without enforcing it. The
4396
+ // headline is the DENOMINATOR, not the crossing count: `agent` steps are a
4397
+ // small minority of step volume and orchestrator dispatch is not observed at
4398
+ // all (#1397), so a bare count invites "my policy is fine" from a partial
4399
+ // surface. formatPrivacyShadow refuses to print one without its coverage.
4400
+ if (process.argv[2] === "privacy") {
4401
+ const args = process.argv.slice(3);
4402
+ (async () => {
4403
+ if (args[0] !== "shadow") {
4404
+ process.stderr.write("Usage: patchwork privacy shadow [--since-days N] [--json]\n" +
4405
+ "\n" +
4406
+ " Observes boundary decisions WITHOUT enforcing them. Configure a\n" +
4407
+ " candidate policy under `privacy.shadow.destinations` in config.json;\n" +
4408
+ " `privacy.destinations` stays untouched, so shadow never enforces.\n");
4409
+ process.exit(2);
4410
+ }
4411
+ const { summarisePrivacyShadow, formatPrivacyShadow } = await import("./privacy/shadowLog.js");
4412
+ const idx = args.indexOf("--since-days");
4413
+ const days = idx !== -1 ? Number(args[idx + 1]) : undefined;
4414
+ const summary = summarisePrivacyShadow(days !== undefined && Number.isFinite(days) && days > 0
4415
+ ? { since: Date.now() - days * 86_400_000 }
4416
+ : {});
4417
+ if (args.includes("--json")) {
4418
+ process.stdout.write(`${JSON.stringify(summary, null, 2)}\n`);
4419
+ }
4420
+ else {
4421
+ process.stdout.write(`${formatPrivacyShadow(summary)}\n`);
4422
+ }
4423
+ process.exit(0);
4424
+ })();
4425
+ }
4392
4426
  if (process.argv[2] === "butler") {
4393
4427
  const args = process.argv.slice(3);
4394
4428
  (async () => {