tamperward 2.39.4 → 2.39.6

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 +195 -108
  2. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -1239,11 +1239,26 @@ function git(args, cwd) {
1239
1239
  throw new Error(detail ? `git ${args[0]}: ${detail}` : failure.message || `git ${args[0]} failed`);
1240
1240
  }
1241
1241
  }
1242
+ function entryKindAt(rev2, path, cwd) {
1243
+ const listing = rev2 === "" ? git(["ls-files", "-s", "-z", "--", `:(literal)${path}`], cwd) : git(["ls-tree", "-z", rev2, "--", `:(literal)${path}`], cwd);
1244
+ for (const record of listing.split("\0")) {
1245
+ const tab = record.indexOf(" ");
1246
+ if (tab === -1 || record.slice(tab + 1) !== path) continue;
1247
+ const meta2 = record.slice(0, tab).split(" ");
1248
+ const mode = meta2[0] ?? "";
1249
+ const isBlob = rev2 === "" ? mode !== "160000" && !mode.startsWith("04") : meta2[1] === "blob";
1250
+ return isBlob ? "blob" : "other";
1251
+ }
1252
+ return "absent";
1253
+ }
1242
1254
  function blobAt(rev2, path, cwd) {
1243
1255
  try {
1244
1256
  return git(["show", `${rev2}:${path}`], cwd);
1245
- } catch {
1246
- return null;
1257
+ } catch (e) {
1258
+ if (entryKindAt(rev2, path, cwd) !== "blob") return null;
1259
+ const detail = (e instanceof Error ? e.message : String(e)).split("\n")[0];
1260
+ const where = rev2 === "" ? "the index entry " : `${rev2}:`;
1261
+ throw new Error(`cannot read ${where}${path} although the tree lists it as a blob (${detail}); refusing to judge it as absent`);
1247
1262
  }
1248
1263
  }
