tamperward 2.42.0 → 2.43.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.
Files changed (2) hide show
  1. package/dist/cli/index.js +93 -27
  2. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -15763,7 +15763,9 @@ function runCapturedProcessSync(executable, args, opts) {
15763
15763
  detached: Boolean(opts.detached),
15764
15764
  killGroupOnFinish: Boolean(opts.killGroupOnFinish),
15765
15765
  drainMs: opts.drainMs ?? 1e3,
15766
- captureBytes: DIAGNOSTIC_TAIL_BYTES
15766
+ captureBytes: DIAGNOSTIC_TAIL_BYTES,
15767
+ progressStage: opts.progressStage,
15768
+ progressIntervalMs: opts.progressIntervalMs
15767
15769
  }),
15768
15770
  { mode: 384 }
15769
15771
  );
@@ -15774,7 +15776,7 @@ function runCapturedProcessSync(executable, args, opts) {
15774
15776
  cwd: opts.cwd,
15775
15777
  env: opts.env,
15776
15778
  encoding: "utf8",
15777
- stdio: ["ignore", "pipe", "ignore"],
15779
+ stdio: ["ignore", "pipe", opts.progressStage ? "inherit" : "ignore"],
15778
15780
  // The trusted result is at most two 16 KiB tails plus small metadata.
15779
15781
  // A candidate that somehow writes into the supervisor's stdout through
15780
15782
  // same-UID /proc can only overflow/corrupt this bounded channel and make
@@ -15928,6 +15930,16 @@ let timedOut = false;
15928
15930
  let exitInfo = { exit: null, signal: null };
15929
15931
  let descendantTracker = null;
15930
15932
  let drainTimer = null;
15933
+ let progressTimer = null;
15934
+ const started = Date.now();
15935
+ function progress() {
15936
+ if (cfg.progressStage !== 'visible' && cfg.progressStage !== 'pristine') return;
15937
+ try {
15938
+ fs.writeSync(2, 'verify: ' + cfg.progressStage + ' suite running (' +
15939
+ Math.floor((Date.now() - started) / 1000) + 's; ' +
15940
+ (stdout.total + stderr.total) + ' output bytes captured)\n');
15941
+ } catch {}
15942
+ }
15931
15943
 
15932
15944
  function killOwned() {
15933
15945
  if (!child || !child.pid) return;
@@ -15950,6 +15962,7 @@ function finish(extra) {
15950
15962
  done = true;
15951
15963
  if (descendantTracker) clearInterval(descendantTracker);
15952
15964
  if (drainTimer) clearTimeout(drainTimer);
15965
+ if (progressTimer) clearInterval(progressTimer);
15953
15966
  // fd 1 is the reserved result channel (suite streams are separate pipes).
15954
15967
  // Write synchronously: process.stdout.write is async on a POSIX pipe, so an
15955
15968
  // immediate process.exit(0) can truncate the result before it flushes.
@@ -15988,6 +16001,11 @@ try {
15988
16001
  }
15989
16002
 
15990
16003
  if (child) {
16004
+ if (cfg.progressStage === 'visible' || cfg.progressStage === 'pristine') {
16005
+ progress();
16006
+ progressTimer = setInterval(progress, Number(cfg.progressIntervalMs) || 30000);
16007
+ progressTimer.unref();
16008
+ }
15991
16009
  if (process.platform === 'linux') {
15992
16010
  trackDescendants();
15993
16011
  descendantTracker = setInterval(trackDescendants, 5);
@@ -16392,7 +16410,7 @@ function containerStateResult(state, secs) {
16392
16410
  }
16393
16411
  return { exit: state.ExitCode, secs };
16394
16412
  }
16395
- function runContainerStage(backend, dir, command, budgetSecs) {
16413
+ function runContainerStage(backend, dir, command, budgetSecs, progressStage) {
16396
16414
  const t0 = Date.now();
16397
16415
  if (backend.kind !== "container" || !backend.available || !backend.image || !backend.enginePath || !backend.engineSha256 || !backend.daemonHost || !engineStable(backend)) {
16398
16416
  return {
@@ -16422,7 +16440,8 @@ function runContainerStage(backend, dir, command, budgetSecs) {
16422
16440
  cwd: dirname7(backend.enginePath),
16423
16441
  env: engineClientEnv(),
16424
16442
  timeoutMs: budgetSecs * 1e3,
16425
- backstopMs: 3e4
16443
+ backstopMs: 3e4,
16444
+ progressStage
16426
16445
  }
16427
16446
  );
16428
16447
  const secs = Math.round((Date.now() - t0) / 1e3);
@@ -17165,7 +17184,7 @@ var init_verification_receipt = __esm({
17165
17184
  // src/cli/verify.ts
17166
17185
  import { execFileSync as execFileSync9, spawnSync as spawnSync3 } from "node:child_process";
17167
17186
  import { createHash as createHash14 } from "node:crypto";
17168
- import { chmodSync as chmodSync2, cpSync, lstatSync as lstatSync10, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync3, readFileSync as readFileSync13, readlinkSync as readlinkSync3, rmSync as rmSync9, symlinkSync, writeFileSync as writeFileSync8, existsSync as existsSync10 } from "node:fs";
17187
+ import { chmodSync as chmodSync2, cpSync, lstatSync as lstatSync10, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync3, readFileSync as readFileSync13, readlinkSync as readlinkSync3, realpathSync as realpathSync8, rmSync as rmSync9, symlinkSync, writeFileSync as writeFileSync8, existsSync as existsSync10 } from "node:fs";
17169
17188
  import { tmpdir as tmpdir4 } from "node:os";
17170
17189
  import { dirname as dirname10, isAbsolute as isAbsolute11, join as join22, relative as relative6, resolve as resolve9, sep as sep4 } from "node:path";
17171
17190
  function oracleAssuranceReport() {
@@ -17508,7 +17527,28 @@ function localVerifierShell(platform = process.platform, command) {
17508
17527
  return null;
17509
17528
  }
17510
17529
  }
17511
- function runLocalSuite(dir, cmd, budgetSecs) {
17530
+ function cargoStageTargets(root, cwd) {
17531
+ const absolute = resolve9(cwd, root);
17532
+ mkdirSync10(absolute, { recursive: true });
17533
+ const canonical2 = realpathSync8(absolute);
17534
+ const checkout = realpathSync8(cwd);
17535
+ const contains = (parent, child) => {
17536
+ const rel = relative6(parent, child);
17537
+ return rel === "" || !rel.startsWith(".." + sep4) && rel !== ".." && !isAbsolute11(rel);
17538
+ };
17539
+ if (contains(checkout, canonical2) || contains(canonical2, checkout)) {
17540
+ throw new Error("Cargo target root must be outside the checkout and cannot contain it");
17541
+ }
17542
+ const targets = { visible: join22(canonical2, "visible"), pristine: join22(canonical2, "pristine") };
17543
+ for (const target of Object.values(targets)) {
17544
+ mkdirSync10(target, { recursive: true });
17545
+ if (lstatSync10(target).isSymbolicLink() || realpathSync8(target) !== target) {
17546
+ throw new Error("Cargo stage targets must be distinct real directories, not links");
17547
+ }
17548
+ }
17549
+ return targets;
17550
+ }
17551
+ function runLocalSuite(dir, cmd, budgetSecs, stage, target, progress) {
17512
17552
  const t0 = Date.now();
17513
17553
  const shell = localVerifierShell(process.platform, cmd);
17514
17554
  if (!shell) {
@@ -17521,13 +17561,26 @@ function runLocalSuite(dir, cmd, budgetSecs) {
17521
17561
  }
17522
17562
  const scratch = mkdtempSync3(join22(tmpdir4(), "tw-verify-run-"));
17523
17563
  try {
17564
+ const env = suiteEnv(scratch);
17565
+ if (target) {
17566
+ let valid = false;
17567
+ try {
17568
+ valid = realpathSync8(target) === target && !lstatSync10(target).isSymbolicLink();
17569
+ } catch {
17570
+ }
17571
+ if (!valid) {
17572
+ return { exit: null, secs: 0, failure: "backend", reason: "Cargo stage target changed before execution" };
17573
+ }
17574
+ env.CARGO_TARGET_DIR = target;
17575
+ }
17524
17576
  const r = runCapturedProcessSync(shell.executable, shell.args, {
17525
17577
  cwd: dir,
17526
- env: suiteEnv(scratch),
17578
+ env,
17527
17579
  timeoutMs: budgetSecs * 1e3,
17528
17580
  detached: true,
17529
17581
  killGroupOnFinish: true,
17530
- backstopMs: 3e4
17582
+ backstopMs: 3e4,
17583
+ progressStage: progress ? stage : void 0
17531
17584
  });
17532
17585
  const secs = Math.round((Date.now() - t0) / 1e3);
17533
17586
  if (r.timedOut) {
@@ -17693,6 +17746,15 @@ function runVerifyImpl(opts) {
17693
17746
  return 2;
17694
17747
  }
17695
17748
  const isolated = verifierBackend.kind === "container";
17749
+ let cargoTargets;
17750
+ if (opts.cargoTargetRoot !== void 0) {
17751
+ if (isolated) return cannotVerify("INVALID_ARGUMENTS", "--cargo-target-root is supported only by the checkpointed-local backend");
17752
+ try {
17753
+ cargoTargets = cargoStageTargets(opts.cargoTargetRoot, cwd);
17754
+ } catch (e) {
17755
+ return cannotVerify("INVALID_ARGUMENTS", `cannot configure Cargo stage targets (${e instanceof Error ? e.message : String(e)})`);
17756
+ }
17757
+ }
17696
17758
  if (!isolated && !localVerifierShell(process.platform, cmd)) {
17697
17759
  opts.onVerdict?.({ verdict: "CANNOT_VERIFY", reason: "LOCAL_VERIFIER_UNSUPPORTED_PLATFORM", detail: `checkpointed-local verifier is unsupported on ${process.platform}` });
17698
17760
  if (opts.json) {
@@ -17736,7 +17798,7 @@ function runVerifyImpl(opts) {
17736
17798
  }
17737
17799
  const frozenNodeModules = dependencyEnvironment ? dependencyEnvironment.roots.find((root) => root.kind === "node_modules")?.realPath ?? null : null;
17738
17800
  const checkDeps = () => dependencyEnvironment ? checkDependencyEnvironment(cwd, dependencyEnvironment) : { ok: true };
17739
- const runStage = opts.runStage ?? ((dir) => isolated ? runContainerStage(verifierBackend, dir, cmd, budget) : runLocalSuite(dir, cmd, budget));
17801
+ const runStage = (dir, stage) => opts.runStage ? opts.runStage(dir) : isolated ? runContainerStage(verifierBackend, dir, cmd, budget, opts.silent ? void 0 : stage) : runLocalSuite(dir, cmd, budget, stage, cargoTargets?.[stage], !opts.silent);
17740
17802
  const notQuiescent = (stage, r) => {
17741
17803
  const detail = `the ${stage} suite exited (code ${r.exit ?? "unknown"}) but left a process holding stdout open after termination was attempted; the stage is not quiescent, so the run cannot be certified`;
17742
17804
  opts.onVerdict?.({ verdict: "CANNOT_VERIFY", reason: "VERIFIER_BACKEND_RUNTIME_FAILURE", detail });
@@ -17817,7 +17879,7 @@ function runVerifyImpl(opts) {
17817
17879
  { verifier_backend: backendReport(), dependency_environment: dependencyReport(), oracle_assurance: oracleAssuranceReport(), materialization_reason: materializationFailureReason(e) }
17818
17880
  );
17819
17881
  }
17820
- const visible = runStage(visDir);
17882
+ const visible = runStage(visDir, "visible");
17821
17883
  if (visible.pipeHeldOpen) {
17822
17884
  cleanup([visRoot]);
17823
17885
  return notQuiescent("visible", visible);
@@ -17933,7 +17995,7 @@ function runVerifyImpl(opts) {
17933
17995
  );
17934
17996
  }
17935
17997
  const overlayBefore = overlayDigest(priDir, restored);
17936
- const pristine = runStage(priDir);
17998
+ const pristine = runStage(priDir, "pristine");
17937
17999
  if (pristine.pipeHeldOpen) {
17938
18000
  cleanup([visRoot, priRoot]);
17939
18001
  return notQuiescent("pristine", pristine);
@@ -18109,13 +18171,14 @@ function parseVerify(args) {
18109
18171
  if (a === "--json") o.json = true;
18110
18172
  else if (a === "--keep") o.keep = true;
18111
18173
  else if (a === "--require-ancestor") o.requireAncestor = true;
18112
- else if (a === "--base" || a === "--cmd" || a === "--cwd" || a === "--budget") {
18174
+ else if (a === "--base" || a === "--cmd" || a === "--cwd" || a === "--budget" || a === "--cargo-target-root") {
18113
18175
  const v = value(i, a);
18114
18176
  if (v === void 0) continue;
18115
18177
  i++;
18116
18178
  if (a === "--base") o.base = v;
18117
18179
  else if (a === "--cmd") o.cmd = v;
18118
18180
  else if (a === "--cwd") o.cwd = v;
18181
+ else if (a === "--cargo-target-root") o.cargoTargetRoot = v;
18119
18182
  else {
18120
18183
  o.budget = Number(v);
18121
18184
  if (!Number.isFinite(o.budget) || o.budget <= 0)
@@ -18239,7 +18302,7 @@ var init_verify = __esm({
18239
18302
  // src/cli/run.ts
18240
18303
  import { execFileSync as execFileSync10, spawn, spawnSync as spawnSync4 } from "node:child_process";
18241
18304
  import { randomBytes as randomBytes3 } from "node:crypto";
18242
- import { accessSync as accessSync3, constants as fsConstants, mkdtempSync as mkdtempSync4, readdirSync as readdirSync5, readFileSync as readFileSync14, readlinkSync as readlinkSync4, realpathSync as realpathSync8, rmSync as rmSync10, statSync as statSync6, writeFileSync as writeFileSync9 } from "node:fs";
18305
+ import { accessSync as accessSync3, constants as fsConstants, mkdtempSync as mkdtempSync4, readdirSync as readdirSync5, readFileSync as readFileSync14, readlinkSync as readlinkSync4, realpathSync as realpathSync9, rmSync as rmSync10, statSync as statSync6, writeFileSync as writeFileSync9 } from "node:fs";
18243
18306
  import { tmpdir as tmpdir5 } from "node:os";
18244
18307
  import { dirname as dirname11, join as join23, resolve as resolve10 } from "node:path";
18245
18308
  function authoritativeRunLifecyclePlatform(platform = process.platform) {
@@ -18294,7 +18357,7 @@ function trustedLinuxPython(candidates = DEFAULT_TRUSTED_PYTHON_CANDIDATES) {
18294
18357
  }
18295
18358
  for (const candidate of candidates) {
18296
18359
  try {
18297
- const real = realpathSync8(candidate);
18360
+ const real = realpathSync9(candidate);
18298
18361
  const st = statSync6(real);
18299
18362
  if (!st.isFile() || writableByCaller2(real)) continue;
18300
18363
  const probe = spawnSync4(
@@ -18567,7 +18630,7 @@ function survivorsHoldingTree(cwd, spawnedAfterTicks) {
18567
18630
  const out3 = [];
18568
18631
  let real;
18569
18632
  try {
18570
- real = realpathSync8(cwd);
18633
+ real = realpathSync9(cwd);
18571
18634
  } catch {
18572
18635
  return out3;
18573
18636
  }
@@ -19982,7 +20045,7 @@ import {
19982
20045
  mkdtempSync as mkdtempSync5,
19983
20046
  readFileSync as readFileSync16,
19984
20047
  readdirSync as readdirSync7,
19985
- realpathSync as realpathSync9,
20048
+ realpathSync as realpathSync10,
19986
20049
  rmSync as rmSync11,
19987
20050
  symlinkSync as symlinkSync2
19988
20051
  } from "node:fs";
@@ -20255,7 +20318,7 @@ function rewriteTraceRoot(accesses, actualRoot) {
20255
20318
  if (!inside3(actualRoot, abs)) return { ...item, path: abs };
20256
20319
  const rel = relative7(actualRoot, abs).split(sep5).join("/");
20257
20320
  try {
20258
- const real = resolve12(realpathSync9(abs));
20321
+ const real = resolve12(realpathSync10(abs));
20259
20322
  if (!inside3(actualRoot, real)) return { ...item, path: real };
20260
20323
  } catch {
20261
20324
  }
@@ -21492,7 +21555,7 @@ var init_adapter3 = __esm({
21492
21555
 
21493
21556
  // src/adapters/copilot-sdk/changes.ts
21494
21557
  import { execFileSync as execFileSync13 } from "node:child_process";
21495
- import { mkdtempSync as mkdtempSync6, writeFileSync as writeFileSync10, readFileSync as readFileSync17, rmSync as rmSync12, existsSync as existsSync13, realpathSync as realpathSync10 } from "node:fs";
21558
+ import { mkdtempSync as mkdtempSync6, writeFileSync as writeFileSync10, readFileSync as readFileSync17, rmSync as rmSync12, existsSync as existsSync13, realpathSync as realpathSync11 } from "node:fs";
21496
21559
  import { tmpdir as tmpdir7 } from "node:os";
21497
21560
  import { basename as basename5, dirname as dirname12, isAbsolute as isAbsolute16, relative as relative11, resolve as resolve15, join as join26 } from "node:path";
21498
21561
  function asStr4(v) {
@@ -21505,7 +21568,7 @@ function relForDisplay5(path, cwd) {
21505
21568
  function canonicalContainedTarget(abs, root) {
21506
21569
  let realRoot;
21507
21570
  try {
21508
- realRoot = realpathSync10(root);
21571
+ realRoot = realpathSync11(root);
21509
21572
  } catch (e) {
21510
21573
  throw new Error(`trusted repository root ${root} cannot be resolved: ${e instanceof Error ? e.message : String(e)}`);
21511
21574
  }
@@ -21519,7 +21582,7 @@ function canonicalContainedTarget(abs, root) {
21519
21582
  }
21520
21583
  let realDir;
21521
21584
  try {
21522
- realDir = realpathSync10(dir);
21585
+ realDir = realpathSync11(dir);
21523
21586
  } catch (e) {
21524
21587
  throw new Error(`write target ${abs} cannot be resolved: ${e instanceof Error ? e.message : String(e)}`);
21525
21588
  }
@@ -22849,7 +22912,7 @@ var init_runtime = __esm({
22849
22912
 
22850
22913
  // src/cli/onboard.ts
22851
22914
  import { execFileSync as execFileSync15 } from "node:child_process";
22852
- import { lstatSync as lstatSync11, mkdtempSync as mkdtempSync7, readFileSync as readFileSync19, realpathSync as realpathSync11, rmSync as rmSync13 } from "node:fs";
22915
+ import { lstatSync as lstatSync11, mkdtempSync as mkdtempSync7, readFileSync as readFileSync19, realpathSync as realpathSync12, rmSync as rmSync13 } from "node:fs";
22853
22916
  import { tmpdir as tmpdir8 } from "node:os";
22854
22917
  import { join as join28, relative as relative12, resolve as resolve16, sep as sep6 } from "node:path";
22855
22918
  import { createInterface } from "node:readline";
@@ -22982,7 +23045,7 @@ async function runOnboard(opts, io = {}) {
22982
23045
  const cwd = resolve16(rootText);
22983
23046
  let sameRoot = cwd === requestedCwd;
22984
23047
  try {
22985
- sameRoot = realpathSync11(cwd) === realpathSync11(requestedCwd);
23048
+ sameRoot = realpathSync12(cwd) === realpathSync12(requestedCwd);
22986
23049
  } catch {
22987
23050
  }
22988
23051
  if (!sameRoot) {
@@ -23365,8 +23428,8 @@ function runDemo(cwd, head, runners, out3) {
23365
23428
  let worktreeRoot;
23366
23429
  let realTarget;
23367
23430
  try {
23368
- worktreeRoot = realpathSync11(wt);
23369
- realTarget = realpathSync11(targetPath);
23431
+ worktreeRoot = realpathSync12(wt);
23432
+ realTarget = realpathSync12(targetPath);
23370
23433
  } catch {
23371
23434
  out3("Demo skipped: the selected test could not be resolved safely inside the disposable worktree.");
23372
23435
  return;
@@ -24616,7 +24679,7 @@ var init_run2 = __esm({
24616
24679
  });
24617
24680
 
24618
24681
  // src/research/ledger-files.ts
24619
- import { closeSync as closeSync6, constants as constants5, fstatSync as fstatSync3, lstatSync as lstatSync12, openSync as openSync5, readFileSync as readFileSync23, readdirSync as readdirSync8, realpathSync as realpathSync12 } from "node:fs";
24682
+ import { closeSync as closeSync6, constants as constants5, fstatSync as fstatSync3, lstatSync as lstatSync12, openSync as openSync5, readFileSync as readFileSync23, readdirSync as readdirSync8, realpathSync as realpathSync13 } from "node:fs";
24620
24683
  import { join as join30, resolve as resolve20 } from "node:path";
24621
24684
  function lstatOrNull(path) {
24622
24685
  try {
@@ -24642,7 +24705,7 @@ function readRegularFile(path, realPairsDir, name) {
24642
24705
  if (listed.nlink !== 1) {
24643
24706
  throw new ResearchError(`ledger record ${path} has ${listed.nlink} links; a hard link can name a file outside pairs/, so only a singly linked regular file is read`);
24644
24707
  }
24645
- const real = realpathSync12.native(path);
24708
+ const real = realpathSync13.native(path);
24646
24709
  if (real !== join30(realPairsDir, name)) {
24647
24710
  throw new ResearchError(`ledger record ${path} resolves outside the pairs directory (${real}); refusing to read it`);
24648
24711
  }
@@ -24672,7 +24735,7 @@ function readPairFiles(ledger) {
24672
24735
  throw new ResearchError(`ledger pairs directory ${pairsDir} is a symlink; only a real directory is read`);
24673
24736
  }
24674
24737
  if (dirStat === null || !dirStat.isDirectory()) throw new ResearchError(`ledger ${root} has no pairs directory`);
24675
- const realPairsDir = realpathSync12.native(pairsDir);
24738
+ const realPairsDir = realpathSync13.native(pairsDir);
24676
24739
  let names;
24677
24740
  try {
24678
24741
  names = readdirSync8(pairsDir).filter((n2) => n2.endsWith(".json")).sort();
@@ -26051,6 +26114,7 @@ function validateCliArgs(cmd, args) {
26051
26114
  "--base": "string",
26052
26115
  "--cmd": "string",
26053
26116
  "--cwd": "string",
26117
+ "--cargo-target-root": "string",
26054
26118
  "--budget": "positive"
26055
26119
  }
26056
26120
  }).error;
@@ -26228,6 +26292,8 @@ Formats:
26228
26292
  (exit 1, or 0 under a compact tw1:<digest>
26229
26293
  or legacy verify@<full-sha> approval); cannot-verify
26230
26294
  fails closed (2)
26295
+ [--cargo-target-root D] separate local Cargo targets D/visible
26296
+ and D/pristine (operator-owned cache)
26231
26297
  tamperward trace-verify [--base R] advisory Linux verifier-input discovery:
26232
26298
  [--cmd C] [--budget S] [--runs N] trace a trusted/known-good base with
26233
26299
  [--json] [--cwd D] strace, union repeated observations,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tamperward",
3
- "version": "2.42.0",
3
+ "version": "2.43.0",
4
4
  "description": "The deterministic agent-integrity gate. One ruleset, evaluated on the actual diff/commands as a verdict, enforced everywhere a change can be made.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "hexrift",