tamperward 2.39.10 → 2.39.12

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 +227 -132
  2. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -671,7 +671,7 @@ var init_policy = __esm({
671
671
  });
672
672
 
673
673
  // src/disk.ts
674
- import { closeSync, constants, fstatSync, lstatSync as lstatSync2, openSync, readSync, readlinkSync, realpathSync as realpathSync2 } from "node:fs";
674
+ import { closeSync, constants, fstatSync, lstatSync as lstatSync2, openSync, readSync, readlinkSync, realpathSync as realpathSync2, writeSync } from "node:fs";
675
675
  import { join as join3 } from "node:path";
676
676
  function errText(e) {
677
677
  return e instanceof Error ? e.message : String(e);
@@ -788,9 +788,53 @@ function readStateFile(abs) {
788
788
  if (e.kind === "absent") return null;
789
789
  if (e.kind === "file") return textOf2(e) ?? "";
790
790
  throw new StateFileError(
791
- `${abs} ${notARegularFile(e)}; the gate reads its session state only as a regular file \u2014 remove what stands there so the state can be re-established`
791
+ `${abs} ${notARegularFile(e)}; the gate reads its state files only as regular files \u2014 remove what stands there so the state can be re-established`
792
792
  );
793
793
  }
794
+ function stateDirectory(gitDir3) {
795
+ const dir = join3(gitDir3, "tamperward");
796
+ const st = lstatSync2(dir, { throwIfNoEntry: false });
797
+ if (st === void 0 || st.isDirectory()) return dir;
798
+ if (st.isSymbolicLink()) {
799
+ let target = "";
800
+ try {
801
+ target = readlinkSync(dir);
802
+ } catch {
803
+ }
804
+ throw new StateFileError(`${dir} is a symbolic link to ${escapeControl(target)}${STATE_DIR_REFUSED}`);
805
+ }
806
+ throw new StateFileError(`${dir} is a ${st.isFile() ? "regular file" : irregularName(st)}${STATE_DIR_REFUSED}`);
807
+ }
808
+ function multiplyLinked(st) {
809
+ return st.nlink === 1 ? null : `has ${st.nlink} names \u2014 a hard link is the same file under another name, the session marker's or the policy's, say`;
810
+ }
811
+ function appendRegular(abs, text, mode = 438) {
812
+ const st = lstatSync2(abs, { throwIfNoEntry: false });
813
+ if (st !== void 0 && !st.isFile()) throw new StateFileError(`${abs} ${notARegularFile(classify(abs, st))}${APPEND_REFUSED}`);
814
+ const linked = st === void 0 ? null : multiplyLinked(st);
815
+ if (linked !== null) throw new StateFileError(`${abs} ${linked}${APPEND_REFUSED}`);
816
+ let fd;
817
+ try {
818
+ fd = openSync(abs, O_APPEND_REGULAR, mode);
819
+ } catch (e) {
820
+ const code2 = errCode(e);
821
+ if (code2 === "ELOOP" || code2 === "ENXIO" || code2 === "EISDIR") {
822
+ throw new StateFileError(`${abs} changed shape while it was being opened (${errText(e)})${APPEND_REFUSED}`);
823
+ }
824
+ throw e;
825
+ }
826
+ try {
827
+ const now = fstatSync(fd);
828
+ if (!now.isFile()) throw new StateFileError(`${abs} is a ${irregularName(now)}${APPEND_REFUSED}`);
829
+ const opened = multiplyLinked(now);
830
+ if (opened !== null) throw new StateFileError(`${abs} ${opened}${APPEND_REFUSED}`);
831
+ const buf = Buffer.from(text, "utf8");
832
+ let off2 = 0;
833
+ while (off2 < buf.length) off2 += writeSync(fd, buf, off2, buf.length - off2);
834
+ } finally {
835
+ closeSync(fd);
836
+ }
837
+ }
794
838
  function describe(e, shown) {
795
839
  switch (e.kind) {
796
840
  case "symlink":
@@ -831,7 +875,7 @@ function unjudgeableProtected(cwd, policy, changes) {
831
875
  }
832
876
  return out3;
833
877
  }
834
- var READ_CAP, NO_META, O_READ, StateFileError;
878
+ var READ_CAP, NO_META, O_READ, StateFileError, STATE_DIR_REFUSED, O_APPEND_REGULAR, APPEND_REFUSED;
835
879
  var init_disk = __esm({
836
880
  "src/disk.ts"() {
837
881
  "use strict";
@@ -842,6 +886,9 @@ var init_disk = __esm({
842
886
  O_READ = constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0);
843
887
  StateFileError = class extends Error {
844
888
  };
889
+ STATE_DIR_REFUSED = "; the gate keeps its state only in a directory of its own under the git directory \u2014 replace what stands there with a directory, or remove it";
890
+ O_APPEND_REGULAR = constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0);
891
+ APPEND_REFUSED = "; the gate appends its records only to a regular file with one name \u2014 remove what stands there so the record can be kept";
845
892
  }
846
893
  });
847
894
 
@@ -11582,7 +11629,13 @@ function writeBaseline(p, sha3) {
11582
11629
  function baselinePath(cwd, sessionId) {
11583
11630
  const gd = gitDir(cwd);
11584
11631
  if (!gd) return null;
11585
- return join10(gd, "tamperward", `session-${sessionId.replace(UNSAFE, "")}`);
11632
+ const name = `session-${sessionId.replace(UNSAFE, "")}`;
11633
+ try {
11634
+ return join10(stateDirectory(gd), name);
11635
+ } catch (e) {
11636
+ if (e instanceof StateFileError) throw new BaselineWriteError(join10(gd, "tamperward", name), e);
11637
+ throw e;
11638
+ }
11586
11639
  }
11587
11640
  function turnBaseline(cwd, sessionId) {
11588
11641
  if (!sessionId) return null;
@@ -11649,7 +11702,7 @@ function statePath(cwd, sessionId, kind) {
11649
11702
  if (!sessionId) return null;
11650
11703
  const gd = gitDir2(cwd);
11651
11704
  if (!gd) return null;
11652
- const dir = join11(gd, "tamperward");
11705
+ const dir = stateDirectory(gd);
11653
11706
  return join11(dir, `${kind}-${sessionId.replace(UNSAFE2, "")}.json`);
11654
11707
  }
11655
11708
  function ptreePath(cwd, sessionId) {
@@ -11777,8 +11830,53 @@ var init_effect = __esm({
11777
11830
  }
11778
11831
  });
11779
11832
 
11833
+ // src/safe-write.ts
11834
+ import { randomBytes } from "node:crypto";
11835
+ import { lstatSync as lstatSync5, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync4 } from "node:fs";
11836
+ function writeTargetKind(path) {
11837
+ let st;
11838
+ try {
11839
+ st = lstatSync5(path, { throwIfNoEntry: false });
11840
+ } catch (e) {
11841
+ if (errnoCode(e) === "ENOTDIR") return "absent";
11842
+ throw e;
11843
+ }
11844
+ if (!st) return "absent";
11845
+ if (st.isSymbolicLink()) return "symlink";
11846
+ return st.isFile() ? "file" : "irregular";
11847
+ }
11848
+ function refuseNonRegular(path) {
11849
+ switch (writeTargetKind(path)) {
11850
+ case "symlink":
11851
+ return "refusing: symlink \u2014 the target would be written instead of this path; replace the link with a regular file, then re-run";
11852
+ case "irregular":
11853
+ return "refusing: not a regular file \u2014 a directory or special file stands where a file is expected; remove it, then re-run";
11854
+ default:
11855
+ return null;
11856
+ }
11857
+ }
11858
+ function existingMode(path, fallback) {
11859
+ if (writeTargetKind(path) !== "file") return fallback;
11860
+ return lstatSync5(path).mode & 511;
11861
+ }
11862
+ function atomicReplaceFile(path, content, mode) {
11863
+ const tmp = `${path}.${process.pid}.${randomBytes(8).toString("hex")}.tmp`;
11864
+ try {
11865
+ writeFileSync4(tmp, content, { encoding: "utf8", flag: "wx", mode });
11866
+ renameSync3(tmp, path);
11867
+ } finally {
11868
+ rmSync4(tmp, { force: true });
11869
+ }
11870
+ }
11871
+ var init_safe_write = __esm({
11872
+ "src/safe-write.ts"() {
11873
+ "use strict";
11874
+ init_narrow();
11875
+ }
11876
+ });
11877
+
11780
11878
  // src/cli/watch.ts
11781
- import { appendFileSync as appendFileSync3, lstatSync as lstatSync5, mkdirSync as mkdirSync4, readdirSync as readdirSync2, watch, writeFileSync as writeFileSync4 } from "node:fs";
11879
+ import { lstatSync as lstatSync6, mkdirSync as mkdirSync4, readdirSync as readdirSync2, watch } from "node:fs";
11782
11880
  import { join as join12 } from "node:path";
11783
11881
  import { createHash as createHash5 } from "node:crypto";
11784
11882
  function snap(abs) {
@@ -11790,7 +11888,7 @@ function snap(abs) {
11790
11888
  }
11791
11889
  function defaultEventLog(cwd) {
11792
11890
  if (process.env.TAMPERWARD_FSEVENTS) return process.env.TAMPERWARD_FSEVENTS;
11793
- return join12(gitDir(cwd) ?? join12(cwd, ".git"), "tamperward", "fsevents.jsonl");
11891
+ return join12(stateDirectory(gitDir(cwd) ?? join12(cwd, ".git")), "fsevents.jsonl");
11794
11892
  }
11795
11893
  function watcherHealthPath(log) {
11796
11894
  return `${log}.health.json`;
@@ -11889,7 +11987,7 @@ function watchTree(dir, cb, onState, onError, watchFn = watch) {
11889
11987
  const child = rel ? `${rel}/${String(fname)}` : String(fname);
11890
11988
  cb(kind, child);
11891
11989
  try {
11892
- if (lstatSync5(join12(dir, child)).isDirectory()) addDir(child);
11990
+ if (lstatSync6(join12(dir, child)).isDirectory()) addDir(child);
11893
11991
  } catch {
11894
11992
  }
11895
11993
  });
@@ -11925,7 +12023,7 @@ function watchTree(dir, cb, onState, onError, watchFn = watch) {
11925
12023
  const child = rel ? `${rel}/${name}` : name;
11926
12024
  if (SKIP2.test(child + "/")) continue;
11927
12025
  try {
11928
- if (lstatSync5(join12(dir, child)).isDirectory()) walk2(child);
12026
+ if (lstatSync6(join12(dir, child)).isDirectory()) walk2(child);
11929
12027
  } catch {
11930
12028
  }
11931
12029
  }
@@ -11964,7 +12062,7 @@ function startWatcher(dir, log, policy, watchFn = watch) {
11964
12062
  let healthWriteWarningEmitted = false;
11965
12063
  const persistHealth = () => {
11966
12064
  try {
11967
- writeFileSync4(healthPath, JSON.stringify(health) + "\n", { mode: 384 });
12065
+ atomicReplaceFile(healthPath, JSON.stringify(health) + "\n", 384);
11968
12066
  healthWriteWarningEmitted = false;
11969
12067
  } catch (e) {
11970
12068
  if (!healthWriteWarningEmitted) {
@@ -12004,7 +12102,7 @@ function startWatcher(dir, log, policy, watchFn = watch) {
12004
12102
  ...s
12005
12103
  };
12006
12104
  try {
12007
- appendFileSync3(log, JSON.stringify(ev) + "\n");
12105
+ appendRegular(log, JSON.stringify(ev) + "\n");
12008
12106
  health.event_count++;
12009
12107
  health.last_append_at = (/* @__PURE__ */ new Date()).toISOString();
12010
12108
  persistHealth();
@@ -12067,6 +12165,7 @@ var init_watch = __esm({
12067
12165
  "src/cli/watch.ts"() {
12068
12166
  "use strict";
12069
12167
  init_disk();
12168
+ init_safe_write();
12070
12169
  init_policy_load();
12071
12170
  init_policy();
12072
12171
  init_build();
@@ -12332,34 +12431,34 @@ var init_fs_events = __esm({
12332
12431
  });
12333
12432
 
12334
12433
  // src/cli/audit.ts
12335
- import { createHash as createHash6, randomBytes } from "node:crypto";
12336
- import { appendFileSync as appendFileSync4, closeSync as closeSync4, existsSync as existsSync5, mkdirSync as mkdirSync5, openSync as openSync4, readSync as readSync3 } from "node:fs";
12434
+ import { createHash as createHash6, randomBytes as randomBytes2 } from "node:crypto";
12435
+ import { closeSync as closeSync4, existsSync as existsSync5, mkdirSync as mkdirSync5, openSync as openSync4, readSync as readSync3 } from "node:fs";
12337
12436
  import { dirname as dirname4, isAbsolute as isAbsolute8, join as join13, resolve as resolve4 } from "node:path";
12338
12437
  function sessionHash(sessionId) {
12339
12438
  if (!sessionId) return void 0;
12340
12439
  return "sha256:" + createHash6("sha256").update(sessionId).digest("hex").slice(0, 24);
12341
12440
  }
12342
12441
  function eventId() {
12343
- return "sha256:" + createHash6("sha256").update(randomBytes(32)).digest("hex").slice(0, 32);
12442
+ return "sha256:" + createHash6("sha256").update(randomBytes2(32)).digest("hex").slice(0, 32);
12344
12443
  }
12345
12444
  function configuredAuditPath(cwd, env = process.env) {
12346
12445
  const value = env[AUDIT_LOG_ENV];
12347
12446
  if (!value) return null;
12348
12447
  if (value === "auto") {
12349
12448
  const ctx = repoContext(cwd);
12350
- return ctx ? join13(ctx.gitDir, "tamperward", "audit.jsonl") : null;
12449
+ return ctx ? join13(stateDirectory(ctx.gitDir), "audit.jsonl") : null;
12351
12450
  }
12352
12451
  return isAbsolute8(value) ? value : resolve4(cwd, value);
12353
12452
  }
12354
12453
  function defaultAuditPath(cwd) {
12355
12454
  const ctx = repoContext(cwd);
12356
- return ctx ? join13(ctx.gitDir, "tamperward", "audit.jsonl") : null;
12455
+ return ctx ? join13(stateDirectory(ctx.gitDir), "audit.jsonl") : null;
12357
12456
  }
12358
12457
  function recordAuditFindings(findings, context) {
12359
12458
  if (findings.length === 0) return;
12360
- const path = configuredAuditPath(context.cwd);
12361
- if (!path) return;
12362
12459
  try {
12460
+ const path = configuredAuditPath(context.cwd);
12461
+ if (!path) return;
12363
12462
  mkdirSync5(dirname4(path), { recursive: true });
12364
12463
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
12365
12464
  const session = sessionHash(context.sessionId);
@@ -12378,7 +12477,7 @@ function recordAuditFindings(findings, context) {
12378
12477
  };
12379
12478
  return JSON.stringify(event);
12380
12479
  });
12381
- appendFileSync4(path, lines.join("\n") + "\n");
12480
+ appendRegular(path, lines.join("\n") + "\n");
12382
12481
  } catch {
12383
12482
  }
12384
12483
  }
@@ -12613,6 +12712,7 @@ var init_audit = __esm({
12613
12712
  "src/cli/audit.ts"() {
12614
12713
  "use strict";
12615
12714
  init_repo_context();
12715
+ init_disk();
12616
12716
  AUDIT_SCHEMA_VERSION = 1;
12617
12717
  AUDIT_LOG_ENV = "TAMPERWARD_AUDIT_LOG";
12618
12718
  MAX_AUDIT_LINE_BYTES = 16 * 1024;
@@ -12631,7 +12731,7 @@ var init_audit = __esm({
12631
12731
  });
12632
12732
 
12633
12733
  // src/cli/hook.ts
12634
- import { readFileSync as readFileSync6, appendFileSync as appendFileSync5, writeFileSync as writeFileSync5, existsSync as existsSync6 } from "node:fs";
12734
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync6 } from "node:fs";
12635
12735
  import { createHash as createHash7 } from "node:crypto";
12636
12736
  function setSnapshotCache(cache3) {
12637
12737
  snapshotCache = cache3;
@@ -12666,7 +12766,7 @@ function recordDenylog(blocks2) {
12666
12766
  const log = process.env.TAMPERWARD_DENYLOG;
12667
12767
  if (!log) return;
12668
12768
  try {
12669
- appendFileSync5(log, blocks2.map((b) => b.rule).join(",") + "\n");
12769
+ appendRegular(log, blocks2.map((b) => b.rule).join(",") + "\n");
12670
12770
  } catch {
12671
12771
  }
12672
12772
  }
@@ -12985,7 +13085,7 @@ function recordWarns(cwd, sessionId, warns) {
12985
13085
  const log = process.env.TAMPERWARD_DENYLOG;
12986
13086
  if (!log) return;
12987
13087
  try {
12988
- appendFileSync5(log, warns.map((w) => `warn:${w.rule}:${w.file ?? ""}`).join("\n") + "\n");
13088
+ appendRegular(log, warns.map((w) => `warn:${w.rule}:${w.file ?? ""}`).join("\n") + "\n");
12989
13089
  } catch {
12990
13090
  }
12991
13091
  }
@@ -12995,7 +13095,7 @@ function recordObserverHealth(cwd, sessionId, state, reason) {
12995
13095
  if (!log) return;
12996
13096
  const detail = (reason ?? "").replace(/[\r\n]+/g, " ").trim();
12997
13097
  try {
12998
- appendFileSync5(
13098
+ appendRegular(
12999
13099
  log,
13000
13100
  `warn:transient-observer:${state}${detail ? ":" + detail : ""}
13001
13101
  `
@@ -13112,7 +13212,7 @@ var init_hook = __esm({
13112
13212
  });
13113
13213
 
13114
13214
  // src/ptree-cache.ts
13115
- import { lstatSync as lstatSync6 } from "node:fs";
13215
+ import { lstatSync as lstatSync7 } from "node:fs";
13116
13216
  import { join as join14 } from "node:path";
13117
13217
  function keyOf(st) {
13118
13218
  return `${st.dev}:${st.ino}:${st.size}:${st.mode}:${st.mtimeNs}:${st.ctimeNs}`;
@@ -13166,7 +13266,7 @@ var init_ptree_cache = __esm({
13166
13266
  const abs = join14(cwd, rel);
13167
13267
  let st;
13168
13268
  try {
13169
- st = lstatSync6(abs, { bigint: true });
13269
+ st = lstatSync7(abs, { bigint: true });
13170
13270
  } catch {
13171
13271
  this.map.delete(abs);
13172
13272
  this.stats.misses++;
@@ -13188,7 +13288,7 @@ var init_ptree_cache = __esm({
13188
13288
  const entry = compute();
13189
13289
  let after;
13190
13290
  try {
13191
- after = lstatSync6(abs, { bigint: true });
13291
+ after = lstatSync7(abs, { bigint: true });
13192
13292
  } catch {
13193
13293
  this.map.delete(abs);
13194
13294
  return entry;
@@ -13206,7 +13306,7 @@ var init_ptree_cache = __esm({
13206
13306
  });
13207
13307
 
13208
13308
  // src/cli/hook-service.ts
13209
- import { chmodSync, existsSync as existsSync7, lstatSync as lstatSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync7, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "node:fs";
13309
+ import { chmodSync, existsSync as existsSync7, lstatSync as lstatSync8, mkdirSync as mkdirSync6, readFileSync as readFileSync7, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "node:fs";
13210
13310
  import { createConnection as createConnection2, createServer } from "node:net";
13211
13311
  import { realpathSync as realpathSync4 } from "node:fs";
13212
13312
  import { sep } from "node:path";
@@ -13289,13 +13389,13 @@ function withEnv(env, fn) {
13289
13389
  }
13290
13390
  function removeQuietly(p) {
13291
13391
  try {
13292
- rmSync4(p, { force: true });
13392
+ rmSync5(p, { force: true });
13293
13393
  } catch {
13294
13394
  }
13295
13395
  }
13296
13396
  function ensurePrivateDir(dir, uid) {
13297
13397
  if (!existsSync7(dir)) mkdirSync6(dir, { recursive: true, mode: 448 });
13298
- const st = lstatSync7(dir);
13398
+ const st = lstatSync8(dir);
13299
13399
  if (!st.isDirectory()) throw new Error(`${dir} is not a directory`);
13300
13400
  if (st.uid !== uid) throw new Error(`${dir} is owned by uid ${st.uid}, not ${uid}; refusing to serve from it`);
13301
13401
  if ((st.mode & 63) !== 0) chmodSync(dir, 448);
@@ -13725,51 +13825,6 @@ var init_verifier_limits = __esm({
13725
13825
  }
13726
13826
  });
13727
13827
 
13728
- // src/safe-write.ts
13729
- import { randomBytes as randomBytes2 } from "node:crypto";
13730
- import { lstatSync as lstatSync8, renameSync as renameSync3, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "node:fs";
13731
- function writeTargetKind(path) {
13732
- let st;
13733
- try {
13734
- st = lstatSync8(path, { throwIfNoEntry: false });
13735
- } catch (e) {
13736
- if (errnoCode(e) === "ENOTDIR") return "absent";
13737
- throw e;
13738
- }
13739
- if (!st) return "absent";
13740
- if (st.isSymbolicLink()) return "symlink";
13741
- return st.isFile() ? "file" : "irregular";
13742
- }
13743
- function refuseNonRegular(path) {
13744
- switch (writeTargetKind(path)) {
13745
- case "symlink":
13746
- return "refusing: symlink \u2014 the target would be written instead of this path; replace the link with a regular file, then re-run";
13747
- case "irregular":
13748
- return "refusing: not a regular file \u2014 a directory or special file stands where a file is expected; remove it, then re-run";
13749
- default:
13750
- return null;
13751
- }
13752
- }
13753
- function existingMode(path, fallback) {
13754
- if (writeTargetKind(path) !== "file") return fallback;
13755
- return lstatSync8(path).mode & 511;
13756
- }
13757
- function atomicReplaceFile(path, content, mode) {
13758
- const tmp = `${path}.${process.pid}.${randomBytes2(8).toString("hex")}.tmp`;
13759
- try {
13760
- writeFileSync7(tmp, content, { encoding: "utf8", flag: "wx", mode });
13761
- renameSync3(tmp, path);
13762
- } finally {
13763
- rmSync5(tmp, { force: true });
13764
- }
13765
- }
13766
- var init_safe_write = __esm({
13767
- "src/safe-write.ts"() {
13768
- "use strict";
13769
- init_narrow();
13770
- }
13771
- });
13772
-
13773
13828
  // src/cli/init.ts
13774
13829
  import { execFileSync as execFileSync6 } from "node:child_process";
13775
13830
  import { createHash as createHash8 } from "node:crypto";
@@ -15063,7 +15118,7 @@ var init_dependency_env = __esm({
15063
15118
 
15064
15119
  // src/suite-diagnostics.ts
15065
15120
  import { spawnSync } from "node:child_process";
15066
- import { mkdtempSync as mkdtempSync2, rmSync as rmSync6, writeFileSync as writeFileSync8 } from "node:fs";
15121
+ import { mkdtempSync as mkdtempSync2, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "node:fs";
15067
15122
  import { tmpdir as tmpdir3 } from "node:os";
15068
15123
  import { join as join17 } from "node:path";
15069
15124
  function emptySuiteDiagnostics() {
@@ -15149,7 +15204,7 @@ function runCapturedProcessSync(executable, args, opts) {
15149
15204
  const configFile = join17(stateDir2, "config.json");
15150
15205
  const backstop = opts.backstopMs ?? 3e4;
15151
15206
  try {
15152
- writeFileSync8(
15207
+ writeFileSync7(
15153
15208
  configFile,
15154
15209
  JSON.stringify({
15155
15210
  executable,
@@ -15916,7 +15971,7 @@ var init_verifier_backend = __esm({
15916
15971
  // src/verification-state.ts
15917
15972
  import { execFileSync as execFileSync8 } from "node:child_process";
15918
15973
  import { createHash as createHash12 } from "node:crypto";
15919
- import { mkdirSync as mkdirSync8, readFileSync as readFileSync11, rmSync as rmSync7, writeFileSync as writeFileSync9 } from "node:fs";
15974
+ import { mkdirSync as mkdirSync8, readFileSync as readFileSync11, rmSync as rmSync7 } from "node:fs";
15920
15975
  import { dirname as dirname8, join as join19 } from "node:path";
15921
15976
  function git2(args, cwd) {
15922
15977
  return execFileSync8("git", args, {
@@ -16033,7 +16088,7 @@ function computeBinding(cwd, inputs, precomputed) {
16033
16088
  }
16034
16089
  function stateDir(cwd) {
16035
16090
  const ctx = repoContext(cwd);
16036
- return ctx ? join19(ctx.gitDir, "tamperward") : null;
16091
+ return ctx ? stateDirectory(ctx.gitDir) : null;
16037
16092
  }
16038
16093
  function verificationRecordPath(cwd) {
16039
16094
  const dir = stateDir(cwd);
@@ -16060,11 +16115,17 @@ function recordVerification(cwd, inputs, treeFingerprintValue) {
16060
16115
  binding
16061
16116
  };
16062
16117
  mkdirSync8(dirname8(path), { recursive: true });
16063
- writeFileSync9(path, JSON.stringify(record) + "\n");
16118
+ atomicReplaceFile(path, JSON.stringify(record) + "\n", 438);
16064
16119
  return true;
16065
16120
  }
16066
16121
  function invalidateVerificationRecordIfCurrent(cwd) {
16067
- const record = readVerificationRecord(cwd);
16122
+ let record;
16123
+ try {
16124
+ record = readVerificationRecord(cwd);
16125
+ } catch (e) {
16126
+ if (e instanceof StateFileError) return false;
16127
+ throw e;
16128
+ }
16068
16129
  if (!record) return false;
16069
16130
  let live;
16070
16131
  try {
@@ -16126,12 +16187,8 @@ function parseVerificationRecord(value) {
16126
16187
  function readVerificationRecord(cwd) {
16127
16188
  const path = verificationRecordPath(cwd);
16128
16189
  if (!path) return null;
16129
- let raw;
16130
- try {
16131
- raw = readFileSync11(path, "utf8");
16132
- } catch {
16133
- return null;
16134
- }
16190
+ const raw = readStateFile(path);
16191
+ if (raw === null) return null;
16135
16192
  let parsed;
16136
16193
  try {
16137
16194
  parsed = JSON.parse(raw);
@@ -16149,25 +16206,25 @@ function pidAlive3(pid) {
16149
16206
  }
16150
16207
  }
16151
16208
  function beginVerifying(cwd) {
16152
- const path = verifyingMarkerPath(cwd);
16153
- if (!path) return false;
16154
16209
  try {
16210
+ const path = verifyingMarkerPath(cwd);
16211
+ if (!path) return false;
16155
16212
  const marker = {
16156
16213
  schema_version: VERIFICATION_STATE_SCHEMA_VERSION,
16157
16214
  pid: process.pid,
16158
16215
  started_at: (/* @__PURE__ */ new Date()).toISOString()
16159
16216
  };
16160
16217
  mkdirSync8(dirname8(path), { recursive: true });
16161
- writeFileSync9(path, JSON.stringify(marker) + "\n");
16218
+ atomicReplaceFile(path, JSON.stringify(marker) + "\n", 438);
16162
16219
  return true;
16163
16220
  } catch {
16164
16221
  return false;
16165
16222
  }
16166
16223
  }
16167
16224
  function endVerifying(cwd) {
16168
- const path = verifyingMarkerPath(cwd);
16169
- if (!path) return;
16170
16225
  try {
16226
+ const path = verifyingMarkerPath(cwd);
16227
+ if (!path) return;
16171
16228
  rmSync7(path, { force: true });
16172
16229
  } catch {
16173
16230
  }
@@ -16175,9 +16232,11 @@ function endVerifying(cwd) {
16175
16232
  function readVerifyingMarker(cwd) {
16176
16233
  const path = verifyingMarkerPath(cwd);
16177
16234
  if (!path) return null;
16235
+ const raw = readStateFile(path);
16236
+ if (raw === null) return null;
16178
16237
  let parsed;
16179
16238
  try {
16180
- parsed = JSON.parse(readFileSync11(path, "utf8"));
16239
+ parsed = JSON.parse(raw);
16181
16240
  } catch {
16182
16241
  return null;
16183
16242
  }
@@ -16204,10 +16263,22 @@ function environmentInputDivergences(recorded, live) {
16204
16263
  return ENVIRONMENT_INPUTS.filter((input) => recorded[input] !== live[input]);
16205
16264
  }
16206
16265
  function evaluateVerificationState(cwd) {
16207
- if (readVerifyingMarker(cwd)) {
16266
+ let marker;
16267
+ let record;
16268
+ try {
16269
+ marker = readVerifyingMarker(cwd);
16270
+ record = marker ? null : readVerificationRecord(cwd);
16271
+ } catch (e) {
16272
+ if (!(e instanceof StateFileError)) throw e;
16273
+ return {
16274
+ state: "UNVERIFIED",
16275
+ reason: "the verification store cannot be read: something other than a regular file stands at a record path",
16276
+ detail: e.message
16277
+ };
16278
+ }
16279
+ if (marker) {
16208
16280
  return { state: "VERIFYING", reason: "a verification is in progress" };
16209
16281
  }
16210
- const record = readVerificationRecord(cwd);
16211
16282
  if (!record) {
16212
16283
  return {
16213
16284
  state: "UNVERIFIED",
@@ -16262,6 +16333,8 @@ var init_verification_state = __esm({
16262
16333
  init_repo_context();
16263
16334
  init_wiring();
16264
16335
  init_dependency_env();
16336
+ init_disk();
16337
+ init_safe_write();
16265
16338
  VERIFICATION_STATE_SCHEMA_VERSION = 1;
16266
16339
  BINDING_INPUTS = [
16267
16340
  "tree",
@@ -16311,7 +16384,7 @@ var init_verification_state = __esm({
16311
16384
 
16312
16385
  // src/verification-receipt.ts
16313
16386
  import { createHash as createHash13 } from "node:crypto";
16314
- import { mkdirSync as mkdirSync9, rmSync as rmSync8, writeFileSync as writeFileSync10 } from "node:fs";
16387
+ import { mkdirSync as mkdirSync9, rmSync as rmSync8 } from "node:fs";
16315
16388
  import { dirname as dirname9, join as join20 } from "node:path";
16316
16389
  function isRecord5(v) {
16317
16390
  return typeof v === "object" && v !== null && !Array.isArray(v);
@@ -16351,23 +16424,23 @@ function receiptFromRecord(record) {
16351
16424
  }
16352
16425
  function receiptPath(cwd) {
16353
16426
  const ctx = repoContext(cwd);
16354
- return ctx ? join20(ctx.gitDir, "tamperward", "verification-receipt.json") : null;
16427
+ return ctx ? join20(stateDirectory(ctx.gitDir), "verification-receipt.json") : null;
16355
16428
  }
16356
16429
  function storeReceipt(cwd, receipt) {
16357
- const path = receiptPath(cwd);
16358
- if (!path) return false;
16359
16430
  try {
16431
+ const path = receiptPath(cwd);
16432
+ if (!path) return false;
16360
16433
  mkdirSync9(dirname9(path), { recursive: true });
16361
- writeFileSync10(path, JSON.stringify(receipt) + "\n");
16434
+ atomicReplaceFile(path, JSON.stringify(receipt) + "\n", 438);
16362
16435
  return true;
16363
16436
  } catch {
16364
16437
  return false;
16365
16438
  }
16366
16439
  }
16367
16440
  function removeStoredReceipt(cwd) {
16368
- const path = receiptPath(cwd);
16369
- if (!path) return;
16370
16441
  try {
16442
+ const path = receiptPath(cwd);
16443
+ if (!path) return;
16371
16444
  rmSync8(path, { force: true });
16372
16445
  } catch {
16373
16446
  }
@@ -16529,6 +16602,8 @@ var RECEIPT_SCHEMA_VERSION, RECEIPT_STAGE_RESULTS, RECEIPT_INTEGRITY_RESULTS;
16529
16602
  var init_verification_receipt = __esm({
16530
16603
  "src/verification-receipt.ts"() {
16531
16604
  "use strict";
16605
+ init_disk();
16606
+ init_safe_write();
16532
16607
  init_repo_context();
16533
16608
  init_verification_state();
16534
16609
  init_machine_output();
@@ -16541,7 +16616,7 @@ var init_verification_receipt = __esm({
16541
16616
  // src/cli/verify.ts
16542
16617
  import { execFileSync as execFileSync9, spawnSync as spawnSync3 } from "node:child_process";
16543
16618
  import { createHash as createHash14 } from "node:crypto";
16544
- import { chmodSync as chmodSync2, cpSync, lstatSync as lstatSync10, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync3, readFileSync as readFileSync12, readlinkSync as readlinkSync3, rmSync as rmSync9, symlinkSync, writeFileSync as writeFileSync11, existsSync as existsSync10 } from "node:fs";
16619
+ import { chmodSync as chmodSync2, cpSync, lstatSync as lstatSync10, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync3, readFileSync as readFileSync12, readlinkSync as readlinkSync3, rmSync as rmSync9, symlinkSync, writeFileSync as writeFileSync8, existsSync as existsSync10 } from "node:fs";
16545
16620
  import { tmpdir as tmpdir4 } from "node:os";
16546
16621
  import { dirname as dirname10, isAbsolute as isAbsolute11, join as join21, relative as relative6, resolve as resolve9, sep as sep4 } from "node:path";
16547
16622
  function oracleAssuranceReport() {
@@ -16736,7 +16811,7 @@ function probeFilesystemCaseSensitivity(dir) {
16736
16811
  const upper = join21(dir, ".tw-case-probe-A");
16737
16812
  const lower = join21(dir, ".tw-case-probe-a");
16738
16813
  try {
16739
- writeFileSync11(upper, "", { flag: "wx" });
16814
+ writeFileSync8(upper, "", { flag: "wx" });
16740
16815
  return !existsSync10(lower);
16741
16816
  } finally {
16742
16817
  rmSync9(upper, { force: true });
@@ -16839,7 +16914,7 @@ function overlayPristine(cwd, base, dest, policy, cmd, dependencyRoot, caseSensi
16839
16914
  safeSymlink(target, out3, dest, `the base's ${e.path}`);
16840
16915
  restoredLinks.push({ path: e.path, out: out3, target });
16841
16916
  } else {
16842
- writeFileSync11(out3, content);
16917
+ writeFileSync8(out3, content);
16843
16918
  chmodSync2(out3, parseInt(e.mode.slice(-4), 8) & 511);
16844
16919
  }
16845
16920
  restored.push(e.path);
@@ -16864,7 +16939,7 @@ function suiteEnv(scratch) {
16864
16939
  }
16865
16940
  const userRc = join21(scratch, "npmrc-user");
16866
16941
  const globalRc = join21(scratch, "npmrc-global");
16867
- for (const f of [userRc, globalRc]) writeFileSync11(f, "", { mode: 292 });
16942
+ for (const f of [userRc, globalRc]) writeFileSync8(f, "", { mode: 292 });
16868
16943
  env.npm_config_userconfig = userRc;
16869
16944
  env.npm_config_globalconfig = globalRc;
16870
16945
  env.npm_config_node_options = " ";
@@ -17615,7 +17690,7 @@ var init_verify = __esm({
17615
17690
  // src/cli/run.ts
17616
17691
  import { execFileSync as execFileSync10, spawn, spawnSync as spawnSync4 } from "node:child_process";
17617
17692
  import { randomBytes as randomBytes3 } from "node:crypto";
17618
- import { accessSync as accessSync3, constants as fsConstants, mkdtempSync as mkdtempSync4, readdirSync as readdirSync4, readFileSync as readFileSync13, readlinkSync as readlinkSync4, realpathSync as realpathSync8, rmSync as rmSync10, statSync as statSync5, writeFileSync as writeFileSync12 } from "node:fs";
17693
+ import { accessSync as accessSync3, constants as fsConstants, mkdtempSync as mkdtempSync4, readdirSync as readdirSync4, readFileSync as readFileSync13, readlinkSync as readlinkSync4, realpathSync as realpathSync8, rmSync as rmSync10, statSync as statSync5, writeFileSync as writeFileSync9 } from "node:fs";
17619
17694
  import { tmpdir as tmpdir5 } from "node:os";
17620
17695
  import { dirname as dirname11, join as join22, resolve as resolve10 } from "node:path";
17621
17696
  function authoritativeRunLifecyclePlatform(platform = process.platform) {
@@ -17712,7 +17787,7 @@ function runAgentSupervised(argv, cwd, budgetSecs, linuxPythonCandidates, lifecy
17712
17787
  failure: trustedPython.reason ?? "trusted Linux python3 interpreter is unavailable"
17713
17788
  };
17714
17789
  }
17715
- writeFileSync12(agentEnvFile, JSON.stringify(process.env), { mode: 384 });
17790
+ writeFileSync9(agentEnvFile, JSON.stringify(process.env), { mode: 384 });
17716
17791
  executable = trustedPython.path;
17717
17792
  args = [
17718
17793
  "-I",
@@ -17823,8 +17898,7 @@ function observerExited(pid) {
17823
17898
  function supervisedObserverLog(cwd) {
17824
17899
  const gd = gitDir(cwd) ?? join22(cwd, ".git");
17825
17900
  return join22(
17826
- gd,
17827
- "tamperward",
17901
+ stateDirectory(gd),
17828
17902
  `run-observer-${process.pid}-${Date.now()}-${randomBytes3(4).toString("hex")}.jsonl`
17829
17903
  );
17830
17904
  }
@@ -19270,7 +19344,10 @@ function renderStatus(model, colour) {
19270
19344
  if (v.state === "STALE" && v.reason) rows.push(["Reason", v.reason]);
19271
19345
  else if (v.state === "BROKEN") rows.push(["Reason", v.detail ?? v.reason ?? "authority wiring is invalid"]);
19272
19346
  else if (v.state === "VERIFYING") rows.push(["Reason", v.reason ?? "a verification is in progress"]);
19273
- else if (v.state === "UNVERIFIED") rows.push(["Next", "run `tamperward verify` to establish a verified baseline"]);
19347
+ else if (v.state === "UNVERIFIED" && v.detail) {
19348
+ rows.push(["Reason", v.detail]);
19349
+ rows.push(["Next", "remove what stands at that path, then run `tamperward verify`"]);
19350
+ } else if (v.state === "UNVERIFIED") rows.push(["Next", "run `tamperward verify` to establish a verified baseline"]);
19274
19351
  if (rows.length) {
19275
19352
  lines.push("");
19276
19353
  const width = Math.max(...rows.map(([k]) => k.length));
@@ -21005,7 +21082,7 @@ var init_adapter3 = __esm({
21005
21082
 
21006
21083
  // src/adapters/copilot-sdk/changes.ts
21007
21084
  import { execFileSync as execFileSync13 } from "node:child_process";
21008
- import { mkdtempSync as mkdtempSync6, writeFileSync as writeFileSync13, readFileSync as readFileSync17, rmSync as rmSync12, existsSync as existsSync14, realpathSync as realpathSync10 } from "node:fs";
21085
+ import { mkdtempSync as mkdtempSync6, writeFileSync as writeFileSync10, readFileSync as readFileSync17, rmSync as rmSync12, existsSync as existsSync14, realpathSync as realpathSync10 } from "node:fs";
21009
21086
  import { tmpdir as tmpdir7 } from "node:os";
21010
21087
  import { basename as basename5, dirname as dirname12, isAbsolute as isAbsolute16, relative as relative11, resolve as resolve15, join as join26 } from "node:path";
21011
21088
  function asStr4(v) {
@@ -21082,9 +21159,9 @@ function reconstructAfterViaGit(rawDiff, display2, before, isCreate) {
21082
21159
  const dir = mkdtempSync6(join26(tmpdir7(), "hf-sdk-apply-"));
21083
21160
  try {
21084
21161
  const targetPath = join26(dir, TARGET);
21085
- if (op !== "create") writeFileSync13(targetPath, before ?? "");
21162
+ if (op !== "create") writeFileSync10(targetPath, before ?? "");
21086
21163
  const patchPath = join26(dir, "change.patch");
21087
- writeFileSync13(patchPath, patch);
21164
+ writeFileSync10(patchPath, patch);
21088
21165
  const git8 = (extra) => execFileSync13("git", ["apply", ...extra, patchPath], {
21089
21166
  cwd: dir,
21090
21167
  encoding: "utf8",
@@ -21852,17 +21929,19 @@ var init_runtime_qualification = __esm({
21852
21929
 
21853
21930
  // src/cli/runtime.ts
21854
21931
  import { execFileSync as execFileSync14 } from "node:child_process";
21855
- import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "node:fs";
21932
+ import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync18 } from "node:fs";
21856
21933
  import { join as join27, dirname as dirname13 } from "node:path";
21857
21934
  function storePath(cwd) {
21858
21935
  const dir = gitDir(cwd);
21859
- return dir ? join27(dir, "tamperward", "runtime-qualification.json") : null;
21936
+ return dir ? join27(stateDirectory(dir), "runtime-qualification.json") : null;
21860
21937
  }
21861
21938
  function readStore(cwd) {
21862
21939
  const path = storePath(cwd);
21863
- if (!path || !existsSync15(path)) return null;
21940
+ if (!path) return null;
21941
+ const raw = readStateFile(path);
21942
+ if (raw === null) return null;
21864
21943
  try {
21865
- const parsed = JSON.parse(readFileSync18(path, "utf8"));
21944
+ const parsed = JSON.parse(raw);
21866
21945
  if (parsed && typeof parsed === "object" && parsed.records && typeof parsed.records === "object") return parsed;
21867
21946
  } catch {
21868
21947
  return null;
@@ -21993,7 +22072,7 @@ function writeRecord(cwd, id, report2) {
21993
22072
  store.updated_at = report2.timestamp;
21994
22073
  try {
21995
22074
  mkdirSync11(dirname13(path), { recursive: true });
21996
- writeFileSync14(path, JSON.stringify(store, null, 2) + "\n", { mode: 384 });
22075
+ atomicReplaceFile(path, JSON.stringify(store, null, 2) + "\n", 384);
21997
22076
  return true;
21998
22077
  } catch {
21999
22078
  return false;
@@ -22173,7 +22252,13 @@ function emit2(report2, opts, cwd) {
22173
22252
  renderText3(report2, cwd);
22174
22253
  }
22175
22254
  function storedQualification(adapter, cwd, opts = {}) {
22176
- const raw = readStore(cwd)?.records[adapter.name];
22255
+ let raw;
22256
+ try {
22257
+ raw = readStore(cwd)?.records[adapter.name];
22258
+ } catch (e) {
22259
+ if (e instanceof StateFileError) return { state: "rejected", reason: e.message };
22260
+ throw e;
22261
+ }
22177
22262
  if (raw === void 0) return { state: "none" };
22178
22263
  const validated = validateStoredReport(raw);
22179
22264
  if ("reason" in validated) return { state: "rejected", reason: validated.reason };
@@ -22212,10 +22297,18 @@ function runRuntime(sub, opts) {
22212
22297
  }
22213
22298
  const { binding, assessments } = buildQualification(target, opts, cwd);
22214
22299
  const report2 = reportFrom("verify", binding, assessments);
22215
- const wrote = writeRecord(cwd, target.name, report2);
22300
+ let wrote = false;
22301
+ let refused;
22302
+ try {
22303
+ wrote = writeRecord(cwd, target.name, report2);
22304
+ } catch (e) {
22305
+ if (!(e instanceof StateFileError)) throw e;
22306
+ refused = e.message;
22307
+ }
22216
22308
  if (!wrote) {
22217
- const dest = storePath(cwd);
22218
- const reason = `could not persist the qualification to ${dest ?? "the git-local store (no repository found)"}; nothing was recorded, so \`tamperward runtime status\` will report UNQUALIFIED`;
22309
+ const dir = gitDir(cwd);
22310
+ const dest = dir ? join27(dir, "tamperward", "runtime-qualification.json") : null;
22311
+ const reason = `could not persist the qualification to ${dest ?? "the git-local store (no repository found)"}${refused ? ` (${refused})` : ""}; nothing was recorded, so \`tamperward runtime status\` will report UNQUALIFIED`;
22219
22312
  const failure = {
22220
22313
  ...report2,
22221
22314
  recorded: false,
@@ -22285,6 +22378,8 @@ var HONESTY_NOTE, CAP_ID_SET, STATE_SEVERITY, AGGREGATE_SEVERITY, RUNTIME_SUBCOM
22285
22378
  var init_runtime = __esm({
22286
22379
  "src/cli/runtime.ts"() {
22287
22380
  "use strict";
22381
+ init_disk();
22382
+ init_safe_write();
22288
22383
  init_build();
22289
22384
  init_wiring();
22290
22385
  init_machine_output();
@@ -23493,7 +23588,7 @@ var init_record = __esm({
23493
23588
  // src/research/run.ts
23494
23589
  import { randomUUID as randomUUID2 } from "node:crypto";
23495
23590
  import { execFileSync as execFileSync16 } from "node:child_process";
23496
- import { closeSync as closeSync5, existsSync as existsSync16, linkSync, mkdirSync as mkdirSync12, openSync as openSync5, readFileSync as readFileSync21, renameSync as renameSync4, rmSync as rmSync14, unlinkSync, writeFileSync as writeFileSync15, writeSync } from "node:fs";
23591
+ import { closeSync as closeSync5, existsSync as existsSync16, linkSync, mkdirSync as mkdirSync12, openSync as openSync5, readFileSync as readFileSync21, renameSync as renameSync4, rmSync as rmSync14, unlinkSync, writeFileSync as writeFileSync11, writeSync as writeSync2 } from "node:fs";
23497
23592
  import { hostname } from "node:os";
23498
23593
  import { join as join29, resolve as resolve19 } from "node:path";
23499
23594
  function git7(args, cwd) {
@@ -23574,7 +23669,7 @@ function acquireResearchLock(ledger, breakStaleLock = false) {
23574
23669
  let fd = -1;
23575
23670
  try {
23576
23671
  fd = openSync5(path, "wx", 384);
23577
- writeSync(fd, text);
23672
+ writeSync2(fd, text);
23578
23673
  closeSync5(fd);
23579
23674
  fd = -1;
23580
23675
  } catch (e) {
@@ -23638,7 +23733,7 @@ function resumableRecord(path, expected) {
23638
23733
  }
23639
23734
  function writeRecordAtomically(path, text) {
23640
23735
  const tmp = `${path}.${process.pid}.tmp`;
23641
- writeFileSync15(tmp, text);
23736
+ writeFileSync11(tmp, text);
23642
23737
  renameSync4(tmp, path);
23643
23738
  }
23644
23739
  function cloneArgs(repo, ws3) {
@@ -24239,7 +24334,7 @@ var init_summarize = __esm({
24239
24334
 
24240
24335
  // src/research/init.ts
24241
24336
  import { createHash as createHash17 } from "node:crypto";
24242
- import { existsSync as existsSync17, mkdirSync as mkdirSync13, readFileSync as readFileSync23, writeFileSync as writeFileSync16 } from "node:fs";
24337
+ import { existsSync as existsSync17, mkdirSync as mkdirSync13, readFileSync as readFileSync23, writeFileSync as writeFileSync12 } from "node:fs";
24243
24338
  import { basename as basename6, dirname as dirname15, resolve as resolve21 } from "node:path";
24244
24339
  function idFrom(repo) {
24245
24340
  const clean = repo.replace(/[\\/]$/, "").split(/[\\/]/).pop() || "task";
@@ -24269,7 +24364,7 @@ function createResearchManifest(opts) {
24269
24364
  };
24270
24365
  const text = JSON.stringify(doc, null, 2) + "\n";
24271
24366
  mkdirSync13(dirname15(out3), { recursive: true });
24272
- writeFileSync16(out3, text, { flag: "wx", mode: 384 });
24367
+ writeFileSync12(out3, text, { flag: "wx", mode: 384 });
24273
24368
  const parsed = readManifest(out3);
24274
24369
  if (parsed.tasks.length !== 1 || parsed.tasks[0].id !== id) throw new ResearchError(`research init wrote an invalid manifest ${out3}`);
24275
24370
  return out3;
@@ -24359,7 +24454,7 @@ var init_report2 = __esm({
24359
24454
  import { createHash as createHash18 } from "node:crypto";
24360
24455
  import { isDeepStrictEqual } from "node:util";
24361
24456
  import { gzipSync, gunzipSync } from "node:zlib";
24362
- import { mkdirSync as mkdirSync14, readFileSync as readFileSync24, writeFileSync as writeFileSync17 } from "node:fs";
24457
+ import { mkdirSync as mkdirSync14, readFileSync as readFileSync24, writeFileSync as writeFileSync13 } from "node:fs";
24363
24458
  import { dirname as dirname16, resolve as resolve22 } from "node:path";
24364
24459
  function octal(value, width) {
24365
24460
  return value.toString(8).padStart(width - 1, "0") + "\0";
@@ -24559,7 +24654,7 @@ function createResearchBundle(opts) {
24559
24654
  entries.push({ name: "provenance.json", bytes: jsonBytes(provenance) });
24560
24655
  const out3 = resolve22(opts.out);
24561
24656
  mkdirSync14(dirname16(out3), { recursive: true });
24562
- writeFileSync17(out3, gzipSync(makeTar(entries)), { flag: "wx", mode: 384 });
24657
+ writeFileSync13(out3, gzipSync(makeTar(entries)), { flag: "wx", mode: 384 });
24563
24658
  return out3;
24564
24659
  }
24565
24660
  function runResearchBundle(opts) {
@@ -24706,7 +24801,7 @@ var init_research = __esm({
24706
24801
  });
24707
24802
 
24708
24803
  // src/cli/receipt.ts
24709
- import { appendFileSync as appendFileSync6, readFileSync as readFileSync25, writeFileSync as writeFileSync18 } from "node:fs";
24804
+ import { appendFileSync as appendFileSync3, readFileSync as readFileSync25, writeFileSync as writeFileSync14 } from "node:fs";
24710
24805
  function parseReceipt(args) {
24711
24806
  const [sub, ...rest] = args;
24712
24807
  const exportOpts = {};
@@ -24808,7 +24903,7 @@ function runReceiptExport(opts = {}) {
24808
24903
  const serialized = JSON.stringify(receipt) + "\n";
24809
24904
  if (opts.out) {
24810
24905
  try {
24811
- writeFileSync18(opts.out, serialized);
24906
+ writeFileSync14(opts.out, serialized);
24812
24907
  } catch (e) {
24813
24908
  process.stderr.write(`tamperward: could not write receipt to ${opts.out} (${e instanceof Error ? e.message : String(e)})
24814
24909
  `);
@@ -25030,7 +25125,7 @@ function writeJobSummary(r, receipt, ciBinding, adjudicatedTree) {
25030
25125
  for (const d of r.divergence) md.push(`- ${d}`);
25031
25126
  md.push("");
25032
25127
  try {
25033
- appendFileSync6(path, md.join("\n") + "\n");
25128
+ appendFileSync3(path, md.join("\n") + "\n");
25034
25129
  } catch {
25035
25130
  }
25036
25131
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tamperward",
3
- "version": "2.39.10",
3
+ "version": "2.39.12",
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",