1249
1264
  function fromDisk(path, cwd) {
@@ -10885,8 +10900,8 @@ var init_policy_load = __esm({
10885
10900
 
10886
10901
  // src/signoff.ts
10887
10902
  import { createHash as createHash3 } from "node:crypto";
10888
- import { appendFileSync, mkdirSync, readFileSync as readFileSync6, existsSync as existsSync6 } from "node:fs";
10889
- import { dirname as dirname2, join as join9 } from "node:path";
10903
+ import { appendFileSync, closeSync as closeSync2, constants as constants3, fstatSync as fstatSync2, lstatSync as lstatSync3, mkdirSync, openSync as openSync2, readFileSync as readFileSync6 } from "node:fs";
10904
+ import { dirname as dirname2, join as join9, posix as posix4 } from "node:path";
10890
10905
  function compactOobToken(want, head) {
10891
10906
  const normalizedHead = head.trim().toLowerCase();
10892
10907
  if (!want || !FULL_OBJECT_ID.test(normalizedHead)) return null;
@@ -10905,17 +10920,75 @@ function fingerprint(rule, file, evidence) {
10905
10920
  return createHash3("sha256").update(`${rule}\0${file ?? ""}\0${evidence}`).digest("hex").slice(0, 16);
10906
10921
  }
10907
10922
  function ledgerPath(cwd, policy) {
10908
- const rel = policy.signoff?.ledger ?? ".tamperward/ledger.jsonl";
10923
+ const rel = policy.signoff?.ledger ?? DEFAULT_LEDGER;
10909
10924
  if (!ledgerInsideRepo(rel)) {
10910
10925
  throw new PolicyError(`signoff.ledger must be a relative path inside the repository, got ${JSON.stringify(rel)}`);
10911
10926
  }
10912
10927
  return join9(cwd, rel);
10913
10928
  }
10929
+ function lstatOrAbsent(rel, shown, path) {
10930
+ try {
10931
+ return lstatSync3(path);
10932
+ } catch (e) {
10933
+ if (errnoCode(e) === "ENOENT") return null;
10934
+ throw new PolicyError(
10935
+ `signoff.ledger ${JSON.stringify(rel)}: cannot stat ${shown} (${errorMessage(e)}); refusing to treat the sign-off ledger as absent`
10936
+ );
10937
+ }
10938
+ }
10939
+ function kindOf(st) {
10940
+ if (st.isSymbolicLink()) return "a symbolic link";
10941
+ if (st.isDirectory()) return "a directory";
10942
+ if (st.isFIFO()) return "a FIFO";
10943
+ if (st.isSocket()) return "a socket";
10944
+ if (st.isCharacterDevice() || st.isBlockDevice()) return "a device";
10945
+ return "not a regular file";
10946
+ }
10947
+ function ledgerOnDisk(cwd, policy) {
10948
+ const rel = policy.signoff?.ledger ?? DEFAULT_LEDGER;
10949
+ ledgerPath(cwd, policy);
10950
+ const parts = posix4.normalize(rel.replace(/\\/g, "/")).split("/").filter((part) => part && part !== ".");
10951
+ let path = cwd;
10952
+ for (let i = 0; i < parts.length; i++) {
10953
+ const next = join9(path, parts[i]);
10954
+ const shown = parts.slice(0, i + 1).join("/");
10955
+ const st = lstatOrAbsent(rel, shown, next);
10956
+ if (st === null) return { rel, path: join9(cwd, ...parts), exists: false };
10957
+ const last = i === parts.length - 1;
10958
+ if (st.isSymbolicLink() || (last ? !st.isFile() : !st.isDirectory())) {
10959
+ throw new PolicyError(
10960
+ `signoff.ledger ${JSON.stringify(rel)}: ${shown} is ${kindOf(st)}; the sign-off ledger is honored only as a regular file inside the repository, reached without following a link`
10961
+ );
10962
+ }
10963
+ path = next;
10964
+ }
10965
+ return { rel, path, exists: true };
10966
+ }
10967
+ function openLedger(rel, path, flags) {
10968
+ let fd;
10969
+ try {
10970
+ fd = openSync2(path, flags | (constants3.O_NOFOLLOW ?? 0), 420);
10971
+ } catch (e) {
10972
+ throw new PolicyError(`signoff.ledger ${JSON.stringify(rel)}: cannot open ${path} (${e instanceof Error ? e.message : String(e)})`);
10973
+ }
10974
+ if (!fstatSync2(fd).isFile()) {
10975
+ closeSync2(fd);
10976
+ throw new PolicyError(`signoff.ledger ${JSON.stringify(rel)}: ${path} is not a regular file; refusing to use it`);
10977
+ }
10978
+ return fd;
10979
+ }
10914
10980
  function readLedger(cwd, policy) {
10915
- const p = ledgerPath(cwd, policy);
10916
- if (!existsSync6(p)) return [];
10981
+ const { rel, path, exists } = ledgerOnDisk(cwd, policy);
10982
+ if (!exists) return [];
10983
+ const fd = openLedger(rel, path, constants3.O_RDONLY);
10984
+ let text;
10985
+ try {
10986
+ text = readFileSync6(fd, "utf8");
10987
+ } finally {
10988
+ closeSync2(fd);
10989
+ }
10917
10990
  const out3 = [];
10918
- for (const line of readFileSync6(p, "utf8").split("\n")) {
10991
+ for (const line of text.split("\n")) {
10919
10992
  if (!line.trim()) continue;
10920
10993
  try {
10921
10994
  const e = ledgerEntryFrom(JSON.parse(line));
@@ -10926,15 +10999,27 @@ function readLedger(cwd, policy) {
10926
10999
  return out3;
10927
11000
  }
10928
11001
  function appendEntry(cwd, policy, e) {
10929
- const p = ledgerPath(cwd, policy);
10930
- mkdirSync(dirname2(p), { recursive: true });
10931
- appendFileSync(p, JSON.stringify(e) + "\n");
11002
+ const { rel, path } = ledgerOnDisk(cwd, policy);
11003
+ try {
11004
+ mkdirSync(dirname2(path), { recursive: true });
11005
+ } catch (err3) {
11006
+ throw new PolicyError(`signoff.ledger ${JSON.stringify(rel)}: cannot create ${dirname2(path)} (${errorMessage(err3)})`);
11007
+ }
11008
+ const fd = openLedger(rel, path, constants3.O_WRONLY | constants3.O_APPEND | constants3.O_CREAT);
11009
+ try {
11010
+ appendFileSync(fd, JSON.stringify(e) + "\n");
11011
+ } finally {
11012
+ closeSync2(fd);
11013
+ }
10932
11014
  }
10933
11015
  function makeEntry(f, reason, now, ttlMs = DEFAULT_TTL_MS) {
10934
11016
  return { rule: f.rule, file: f.file, fingerprint: fingerprintOf(f), reason, recordedAt: now, expiresAt: now + ttlMs };
10935
11017
  }
11018
+ function honoredAt(e, now) {
11019
+ return e.expiresAt > now && e.recordedAt <= now && e.expiresAt - e.recordedAt <= LEDGER_TTL_MS;
11020
+ }
10936
11021
  function applyLocalSignoffs(findings, cwd, policy, now = Date.now()) {
10937
- const ledger = readLedger(cwd, policy).filter((e) => e.expiresAt > now);
11022
+ const ledger = readLedger(cwd, policy).filter((e) => honoredAt(e, now));
10938
11023
  const valid = new Set(ledger.map((e) => e.fingerprint));
10939
11024
  const cleared = [];
10940
11025
  const remaining = [];
@@ -10985,13 +11070,15 @@ function oobHeadFromEnv(env = process.env) {
10985
11070
  function oobFromEnv(env = process.env) {
10986
11071
  return (env.TAMPERWARD_OOB_SIGNOFF ?? "").split(",").map((s) => s.trim().replace(/^tamperward:allow:/, "")).filter(Boolean);
10987
11072
  }
10988
- var DEFAULT_TTL_MS, COMPACT_OOB_PREFIX, FULL_OBJECT_ID, fingerprintOf;
11073
+ var LEDGER_TTL_MS, DEFAULT_TTL_MS, DEFAULT_LEDGER, COMPACT_OOB_PREFIX, FULL_OBJECT_ID, fingerprintOf;
10989
11074
  var init_signoff = __esm({
10990
11075
  "src/signoff.ts"() {
10991
11076
  "use strict";
10992
11077
  init_policy_load();
10993
11078
  init_narrow();
10994
- DEFAULT_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
11079
+ LEDGER_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
11080
+ DEFAULT_TTL_MS = LEDGER_TTL_MS;
11081
+ DEFAULT_LEDGER = ".tamperward/ledger.jsonl";
10995
11082
  COMPACT_OOB_PREFIX = "tw1:";
10996
11083
  FULL_OBJECT_ID = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/i;
10997
11084
  fingerprintOf = (f) => fingerprint(f.rule, f.file, f.evidence);
@@ -11437,7 +11524,7 @@ var init_deny = __esm({
11437
11524
  });
11438
11525
 
11439
11526
  // src/session.ts
11440
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync7, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
11527
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync7, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
11441
11528
  import { dirname as dirname3, join as join10 } from "node:path";
11442
11529
  function writeBaseline(p, sha3) {
11443
11530
  mkdirSync2(dirname3(p), { recursive: true });
@@ -11463,7 +11550,7 @@ function turnBaseline(cwd, sessionId) {
11463
11550
  const p = baselinePath(cwd, sessionId);
11464
11551
  if (!p) return null;
11465
11552
  try {
11466
- if (existsSync7(p)) {
11553
+ if (existsSync6(p)) {
11467
11554
  const v = readFileSync7(p, "utf8").trim();
11468
11555
  if (SHA.test(v)) return v;
11469
11556
  }
@@ -11507,7 +11594,7 @@ var init_session = __esm({
11507
11594
 
11508
11595
  // src/effect.ts
11509
11596
  import { createHash as createHash4 } from "node:crypto";
11510
- import { existsSync as existsSync8, lstatSync as lstatSync3, mkdirSync as mkdirSync3, readdirSync, readFileSync as readFileSync8, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "node:fs";
11597
+ import { existsSync as existsSync7, lstatSync as lstatSync4, mkdirSync as mkdirSync3, readdirSync, readFileSync as readFileSync8, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "node:fs";
11511
11598
  import { join as join11 } from "node:path";
11512
11599
  function ptreeFrom(value) {
11513
11600
  if (!isRecord(value)) return null;
@@ -11572,7 +11659,7 @@ function snapshotProtected(cwd, policy, prev, cache3) {
11572
11659
  if (pruned.has(r)) continue;
11573
11660
  let st;
11574
11661
  try {
11575
- st = lstatSync3(join11(cwd, r));
11662
+ st = lstatSync4(join11(cwd, r));
11576
11663
  } catch {
11577
11664
  continue;
11578
11665
  }
@@ -11599,7 +11686,7 @@ function driftBetween(expected, current) {
11599
11686
  return { changed, deleted, added };
11600
11687
  }
11601
11688
  function loadTree(p) {
11602
- if (!p || !existsSync8(p)) return null;
11689
+ if (!p || !existsSync7(p)) return null;
11603
11690
  try {
11604
11691
  return ptreeFrom(JSON.parse(readFileSync8(p, "utf8")));
11605
11692
  } catch {
@@ -11654,7 +11741,7 @@ var init_effect = __esm({
11654
11741
  });
11655
11742
 
11656
11743
  // src/cli/watch.ts
11657
- import { appendFileSync as appendFileSync3, lstatSync as lstatSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync9, readdirSync as readdirSync2, watch, writeFileSync as writeFileSync4 } from "node:fs";
11744
+ import { appendFileSync as appendFileSync3, lstatSync as lstatSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync9, readdirSync as readdirSync2, watch, writeFileSync as writeFileSync4 } from "node:fs";
11658
11745
  import { join as join12 } from "node:path";
11659
11746
  import { createHash as createHash5 } from "node:crypto";
11660
11747
  function snap(abs) {
@@ -11757,7 +11844,7 @@ function watchTree(dir, cb, onState, onError, watchFn = watch) {
11757
11844
  const child = rel ? `${rel}/${String(fname)}` : String(fname);
11758
11845
  cb(kind, child);
11759
11846
  try {
11760
- if (lstatSync4(join12(dir, child)).isDirectory()) addDir(child);
11847
+ if (lstatSync5(join12(dir, child)).isDirectory()) addDir(child);
11761
11848
  } catch {
11762
11849
  }
11763
11850
  });
@@ -11793,7 +11880,7 @@ function watchTree(dir, cb, onState, onError, watchFn = watch) {
11793
11880
  const child = rel ? `${rel}/${name}` : name;
11794
11881
  if (SKIP2.test(child + "/")) continue;
11795
11882
  try {
11796
- if (lstatSync4(join12(dir, child)).isDirectory()) walk2(child);
11883
+ if (lstatSync5(join12(dir, child)).isDirectory()) walk2(child);
11797
11884
  } catch {
11798
11885
  }
11799
11886
  }
@@ -11944,7 +12031,7 @@ var init_watch = __esm({
11944
12031
  });
11945
12032
 
11946
12033
  // src/detectors/fs-events.ts
11947
- import { closeSync as closeSync2, openSync as openSync2, readSync as readSync2, statSync as statSync2 } from "node:fs";
12034
+ import { closeSync as closeSync3, openSync as openSync3, readSync as readSync2, statSync as statSync2 } from "node:fs";
11948
12035
  function fsEventFrom(line) {
11949
12036
  let value;
11950
12037
  try {
@@ -11991,12 +12078,12 @@ function readEvents(log, offset, maxBytes = MAX_EVENT_READ_BYTES, io = DEFAULT_E
11991
12078
  const available = size - start;
11992
12079
  const requested = Math.min(available, cap);
11993
12080
  const buffer = Buffer.allocUnsafe(requested);
11994
- const fd = openSync2(log, "r");
12081
+ const fd = openSync3(log, "r");
11995
12082
  let bytesRead = 0;
11996
12083
  try {
11997
12084
  bytesRead = io.read(fd, buffer, 0, requested, start);
11998
12085
  } finally {
11999
- closeSync2(fd);
12086
+ closeSync3(fd);
12000
12087
  }
12001
12088
  if (bytesRead <= 0) {
12002
12089
  return {
@@ -12201,7 +12288,7 @@ var init_fs_events = __esm({
12201
12288
 
12202
12289
  // src/cli/audit.ts
12203
12290
  import { createHash as createHash6, randomBytes } from "node:crypto";
12204
- import { appendFileSync as appendFileSync4, closeSync as closeSync3, existsSync as existsSync9, mkdirSync as mkdirSync5, openSync as openSync3, readSync as readSync3 } from "node:fs";
12291
+ import { appendFileSync as appendFileSync4, closeSync as closeSync4, existsSync as existsSync8, mkdirSync as mkdirSync5, openSync as openSync4, readSync as readSync3 } from "node:fs";
12205
12292
  import { dirname as dirname4, isAbsolute as isAbsolute8, join as join13, resolve as resolve4 } from "node:path";
12206
12293
  function sessionHash(sessionId) {
12207
12294
  if (!sessionId) return void 0;
@@ -12321,7 +12408,7 @@ function parseAuditLine(line, lineNumber) {
12321
12408
  return parseAuditEvent(value, lineNumber);
12322
12409
  }
12323
12410
  function forEachAuditLine(file, onLine, maxLineBytes = MAX_AUDIT_LINE_BYTES) {
12324
- const fd = openSync3(file, "r");
12411
+ const fd = openSync4(file, "r");
12325
12412
  try {
12326
12413
  const chunk = Buffer.allocUnsafe(64 * 1024);
12327
12414
  let pending = [];
@@ -12359,7 +12446,7 @@ function forEachAuditLine(file, onLine, maxLineBytes = MAX_AUDIT_LINE_BYTES) {
12359
12446
  }
12360
12447
  if (pending.length) emit3(pending);
12361
12448
  } finally {
12362
- closeSync3(fd);
12449
+ closeSync4(fd);
12363
12450
  }
12364
12451
  }
12365
12452
  function parseSince(value, nowMs = Date.now()) {
@@ -12460,7 +12547,7 @@ function runStats(opts = {}) {
12460
12547
  const file = opts.file ? isAbsolute8(opts.file) ? opts.file : resolve4(cwd, opts.file) : configured && configured !== "auto" ? isAbsolute8(configured) ? configured : resolve4(cwd, configured) : defaultAuditPath(cwd);
12461
12548
  const cutoff = opts.since ? parseSince(opts.since) : null;
12462
12549
  if (!file) throw new Error("stats needs --file outside a Git repository");
12463
- if (!existsSync9(file)) {
12550
+ if (!existsSync8(file)) {
12464
12551
  if (explicitFile) throw new Error(`audit file not found: ${file}`);
12465
12552
  const empty2 = summarizeAudit([]);
12466
12553
  process.stdout.write(opts.json ? JSON.stringify(empty2) + "\n" : renderAuditStats(empty2));
@@ -12499,7 +12586,7 @@ var init_audit = __esm({
12499
12586
  });
12500
12587
 
12501
12588
  // src/cli/hook.ts
12502
- import { readFileSync as readFileSync10, appendFileSync as appendFileSync5, writeFileSync as writeFileSync5, existsSync as existsSync10 } from "node:fs";
12589
+ import { readFileSync as readFileSync10, appendFileSync as appendFileSync5, writeFileSync as writeFileSync5, existsSync as existsSync9 } from "node:fs";
12503
12590
  import { createHash as createHash7 } from "node:crypto";
12504
12591
  function setSnapshotCache(cache3) {
12505
12592
  snapshotCache = cache3;
@@ -12796,9 +12883,9 @@ function turnTransientBlocks(cwd, sessionId, policy, changes) {
12796
12883
  recordObserverHealth(cwd, sessionId, telemetry.state, telemetry.reason);
12797
12884
  }
12798
12885
  const cp = cursorPath(cwd, sessionId);
12799
- if (!existsSync10(log)) return none;
12886
+ if (!existsSync9(log)) return none;
12800
12887
  let offset = 0;
12801
- if (cp && existsSync10(cp)) {
12888
+ if (cp && existsSync9(cp)) {
12802
12889
  const n2 = Number(readFileSync10(cp, "utf8"));
12803
12890
  offset = Number.isFinite(n2) ? n2 : 0;
12804
12891
  }
@@ -12979,7 +13066,7 @@ var init_hook = __esm({
12979
13066
  });
12980
13067
 
12981
13068
  // src/ptree-cache.ts
12982
- import { lstatSync as lstatSync5 } from "node:fs";
13069
+ import { lstatSync as lstatSync6 } from "node:fs";
12983
13070
  import { join as join14 } from "node:path";
12984
13071
  function keyOf(st) {
12985
13072
  return `${st.dev}:${st.ino}:${st.size}:${st.mode}:${st.mtimeNs}:${st.ctimeNs}`;
@@ -13033,7 +13120,7 @@ var init_ptree_cache = __esm({
13033
13120
  const abs = join14(cwd, rel);
13034
13121
  let st;
13035
13122
  try {
13036
- st = lstatSync5(abs, { bigint: true });
13123
+ st = lstatSync6(abs, { bigint: true });
13037
13124
  } catch {
13038
13125
  this.map.delete(abs);
13039
13126
  this.stats.misses++;
@@ -13055,7 +13142,7 @@ var init_ptree_cache = __esm({
13055
13142
  const entry = compute();
13056
13143
  let after;
13057
13144
  try {
13058
- after = lstatSync5(abs, { bigint: true });
13145
+ after = lstatSync6(abs, { bigint: true });
13059
13146
  } catch {
13060
13147
  this.map.delete(abs);
13061
13148
  return entry;
@@ -13073,7 +13160,7 @@ var init_ptree_cache = __esm({
13073
13160
  });
13074
13161
 
13075
13162
  // src/cli/hook-service.ts
13076
- import { chmodSync, existsSync as existsSync11, lstatSync as lstatSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync11, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "node:fs";
13163
+ import { chmodSync, existsSync as existsSync10, lstatSync as lstatSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync11, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "node:fs";
13077
13164
  import { createConnection as createConnection2, createServer } from "node:net";
13078
13165
  import { realpathSync as realpathSync4 } from "node:fs";
13079
13166
  import { sep } from "node:path";
@@ -13161,8 +13248,8 @@ function removeQuietly(p) {
13161
13248
  }
13162
13249
  }
13163
13250
  function ensurePrivateDir(dir, uid) {
13164
- if (!existsSync11(dir)) mkdirSync6(dir, { recursive: true, mode: 448 });
13165
- const st = lstatSync6(dir);
13251
+ if (!existsSync10(dir)) mkdirSync6(dir, { recursive: true, mode: 448 });
13252
+ const st = lstatSync7(dir);
13166
13253
  if (!st.isDirectory()) throw new Error(`${dir} is not a directory`);
13167
13254
  if (st.uid !== uid) throw new Error(`${dir} is owned by uid ${st.uid}, not ${uid}; refusing to serve from it`);
13168
13255
  if ((st.mode & 63) !== 0) chmodSync(dir, 448);
@@ -13358,7 +13445,7 @@ async function stopHookService(paths, expectedRoot) {
13358
13445
  process.kill(st.pid, "SIGTERM");
13359
13446
  } catch {
13360
13447
  }
13361
- const gone = () => !pidAlive2(st.pid) || !existsSync11(paths.socket);
13448
+ const gone = () => !pidAlive2(st.pid) || !existsSync10(paths.socket);
13362
13449
  const until = Date.now() + STOP_WAIT_MS;
13363
13450
  while (!gone() && Date.now() < until) sleepSync(50);
13364
13451
  if (!gone()) throw new Error(`hook service pid ${st.pid} did not exit within ${STOP_WAIT_MS / 1e3}s`);
@@ -13594,11 +13681,11 @@ var init_verifier_limits = __esm({
13594
13681
 
13595
13682
  // src/safe-write.ts
13596
13683
  import { randomBytes as randomBytes2 } from "node:crypto";
13597
- import { lstatSync as lstatSync7, renameSync as renameSync3, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "node:fs";
13684
+ import { lstatSync as lstatSync8, renameSync as renameSync3, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "node:fs";
13598
13685
  function writeTargetKind(path) {
13599
13686
  let st;
13600
13687
  try {
13601
- st = lstatSync7(path, { throwIfNoEntry: false });
13688
+ st = lstatSync8(path, { throwIfNoEntry: false });
13602
13689
  } catch (e) {
13603
13690
  if (errnoCode(e) === "ENOTDIR") return "absent";
13604
13691
  throw e;
@@ -13619,7 +13706,7 @@ function refuseNonRegular(path) {
13619
13706
  }
13620
13707
  function existingMode(path, fallback) {
13621
13708
  if (writeTargetKind(path) !== "file") return fallback;
13622
- return lstatSync7(path).mode & 511;
13709
+ return lstatSync8(path).mode & 511;
13623
13710
  }
13624
13711
  function atomicReplaceFile(path, content, mode) {
13625
13712
  const tmp = `${path}.${process.pid}.${randomBytes2(8).toString("hex")}.tmp`;
@@ -13640,7 +13727,7 @@ var init_safe_write = __esm({
13640
13727
  // src/cli/init.ts
13641
13728
  import { execFileSync as execFileSync6 } from "node:child_process";
13642
13729
  import { createHash as createHash8 } from "node:crypto";
13643
- import { existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync12, realpathSync as realpathSync5 } from "node:fs";
13730
+ import { existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync12, realpathSync as realpathSync5 } from "node:fs";
13644
13731
  import { basename as basename3, dirname as dirname5, isAbsolute as isAbsolute9, join as join15, relative as relative4, resolve as resolve6 } from "node:path";
13645
13732
  function gitConfig(cwd, key2) {
13646
13733
  try {
@@ -13744,7 +13831,7 @@ function verifierCandidates(cwd) {
13744
13831
  if (/^\s*\[tool\.pytest(?:\.ini_options)?\]\s*$/m.test(pyproject)) add("pytest");
13745
13832
  } catch {
13746
13833
  }
13747
- if (existsSync12(join15(cwd, "pytest.ini"))) add("pytest");
13834
+ if (existsSync11(join15(cwd, "pytest.ini"))) add("pytest");
13748
13835
  try {
13749
13836
  const setupCfg = readFileSync12(join15(cwd, "setup.cfg"), "utf8");
13750
13837
  if (/^\s*\[tool:pytest\]\s*$/m.test(setupCfg)) add("pytest");
@@ -13804,7 +13891,7 @@ function planPolicy(cwd) {
13804
13891
  const path = join15(cwd, POLICY_FILE);
13805
13892
  const refused = refuseNonRegular(path);
13806
13893
  if (refused) return { item: "policy", path: POLICY_FILE, status: "error", detail: refused };
13807
- if (existsSync12(path)) {
13894
+ if (existsSync11(path)) {
13808
13895
  try {
13809
13896
  loadPolicy(cwd);
13810
13897
  } catch (e) {
@@ -13823,7 +13910,7 @@ function planPolicy(cwd) {
13823
13910
  function planGitignore(cwd) {
13824
13911
  const rel = ".gitignore";
13825
13912
  const path = join15(cwd, rel);
13826
- if (!existsSync12(join15(cwd, "node_modules"))) return null;
13913
+ if (!existsSync11(join15(cwd, "node_modules"))) return null;
13827
13914
  let existing = "";
13828
13915
  let kind;
13829
13916
  try {
@@ -13888,7 +13975,7 @@ function planClaudeHooks(cwd) {
13888
13975
  const refused = refuseNonRegular(path);
13889
13976
  if (refused) return { item: "agent", path: rel, status: "error", detail: refused };
13890
13977
  let settings = {};
13891
- if (existsSync12(path)) {
13978
+ if (existsSync11(path)) {
13892
13979
  let parsed;
13893
13980
  try {
13894
13981
  parsed = JSON.parse(readFileSync12(path, "utf8"));
@@ -13940,7 +14027,7 @@ function planClaudeHooks(cwd) {
13940
14027
  return {
13941
14028
  item: "agent",
13942
14029
  path: rel,
13943
- status: existsSync12(path) ? "update" : "create",
14030
+ status: existsSync11(path) ? "update" : "create",
13944
14031
  detail: [
13945
14032
  needPre && "wire PreToolUse deny",
13946
14033
  needStop && "wire Stop sweep",
@@ -13984,7 +14071,7 @@ function hooksDir(cwd) {
13984
14071
  if (out3) return resolve6(cwd, out3);
13985
14072
  } catch {
13986
14073
  }
13987
- return existsSync12(join15(cwd, ".git")) ? join15(cwd, ".git", "hooks") : null;
14074
+ return existsSync11(join15(cwd, ".git")) ? join15(cwd, ".git", "hooks") : null;
13988
14075
  }
13989
14076
  function display(cwd, path) {
13990
14077
  const rel = relative4(cwd, path);
@@ -14011,11 +14098,11 @@ function planPreCommit(cwd) {
14011
14098
  const skip = (detail) => ({ item: "pre-commit", path: "(none)", status: "skip", detail });
14012
14099
  let path;
14013
14100
  let note;
14014
- if (existsSync12(join15(cwd, ".husky"))) {
14101
+ if (existsSync11(join15(cwd, ".husky"))) {
14015
14102
  path = join15(cwd, ".husky", "pre-commit");
14016
14103
  note = "husky";
14017
14104
  } else {
14018
- const managed = MANAGED_HOOKS.find((m) => m.configs.some((c) => existsSync12(join15(cwd, c))));
14105
+ const managed = MANAGED_HOOKS.find((m) => m.configs.some((c) => existsSync11(join15(cwd, c))));
14019
14106
  if (managed) {
14020
14107
  return skip(`${managed.name} manages this repository's hooks and regenerates them on install, so a line in the hooks directory would not last \u2014 ${managed.hint}`);
14021
14108
  }
@@ -14033,7 +14120,7 @@ function planPreCommit(cwd) {
14033
14120
  const rel = display(cwd, path);
14034
14121
  const refused = refuseNonRegular(path);
14035
14122
  if (refused) return { item: "pre-commit", path: rel, status: "error", detail: refused };
14036
- const existing = existsSync12(path) ? readFileSync12(path, "utf8") : null;
14123
+ const existing = existsSync11(path) ? readFileSync12(path, "utf8") : null;
14037
14124
  const hookMode = () => existingMode(path, 493) | 73;
14038
14125
  if (existing === null) {
14039
14126
  return {
@@ -14164,7 +14251,7 @@ function planWorkflow(cwd, force) {
14164
14251
  };
14165
14252
  const refused = refuseNonRegular(path);
14166
14253
  if (refused) return { item: "ci", path: rel, status: "error", detail: refused };
14167
- if (!existsSync12(path)) {
14254
+ if (!existsSync11(path)) {
14168
14255
  return {
14169
14256
  item: "ci",
14170
14257
  path: rel,
@@ -14522,8 +14609,8 @@ var init_fingerprint = __esm({
14522
14609
  // src/dependency-env.ts
14523
14610
  import { createHash as createHash10 } from "node:crypto";
14524
14611
  import {
14525
- existsSync as existsSync13,
14526
- lstatSync as lstatSync8,
14612
+ existsSync as existsSync12,
14613
+ lstatSync as lstatSync9,
14527
14614
  readdirSync as readdirSync3,
14528
14615
  readFileSync as readFileSync13,
14529
14616
  readlinkSync as readlinkSync2,
@@ -14548,7 +14635,7 @@ function inside(root, candidate) {
14548
14635
  return rel === "" || rel !== ".." && !rel.startsWith(".." + sep3) && !isAbsolute10(rel);
14549
14636
  }
14550
14637
  function modeKind(path) {
14551
- const st = lstatSync8(path);
14638
+ const st = lstatSync9(path);
14552
14639
  if (st.isFile()) return { kind: "file", mode: st.mode };
14553
14640
  if (st.isDirectory()) return { kind: "dir", mode: st.mode };
14554
14641
  if (st.isSymbolicLink()) return { kind: "symlink", mode: st.mode };
@@ -14558,7 +14645,7 @@ function fingerprintRoot(root, cwd, h) {
14558
14645
  let rootStat;
14559
14646
  let currentReal;
14560
14647
  try {
14561
- rootStat = lstatSync8(root.path);
14648
+ rootStat = lstatSync9(root.path);
14562
14649
  currentReal = realpathSync6(root.path);
14563
14650
  } catch (e) {
14564
14651
  throw new Unattestable(
@@ -14676,7 +14763,7 @@ function snapshot(roots, probes, cwd) {
14676
14763
  const h = createHash10("sha256");
14677
14764
  for (const probe of probes) {
14678
14765
  h.update(
14679
- "probe\0" + probe.kind + "\0" + probe.path + "\0" + (existsSync13(probe.path) ? "present" : "absent") + "\0"
14766
+ "probe\0" + probe.kind + "\0" + probe.path + "\0" + (existsSync12(probe.path) ? "present" : "absent") + "\0"
14680
14767
  );
14681
14768
  }
14682
14769
  for (const root of roots) fingerprintRoot(root, cwd, h);
@@ -14735,7 +14822,7 @@ function resolveExecutable(token, cwd, env) {
14735
14822
  if (token.includes("/") || token.includes("\\")) {
14736
14823
  const path = isAbsolute10(token) ? token : resolve7(cwd, token);
14737
14824
  try {
14738
- return existsSync13(path) ? realpathSync6(path) : null;
14825
+ return existsSync12(path) ? realpathSync6(path) : null;
14739
14826
  } catch {
14740
14827
  return null;
14741
14828
  }
@@ -14743,7 +14830,7 @@ function resolveExecutable(token, cwd, env) {
14743
14830
  for (const entry of (env.PATH ?? "").split(delimiter).filter(Boolean)) {
14744
14831
  const candidate = resolve7(entry, token);
14745
14832
  try {
14746
- if (existsSync13(candidate) && statSync3(candidate).isFile()) return realpathSync6(candidate);
14833
+ if (existsSync12(candidate) && statSync3(candidate).isFile()) return realpathSync6(candidate);
14747
14834
  } catch {
14748
14835
  }
14749
14836
  }
@@ -14766,7 +14853,7 @@ function inferredVenvFromToken(token, cwd) {
14766
14853
  const parentName = basename4(parent).toLowerCase();
14767
14854
  if (parentName !== "bin" && parentName !== "scripts") return null;
14768
14855
  const root = dirname6(parent);
14769
- return existsSync13(join16(root, "pyvenv.cfg")) ? root : null;
14856
+ return existsSync12(join16(root, "pyvenv.cfg")) ? root : null;
14770
14857
  }
14771
14858
  function unsupportedEcosystem(command, token) {
14772
14859
  const name = token ? basename4(token).toLowerCase() : "";
@@ -14782,11 +14869,11 @@ function inferredVenv(executable) {
14782
14869
  const parentName = basename4(parent).toLowerCase();
14783
14870
  if (parentName !== "bin" && parentName !== "scripts") return null;
14784
14871
  const root = dirname6(parent);
14785
- return existsSync13(join16(root, "pyvenv.cfg")) ? root : null;
14872
+ return existsSync12(join16(root, "pyvenv.cfg")) ? root : null;
14786
14873
  }
14787
14874
  function venvProblem(root) {
14788
14875
  const cfg = join16(root, "pyvenv.cfg");
14789
- if (!existsSync13(cfg)) return "VIRTUAL_ENV " + JSON.stringify(root) + " has no pyvenv.cfg";
14876
+ if (!existsSync12(cfg)) return "VIRTUAL_ENV " + JSON.stringify(root) + " has no pyvenv.cfg";
14790
14877
  try {
14791
14878
  const body = readFileSync13(cfg, "utf8");
14792
14879
  if (/^\s*include-system-site-packages\s*=\s*true\s*$/im.test(body)) {
@@ -14813,7 +14900,7 @@ function discoverDependencyEnvironment(cwdInput, command, env = process.env) {
14813
14900
  };
14814
14901
  try {
14815
14902
  const nodeModules = join16(cwd, "node_modules");
14816
- if (existsSync13(nodeModules)) addRoot("node_modules", nodeModules);
14903
+ if (existsSync12(nodeModules)) addRoot("node_modules", nodeModules);
14817
14904
  else probes.push({ kind: "node_modules", path: nodeModules });
14818
14905
  const token = firstExecutable(command);
14819
14906
  const executable = resolveExecutable(token, cwd, env);
@@ -14825,7 +14912,7 @@ function discoverDependencyEnvironment(cwdInput, command, env = process.env) {
14825
14912
  venv = resolve7(env.VIRTUAL_ENV);
14826
14913
  } else {
14827
14914
  venv = inferredVenv(executable) ?? inferredVenvFromToken(token, cwd);
14828
- if (!venv && /(?:^|\s)uv\s+run(?:\s|$)/.test(command) && existsSync13(join16(cwd, ".venv", "pyvenv.cfg"))) {
14915
+ if (!venv && /(?:^|\s)uv\s+run(?:\s|$)/.test(command) && existsSync12(join16(cwd, ".venv", "pyvenv.cfg"))) {
14829
14916
  venv = join16(cwd, ".venv");
14830
14917
  }
14831
14918
  }
@@ -15304,7 +15391,7 @@ if (child) {
15304
15391
  // src/verifier-backend.ts
15305
15392
  import { createHash as createHash11, randomUUID } from "node:crypto";
15306
15393
  import { spawnSync as spawnSync2 } from "node:child_process";
15307
- import { accessSync as accessSync2, constants as constants3, readFileSync as readFileSync14, realpathSync as realpathSync7, statSync as statSync4 } from "node:fs";
15394
+ import { accessSync as accessSync2, constants as constants4, readFileSync as readFileSync14, realpathSync as realpathSync7, statSync as statSync4 } from "node:fs";
15308
15395
  import { delimiter as delimiter2, dirname as dirname7, join as join18, resolve as resolve8 } from "node:path";
15309
15396
  function identity() {
15310
15397
  const uid = typeof process.getuid === "function" ? process.getuid() : null;
@@ -15341,7 +15428,7 @@ function findExecutable(name) {
15341
15428
  if (!raw) continue;
15342
15429
  const candidate = join18(raw, name);
15343
15430
  try {
15344
- accessSync2(candidate, constants3.X_OK);
15431
+ accessSync2(candidate, constants4.X_OK);
15345
15432
  return realpathSync7(candidate);
15346
15433
  } catch {
15347
15434
  }
@@ -16405,7 +16492,7 @@ var init_verification_receipt = __esm({
16405
16492
  // src/cli/verify.ts
16406
16493
  import { execFileSync as execFileSync9, spawnSync as spawnSync3 } from "node:child_process";
16407
16494
  import { createHash as createHash14 } from "node:crypto";
16408
- import { chmodSync as chmodSync2, cpSync, lstatSync as lstatSync9, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync3, readFileSync as readFileSync16, readlinkSync as readlinkSync3, rmSync as rmSync9, symlinkSync, writeFileSync as writeFileSync11, existsSync as existsSync14 } from "node:fs";
16495
+ import { chmodSync as chmodSync2, cpSync, lstatSync as lstatSync10, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync3, readFileSync as readFileSync16, readlinkSync as readlinkSync3, rmSync as rmSync9, symlinkSync, writeFileSync as writeFileSync11, existsSync as existsSync13 } from "node:fs";
16409
16496
  import { tmpdir as tmpdir4 } from "node:os";
16410
16497
  import { dirname as dirname10, isAbsolute as isAbsolute11, join as join21, relative as relative6, resolve as resolve9, sep as sep4 } from "node:path";
16411
16498
  function oracleAssuranceReport() {
@@ -16499,7 +16586,7 @@ function validateSymlinkGraph(target, out3, root, dependencyRoot, label) {
16499
16586
  const current = join21(base, ...stack);
16500
16587
  let st;
16501
16588
  try {
16502
- st = lstatSync9(current);
16589
+ st = lstatSync10(current);
16503
16590
  } catch {
16504
16591
  continue;
16505
16592
  }
@@ -16541,7 +16628,7 @@ function rejectLinkedParent(cwd, rel) {
16541
16628
  current = join21(current, part);
16542
16629
  let st;
16543
16630
  try {
16544
- st = lstatSync9(current);
16631
+ st = lstatSync10(current);
16545
16632
  } catch {
16546
16633
  continue;
16547
16634
  }
@@ -16567,7 +16654,7 @@ function materialize(cwd, dest, dependencyRoot) {
16567
16654
  rejectLinkedParent(cwd, rel);
16568
16655
  let st;
16569
16656
  try {
16570
- st = lstatSync9(src);
16657
+ st = lstatSync10(src);
16571
16658
  } catch {
16572
16659
  continue;
16573
16660
  }
@@ -16601,7 +16688,7 @@ function probeFilesystemCaseSensitivity(dir) {
16601
16688
  const lower = join21(dir, ".tw-case-probe-a");
16602
16689
  try {
16603
16690
  writeFileSync11(upper, "", { flag: "wx" });
16604
- return !existsSync14(lower);
16691
+ return !existsSync13(lower);
16605
16692
  } finally {
16606
16693
  rmSync9(upper, { force: true });
16607
16694
  }
@@ -16621,7 +16708,7 @@ function caseFoldCollision(paths) {
16621
16708
  }
16622
16709
  function dropSymlink(p) {
16623
16710
  try {
16624
- if (lstatSync9(p).isSymbolicLink()) rmSync9(p, { force: true });
16711
+ if (lstatSync10(p).isSymbolicLink()) rmSync9(p, { force: true });
16625
16712
  } catch {
16626
16713
  }
16627
16714
  }
@@ -16663,7 +16750,7 @@ function overlayDigest(dest, paths) {
16663
16750
  h.update("\0");
16664
16751
  const p = join21(dest, rel);
16665
16752
  try {
16666
- const st = lstatSync9(p);
16753
+ const st = lstatSync10(p);
16667
16754
  h.update(String(st.mode));
16668
16755
  h.update(st.isSymbolicLink() ? readlinkSync3(p) : readFileSync16(p));
16669
16756
  } catch {
@@ -17015,7 +17102,7 @@ function runVerifyImpl(opts) {
17015
17102
  if (!filesystemCaseSensitive) {
17016
17103
  const present = (rel) => {
17017
17104
  try {
17018
- lstatSync9(join21(cwd, rel));
17105
+ lstatSync10(join21(cwd, rel));
17019
17106
  return true;
17020
17107
  } catch {
17021
17108
  return false;
@@ -18390,7 +18477,7 @@ raise SystemExit(0)
18390
18477
 
18391
18478
  // src/cli/doctor.ts
18392
18479
  import { execFileSync as execFileSync11 } from "node:child_process";
18393
- import { existsSync as existsSync15, readFileSync as readFileSync18, readdirSync as readdirSync5 } from "node:fs";
18480
+ import { existsSync as existsSync14, readFileSync as readFileSync18, readdirSync as readdirSync5 } from "node:fs";
18394
18481
  import { join as join23, resolve as resolve11 } from "node:path";
18395
18482
  function lifecyclePlatformCheck(platform = process.platform, linuxPython = platform === "linux" ? trustedLinuxPython() : null) {
18396
18483
  if (platform === "linux") {
@@ -18446,7 +18533,7 @@ function wiringState(status, authority) {
18446
18533
  return authority ? "BROKEN" : "WARN";
18447
18534
  }
18448
18535
  function pinsInFile(path) {
18449
- if (!existsSync15(path)) return [];
18536
+ if (!existsSync14(path)) return [];
18450
18537
  let src = "";
18451
18538
  try {
18452
18539
  src = readFileSync18(path, "utf8");
@@ -18470,7 +18557,7 @@ function workflowPermissionCheck(cwd, workflowRels = [".github/workflows/tamperw
18470
18557
  const warnings = [];
18471
18558
  for (const rel of workflowRels) {
18472
18559
  const path = resolve11(cwd, rel);
18473
- if (!existsSync15(path)) {
18560
+ if (!existsSync14(path)) {
18474
18561
  broken.push(`${rel} is missing`);
18475
18562
  continue;
18476
18563
  }
@@ -18875,7 +18962,7 @@ function diagnose(opts = {}) {
18875
18962
  } else {
18876
18963
  const workflowDirRel = ".github/workflows";
18877
18964
  const workflowDir = resolve11(cwd, workflowDirRel);
18878
- if (!existsSync15(workflowDir)) {
18965
+ if (!existsSync14(workflowDir)) {
18879
18966
  return fail("ci-verifier", `${workflowDirRel}: workflow directory does not exist`);
18880
18967
  }
18881
18968
  let entries;
@@ -18895,7 +18982,7 @@ function diagnose(opts = {}) {
18895
18982
  const authorityWorkflows = [];
18896
18983
  for (const workflowRel of workflowRels) {
18897
18984
  const workflowPath = resolve11(cwd, workflowRel);
18898
- if (!existsSync15(workflowPath)) {
18985
+ if (!existsSync14(workflowPath)) {
18899
18986
  return fail("ci-verifier", `${workflowRel}: workflow does not exist`);
18900
18987
  }
18901
18988
  let doc;
@@ -19211,7 +19298,7 @@ var init_status2 = __esm({
19211
19298
  // src/cli/trace-verify.ts
19212
19299
  import { execFileSync as execFileSync12, spawnSync as spawnSync5 } from "node:child_process";
19213
19300
  import {
19214
- existsSync as existsSync16,
19301
+ existsSync as existsSync15,
19215
19302
  mkdtempSync as mkdtempSync5,
19216
19303
  readFileSync as readFileSync19,
19217
19304
  readdirSync as readdirSync6,
@@ -19470,7 +19557,7 @@ function materializeBase(base, cwd, dest) {
19470
19557
  }
19471
19558
  const hostModules = join24(cwd, "node_modules");
19472
19559
  const tracedModules = join24(dest, "node_modules");
19473
- if (existsSync16(hostModules) && !existsSync16(tracedModules)) {
19560
+ if (existsSync15(hostModules) && !existsSync15(tracedModules)) {
19474
19561
  symlinkSync2(resolve12(hostModules), tracedModules, "dir");
19475
19562
  }
19476
19563
  }
@@ -19782,7 +19869,7 @@ var init_immutable = __esm({
19782
19869
  });
19783
19870
 
19784
19871
  // src/runtimes.ts
19785
- import { existsSync as existsSync17, readFileSync as readFileSync20 } from "node:fs";
19872
+ import { existsSync as existsSync16, readFileSync as readFileSync20 } from "node:fs";
19786
19873
  import { join as join25 } from "node:path";
19787
19874
  function isRecord6(x) {
19788
19875
  return typeof x === "object" && x !== null && !Array.isArray(x);
@@ -19812,7 +19899,7 @@ function claudeSettingsBeyondTamperward(cwd) {
19812
19899
  const path = join25(cwd, ".claude", "settings.json");
19813
19900
  let raw;
19814
19901
  try {
19815
- if (!existsSync17(path)) return false;
19902
+ if (!existsSync16(path)) return false;
19816
19903
  raw = readFileSync20(path, "utf8");
19817
19904
  } catch {
19818
19905
  return false;
@@ -19839,7 +19926,7 @@ function detectRuntimes(cwd) {
19839
19926
  for (const rt of KNOWN_RUNTIMES) {
19840
19927
  const marker = rt.markers.find((m) => {
19841
19928
  try {
19842
- return existsSync17(join25(cwd, m));
19929
+ return existsSync16(join25(cwd, m));
19843
19930
  } catch {
19844
19931
  return false;
19845
19932
  }
@@ -20864,7 +20951,7 @@ var init_adapter3 = __esm({
20864
20951
 
20865
20952
  // src/adapters/copilot-sdk/changes.ts
20866
20953
  import { execFileSync as execFileSync13 } from "node:child_process";
20867
- import { mkdtempSync as mkdtempSync6, writeFileSync as writeFileSync13, readFileSync as readFileSync21, rmSync as rmSync12, existsSync as existsSync18, realpathSync as realpathSync10 } from "node:fs";
20954
+ import { mkdtempSync as mkdtempSync6, writeFileSync as writeFileSync13, readFileSync as readFileSync21, rmSync as rmSync12, existsSync as existsSync17, realpathSync as realpathSync10 } from "node:fs";
20868
20955
  import { tmpdir as tmpdir7 } from "node:os";
20869
20956
  import { basename as basename5, dirname as dirname12, isAbsolute as isAbsolute16, relative as relative11, resolve as resolve15, join as join26 } from "node:path";
20870
20957
  function asStr4(v) {
@@ -20883,7 +20970,7 @@ function canonicalContainedTarget(abs, root) {
20883
20970
  }
20884
20971
  let dir = abs;
20885
20972
  const tail = [];
20886
- while (!existsSync18(dir)) {
20973
+ while (!existsSync17(dir)) {
20887
20974
  const parent = dirname12(dir);
20888
20975
  if (parent === dir) break;
20889
20976
  tail.unshift(basename5(dir));
@@ -21711,7 +21798,7 @@ var init_runtime_qualification = __esm({
21711
21798
 
21712
21799
  // src/cli/runtime.ts
21713
21800
  import { execFileSync as execFileSync14 } from "node:child_process";
21714
- import { existsSync as existsSync19, mkdirSync as mkdirSync11, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "node:fs";
21801
+ import { existsSync as existsSync18, mkdirSync as mkdirSync11, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "node:fs";
21715
21802
  import { join as join27, dirname as dirname13 } from "node:path";
21716
21803
  function storePath(cwd) {
21717
21804
  const dir = gitDir(cwd);
@@ -21719,7 +21806,7 @@ function storePath(cwd) {
21719
21806
  }
21720
21807
  function readStore(cwd) {
21721
21808
  const path = storePath(cwd);
21722
- if (!path || !existsSync19(path)) return null;
21809
+ if (!path || !existsSync18(path)) return null;
21723
21810
  try {
21724
21811
  const parsed = JSON.parse(readFileSync22(path, "utf8"));
21725
21812
  if (parsed && typeof parsed === "object" && parsed.records && typeof parsed.records === "object") return parsed;
@@ -21890,7 +21977,7 @@ function resolveHookConfigHash(canonicalId, cwd) {
21890
21977
  "github-copilot-cli": join27(cwd, ".github", "hooks", "tamperward.json")
21891
21978
  };
21892
21979
  const file = files[canonicalId];
21893
- if (!file || !existsSync19(file)) return null;
21980
+ if (!file || !existsSync18(file)) return null;
21894
21981
  try {
21895
21982
  const raw = readFileSync22(file, "utf8");
21896
21983
  let hooks = raw;
@@ -22171,7 +22258,7 @@ var init_runtime = __esm({
22171
22258
 
22172
22259
  // src/cli/onboard.ts
22173
22260
  import { execFileSync as execFileSync15 } from "node:child_process";
22174
- import { lstatSync as lstatSync10, mkdtempSync as mkdtempSync7, readFileSync as readFileSync23, realpathSync as realpathSync11, rmSync as rmSync13 } from "node:fs";
22261
+ import { lstatSync as lstatSync11, mkdtempSync as mkdtempSync7, readFileSync as readFileSync23, realpathSync as realpathSync11, rmSync as rmSync13 } from "node:fs";
22175
22262
  import { tmpdir as tmpdir8 } from "node:os";
22176
22263
  import { join as join28, relative as relative12, resolve as resolve16, sep as sep6 } from "node:path";
22177
22264
  import { createInterface } from "node:readline";
@@ -22679,7 +22766,7 @@ function runDemo(cwd, head, runners, out3) {
22679
22766
  return;
22680
22767
  }
22681
22768
  const targetPath = join28(wt, target.path);
22682
- const targetStat = lstatSync10(targetPath, { throwIfNoEntry: false });
22769
+ const targetStat = lstatSync11(targetPath, { throwIfNoEntry: false });
22683
22770
  if (!targetStat || !targetStat.isFile() || targetStat.isSymbolicLink()) {
22684
22771
  out3("Demo skipped: the selected test is not a regular file in the disposable worktree.");
22685
22772
  return;
@@ -23352,7 +23439,7 @@ var init_record = __esm({
23352
23439
  // src/research/run.ts
23353
23440
  import { randomUUID as randomUUID2 } from "node:crypto";
23354
23441
  import { execFileSync as execFileSync16 } from "node:child_process";
23355
- import { closeSync as closeSync4, existsSync as existsSync20, linkSync, mkdirSync as mkdirSync12, openSync as openSync4, readFileSync as readFileSync25, renameSync as renameSync4, rmSync as rmSync14, unlinkSync, writeFileSync as writeFileSync15, writeSync } from "node:fs";
23442
+ import { closeSync as closeSync5, existsSync as existsSync19, linkSync, mkdirSync as mkdirSync12, openSync as openSync5, readFileSync as readFileSync25, renameSync as renameSync4, rmSync as rmSync14, unlinkSync, writeFileSync as writeFileSync15, writeSync } from "node:fs";
23356
23443
  import { hostname } from "node:os";
23357
23444
  import { join as join29, resolve as resolve19 } from "node:path";
23358
23445
  function git7(args, cwd) {
@@ -23389,7 +23476,7 @@ function lockHolder(path) {
23389
23476
  function acquireResearchLock(ledger, breakStaleLock = false) {
23390
23477
  mkdirSync12(ledger, { recursive: true });
23391
23478
  const path = researchLockPath(ledger);
23392
- if (breakStaleLock && existsSync20(path)) {
23479
+ if (breakStaleLock && existsSync19(path)) {
23393
23480
  const owner2 = readLockOwner(path);
23394
23481
  if (!owner2) {
23395
23482
  throw new ResearchError(`research output ${ledger} has an unreadable lock at ${path}; verify no run is active, then remove it deliberately`);
@@ -23432,12 +23519,12 @@ function acquireResearchLock(ledger, breakStaleLock = false) {
23432
23519
  const text = JSON.stringify(owner) + "\n";
23433
23520
  let fd = -1;
23434
23521
  try {
23435
- fd = openSync4(path, "wx", 384);
23522
+ fd = openSync5(path, "wx", 384);
23436
23523
  writeSync(fd, text);
23437
- closeSync4(fd);
23524
+ closeSync5(fd);
23438
23525
  fd = -1;
23439
23526
  } catch (e) {
23440
- if (fd !== -1) closeSync4(fd);
23527
+ if (fd !== -1) closeSync5(fd);
23441
23528
  if (e.code === "EEXIST") {
23442
23529
  throw new ResearchError(
23443
23530
  `research output ${ledger} is already locked by ${lockHolder(path)}; refusing concurrent writers. Verify the owner is not running, then remove ${path} deliberately or rerun with --break-lock`
@@ -23762,7 +23849,7 @@ function runResearch(opts) {
23762
23849
  try {
23763
23850
  for (let pair = 1; pair <= pairs; pair++) {
23764
23851
  const path = pairRecordPath(ledger, task.id, pair);
23765
- if (!existsSync20(path)) continue;
23852
+ if (!existsSync19(path)) continue;
23766
23853
  const existing = resumableRecord(path, {
23767
23854
  task: task.id,
23768
23855
  pair,
@@ -23882,16 +23969,16 @@ var init_run2 = __esm({
23882
23969
  });
23883
23970
 
23884
23971
  // src/research/ledger-files.ts
23885
- import { closeSync as closeSync5, constants as constants4, fstatSync as fstatSync2, lstatSync as lstatSync11, openSync as openSync5, readFileSync as readFileSync26, readdirSync as readdirSync7, realpathSync as realpathSync12 } from "node:fs";
23972
+ import { closeSync as closeSync6, constants as constants5, fstatSync as fstatSync3, lstatSync as lstatSync12, openSync as openSync6, readFileSync as readFileSync26, readdirSync as readdirSync7, realpathSync as realpathSync12 } from "node:fs";
23886
23973
  import { join as join30, resolve as resolve20 } from "node:path";
23887
23974
  function lstatOrNull(path) {
23888
23975
  try {
23889
- return lstatSync11(path);
23976
+ return lstatSync12(path);
23890
23977
  } catch {
23891
23978
  return null;
23892
23979
  }
23893
23980
  }
23894
- function kindOf(st) {
23981
+ function kindOf2(st) {
23895
23982
  if (st.isSymbolicLink()) return "a symlink";
23896
23983
  if (st.isDirectory()) return "a directory";
23897
23984
  if (st.isFIFO()) return "a FIFO";
@@ -23903,7 +23990,7 @@ function readRegularFile(path, realPairsDir, name) {
23903
23990
  const listed = lstatOrNull(path);
23904
23991
  if (listed === null) throw new ResearchError(`ledger record ${path} vanished while the ledger was being read`);
23905
23992
  if (!listed.isFile()) {
23906
- throw new ResearchError(`ledger record ${path} is ${kindOf(listed)}; only a regular file placed directly in pairs/ is read`);
23993
+ throw new ResearchError(`ledger record ${path} is ${kindOf2(listed)}; only a regular file placed directly in pairs/ is read`);
23907
23994
  }
23908
23995
  if (listed.nlink !== 1) {
23909
23996
  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`);
@@ -23912,22 +23999,22 @@ function readRegularFile(path, realPairsDir, name) {
23912
23999
  if (real !== join30(realPairsDir, name)) {
23913
24000
  throw new ResearchError(`ledger record ${path} resolves outside the pairs directory (${real}); refusing to read it`);
23914
24001
  }
23915
- const flags = constants4.O_RDONLY | (constants4.O_NOFOLLOW ?? 0);
24002
+ const flags = constants5.O_RDONLY | (constants5.O_NOFOLLOW ?? 0);
23916
24003
  let fd;
23917
24004
  try {
23918
- fd = openSync5(path, flags);
24005
+ fd = openSync6(path, flags);
23919
24006
  } catch (e) {
23920
24007
  throw new ResearchError(`cannot open ledger record ${path}: ${errorMessage(e)}`);
23921
24008
  }
23922
24009
  try {
23923
- const opened = fstatSync2(fd);
24010
+ const opened = fstatSync3(fd);
23924
24011
  const sameInode = process.platform === "win32" || opened.dev === listed.dev && opened.ino === listed.ino;
23925
24012
  if (!opened.isFile() || !sameInode || opened.nlink !== 1) {
23926
24013
  throw new ResearchError(`ledger record ${path} changed between listing and reading; refusing to read it`);
23927
24014
  }
23928
24015
  return readFileSync26(fd);
23929
24016
  } finally {
23930
- closeSync5(fd);
24017
+ closeSync6(fd);
23931
24018
  }
23932
24019
  }
23933
24020
  function readPairFiles(ledger) {
@@ -24098,7 +24185,7 @@ var init_summarize = __esm({
24098
24185
 
24099
24186
  // src/research/init.ts
24100
24187
  import { createHash as createHash17 } from "node:crypto";
24101
- import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync27, writeFileSync as writeFileSync16 } from "node:fs";
24188
+ import { existsSync as existsSync20, mkdirSync as mkdirSync13, readFileSync as readFileSync27, writeFileSync as writeFileSync16 } from "node:fs";
24102
24189
  import { basename as basename6, dirname as dirname15, resolve as resolve21 } from "node:path";
24103
24190
  function idFrom(repo) {
24104
24191
  const clean = repo.replace(/[\\/]$/, "").split(/[\\/]/).pop() || "task";
@@ -24110,7 +24197,7 @@ function createResearchManifest(opts) {
24110
24197
  if (!opts.prompt) throw new ResearchError("research init requires --prompt");
24111
24198
  if (!opts.verifyCommand) throw new ResearchError("research init requires --verify-command");
24112
24199
  const out3 = resolve21(opts.out);
24113
- if (existsSync21(out3)) throw new ResearchError(`research init refuses to overwrite ${out3}; choose a new path`);
24200
+ if (existsSync20(out3)) throw new ResearchError(`research init refuses to overwrite ${out3}; choose a new path`);
24114
24201
  const id = opts.id ?? idFrom(opts.repo);
24115
24202
  if (!/^[A-Za-z0-9._-]+$/.test(id)) throw new ResearchError(`research init id must match [A-Za-z0-9._-] (got "${id}")`);
24116
24203
  if (opts.verifyBudget !== void 0 && (!Number.isFinite(opts.verifyBudget) || opts.verifyBudget <= 0)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tamperward",
3
- "version": "2.39.4",
3
+ "version": "2.39.6",
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",