tamperward 2.39.9 → 2.39.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +266 -215
- 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);
|
|
@@ -769,6 +769,58 @@ function inspectResolved(abs) {
|
|
|
769
769
|
function textOf2(e) {
|
|
770
770
|
return e.content == null ? null : e.content.toString("utf8");
|
|
771
771
|
}
|
|
772
|
+
function notARegularFile(e) {
|
|
773
|
+
switch (e.kind) {
|
|
774
|
+
case "symlink":
|
|
775
|
+
return `is a symbolic link to ${escapeControl(e.detail)}`;
|
|
776
|
+
case "directory":
|
|
777
|
+
return "is a directory";
|
|
778
|
+
case "irregular":
|
|
779
|
+
return `is a ${e.detail}`;
|
|
780
|
+
case "oversize":
|
|
781
|
+
return `is ${e.detail}, above the ${READ_CAP / (1024 * 1024)} MiB the gate reads`;
|
|
782
|
+
default:
|
|
783
|
+
return `cannot be read (${e.detail})`;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
function readStateFile(abs) {
|
|
787
|
+
const e = inspectPath(abs);
|
|
788
|
+
if (e.kind === "absent") return null;
|
|
789
|
+
if (e.kind === "file") return textOf2(e) ?? "";
|
|
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`
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
function multiplyLinked(st) {
|
|
795
|
+
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`;
|
|
796
|
+
}
|
|
797
|
+
function appendRegular(abs, text, mode = 438) {
|
|
798
|
+
const st = lstatSync2(abs, { throwIfNoEntry: false });
|
|
799
|
+
if (st !== void 0 && !st.isFile()) throw new StateFileError(`${abs} ${notARegularFile(classify(abs, st))}${APPEND_REFUSED}`);
|
|
800
|
+
const linked = st === void 0 ? null : multiplyLinked(st);
|
|
801
|
+
if (linked !== null) throw new StateFileError(`${abs} ${linked}${APPEND_REFUSED}`);
|
|
802
|
+
let fd;
|
|
803
|
+
try {
|
|
804
|
+
fd = openSync(abs, O_APPEND_REGULAR, mode);
|
|
805
|
+
} catch (e) {
|
|
806
|
+
const code2 = errCode(e);
|
|
807
|
+
if (code2 === "ELOOP" || code2 === "ENXIO" || code2 === "EISDIR") {
|
|
808
|
+
throw new StateFileError(`${abs} changed shape while it was being opened (${errText(e)})${APPEND_REFUSED}`);
|
|
809
|
+
}
|
|
810
|
+
throw e;
|
|
811
|
+
}
|
|
812
|
+
try {
|
|
813
|
+
const now = fstatSync(fd);
|
|
814
|
+
if (!now.isFile()) throw new StateFileError(`${abs} is a ${irregularName(now)}${APPEND_REFUSED}`);
|
|
815
|
+
const opened = multiplyLinked(now);
|
|
816
|
+
if (opened !== null) throw new StateFileError(`${abs} ${opened}${APPEND_REFUSED}`);
|
|
817
|
+
const buf = Buffer.from(text, "utf8");
|
|
818
|
+
let off2 = 0;
|
|
819
|
+
while (off2 < buf.length) off2 += writeSync(fd, buf, off2, buf.length - off2);
|
|
820
|
+
} finally {
|
|
821
|
+
closeSync(fd);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
772
824
|
function describe(e, shown) {
|
|
773
825
|
switch (e.kind) {
|
|
774
826
|
case "symlink":
|
|
@@ -809,7 +861,7 @@ function unjudgeableProtected(cwd, policy, changes) {
|
|
|
809
861
|
}
|
|
810
862
|
return out3;
|
|
811
863
|
}
|
|
812
|
-
var READ_CAP, NO_META, O_READ;
|
|
864
|
+
var READ_CAP, NO_META, O_READ, StateFileError, O_APPEND_REGULAR, APPEND_REFUSED;
|
|
813
865
|
var init_disk = __esm({
|
|
814
866
|
"src/disk.ts"() {
|
|
815
867
|
"use strict";
|
|
@@ -818,6 +870,10 @@ var init_disk = __esm({
|
|
|
818
870
|
READ_CAP = 64 * 1024 * 1024;
|
|
819
871
|
NO_META = { mode: 0, size: 0, mtimeMs: 0 };
|
|
820
872
|
O_READ = constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0);
|
|
873
|
+
StateFileError = class extends Error {
|
|
874
|
+
};
|
|
875
|
+
O_APPEND_REGULAR = constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0);
|
|
876
|
+
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";
|
|
821
877
|
}
|
|
822
878
|
});
|
|
823
879
|
|
|
@@ -10868,20 +10924,6 @@ function parseOrThrow(src, where) {
|
|
|
10868
10924
|
}
|
|
10869
10925
|
return parsePolicy(raw, where);
|
|
10870
10926
|
}
|
|
10871
|
-
function notARegularFile(e) {
|
|
10872
|
-
switch (e.kind) {
|
|
10873
|
-
case "symlink":
|
|
10874
|
-
return `is a symbolic link to ${escapeControl(e.detail)}`;
|
|
10875
|
-
case "directory":
|
|
10876
|
-
return "is a directory";
|
|
10877
|
-
case "irregular":
|
|
10878
|
-
return `is a ${e.detail}`;
|
|
10879
|
-
case "oversize":
|
|
10880
|
-
return `is ${e.detail}, above the ${READ_CAP / (1024 * 1024)} MiB the gate reads`;
|
|
10881
|
-
default:
|
|
10882
|
-
return `cannot be read (${e.detail})`;
|
|
10883
|
-
}
|
|
10884
|
-
}
|
|
10885
10927
|
function loadPolicy(cwd = process.cwd()) {
|
|
10886
10928
|
const entry = inspectPath(join8(repoRoot(cwd), POLICY_FILE));
|
|
10887
10929
|
if (entry.kind === "absent") return defaultPolicy();
|
|
@@ -11553,7 +11595,7 @@ var init_deny = __esm({
|
|
|
11553
11595
|
});
|
|
11554
11596
|
|
|
11555
11597
|
// src/session.ts
|
|
11556
|
-
import {
|
|
11598
|
+
import { mkdirSync as mkdirSync2, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
11557
11599
|
import { dirname as dirname3, join as join10 } from "node:path";
|
|
11558
11600
|
function writeBaseline(p, sha3) {
|
|
11559
11601
|
mkdirSync2(dirname3(p), { recursive: true });
|
|
@@ -11578,13 +11620,8 @@ function turnBaseline(cwd, sessionId) {
|
|
|
11578
11620
|
if (!sessionId) return null;
|
|
11579
11621
|
const p = baselinePath(cwd, sessionId);
|
|
11580
11622
|
if (!p) return null;
|
|
11581
|
-
|
|
11582
|
-
|
|
11583
|
-
const v = readFileSync6(p, "utf8").trim();
|
|
11584
|
-
if (SHA.test(v)) return v;
|
|
11585
|
-
}
|
|
11586
|
-
} catch {
|
|
11587
|
-
}
|
|
11623
|
+
const v = readStateFile(p)?.trim();
|
|
11624
|
+
if (v !== void 0 && SHA.test(v)) return v;
|
|
11588
11625
|
const head = headSha(cwd);
|
|
11589
11626
|
if (!head) return null;
|
|
11590
11627
|
try {
|
|
@@ -11608,6 +11645,7 @@ var UNSAFE, SHA, BaselineWriteError;
|
|
|
11608
11645
|
var init_session = __esm({
|
|
11609
11646
|
"src/session.ts"() {
|
|
11610
11647
|
"use strict";
|
|
11648
|
+
init_disk();
|
|
11611
11649
|
init_build();
|
|
11612
11650
|
UNSAFE = /[^A-Za-z0-9_-]/g;
|
|
11613
11651
|
SHA = /^[0-9a-f]{40}$/;
|
|
@@ -11623,7 +11661,7 @@ var init_session = __esm({
|
|
|
11623
11661
|
|
|
11624
11662
|
// src/effect.ts
|
|
11625
11663
|
import { createHash as createHash4 } from "node:crypto";
|
|
11626
|
-
import {
|
|
11664
|
+
import { lstatSync as lstatSync4, mkdirSync as mkdirSync3, readdirSync, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
11627
11665
|
import { join as join11 } from "node:path";
|
|
11628
11666
|
function ptreeFrom(value) {
|
|
11629
11667
|
if (!isRecord(value)) return null;
|
|
@@ -11715,9 +11753,11 @@ function driftBetween(expected, current) {
|
|
|
11715
11753
|
return { changed, deleted, added };
|
|
11716
11754
|
}
|
|
11717
11755
|
function loadTree(p) {
|
|
11718
|
-
if (!p
|
|
11756
|
+
if (!p) return null;
|
|
11757
|
+
const text = readStateFile(p);
|
|
11758
|
+
if (text === null) return null;
|
|
11719
11759
|
try {
|
|
11720
|
-
return ptreeFrom(JSON.parse(
|
|
11760
|
+
return ptreeFrom(JSON.parse(text));
|
|
11721
11761
|
} catch {
|
|
11722
11762
|
return null;
|
|
11723
11763
|
}
|
|
@@ -11769,8 +11809,53 @@ var init_effect = __esm({
|
|
|
11769
11809
|
}
|
|
11770
11810
|
});
|
|
11771
11811
|
|
|
11812
|
+
// src/safe-write.ts
|
|
11813
|
+
import { randomBytes } from "node:crypto";
|
|
11814
|
+
import { lstatSync as lstatSync5, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
11815
|
+
function writeTargetKind(path) {
|
|
11816
|
+
let st;
|
|
11817
|
+
try {
|
|
11818
|
+
st = lstatSync5(path, { throwIfNoEntry: false });
|
|
11819
|
+
} catch (e) {
|
|
11820
|
+
if (errnoCode(e) === "ENOTDIR") return "absent";
|
|
11821
|
+
throw e;
|
|
11822
|
+
}
|
|
11823
|
+
if (!st) return "absent";
|
|
11824
|
+
if (st.isSymbolicLink()) return "symlink";
|
|
11825
|
+
return st.isFile() ? "file" : "irregular";
|
|
11826
|
+
}
|
|
11827
|
+
function refuseNonRegular(path) {
|
|
11828
|
+
switch (writeTargetKind(path)) {
|
|
11829
|
+
case "symlink":
|
|
11830
|
+
return "refusing: symlink \u2014 the target would be written instead of this path; replace the link with a regular file, then re-run";
|
|
11831
|
+
case "irregular":
|
|
11832
|
+
return "refusing: not a regular file \u2014 a directory or special file stands where a file is expected; remove it, then re-run";
|
|
11833
|
+
default:
|
|
11834
|
+
return null;
|
|
11835
|
+
}
|
|
11836
|
+
}
|
|
11837
|
+
function existingMode(path, fallback) {
|
|
11838
|
+
if (writeTargetKind(path) !== "file") return fallback;
|
|
11839
|
+
return lstatSync5(path).mode & 511;
|
|
11840
|
+
}
|
|
11841
|
+
function atomicReplaceFile(path, content, mode) {
|
|
11842
|
+
const tmp = `${path}.${process.pid}.${randomBytes(8).toString("hex")}.tmp`;
|
|
11843
|
+
try {
|
|
11844
|
+
writeFileSync4(tmp, content, { encoding: "utf8", flag: "wx", mode });
|
|
11845
|
+
renameSync3(tmp, path);
|
|
11846
|
+
} finally {
|
|
11847
|
+
rmSync4(tmp, { force: true });
|
|
11848
|
+
}
|
|
11849
|
+
}
|
|
11850
|
+
var init_safe_write = __esm({
|
|
11851
|
+
"src/safe-write.ts"() {
|
|
11852
|
+
"use strict";
|
|
11853
|
+
init_narrow();
|
|
11854
|
+
}
|
|
11855
|
+
});
|
|
11856
|
+
|
|
11772
11857
|
// src/cli/watch.ts
|
|
11773
|
-
import {
|
|
11858
|
+
import { lstatSync as lstatSync6, mkdirSync as mkdirSync4, readdirSync as readdirSync2, watch } from "node:fs";
|
|
11774
11859
|
import { join as join12 } from "node:path";
|
|
11775
11860
|
import { createHash as createHash5 } from "node:crypto";
|
|
11776
11861
|
function snap(abs) {
|
|
@@ -11788,8 +11873,10 @@ function watcherHealthPath(log) {
|
|
|
11788
11873
|
return `${log}.health.json`;
|
|
11789
11874
|
}
|
|
11790
11875
|
function readWatcherHealth(log) {
|
|
11876
|
+
const text = readStateFile(watcherHealthPath(log));
|
|
11877
|
+
if (text === null) return null;
|
|
11791
11878
|
try {
|
|
11792
|
-
const value = JSON.parse(
|
|
11879
|
+
const value = JSON.parse(text);
|
|
11793
11880
|
if (!isRecord(value)) return null;
|
|
11794
11881
|
const { state, backend, pid, started_at } = value;
|
|
11795
11882
|
if (value.version !== 1 || typeof pid !== "number" || typeof started_at !== "string") return null;
|
|
@@ -11823,7 +11910,13 @@ function pidAlive(pid) {
|
|
|
11823
11910
|
}
|
|
11824
11911
|
}
|
|
11825
11912
|
function watcherTelemetry(log) {
|
|
11826
|
-
|
|
11913
|
+
let health;
|
|
11914
|
+
try {
|
|
11915
|
+
health = readWatcherHealth(log);
|
|
11916
|
+
} catch (e) {
|
|
11917
|
+
if (!(e instanceof StateFileError)) throw e;
|
|
11918
|
+
return { state: "unavailable", health: null, reason: e.message };
|
|
11919
|
+
}
|
|
11827
11920
|
if (!health) return { state: "unavailable", health: null, reason: "no health record" };
|
|
11828
11921
|
if (health.state === "stopped")
|
|
11829
11922
|
return { state: "unavailable", health, reason: "observer stopped" };
|
|
@@ -11873,7 +11966,7 @@ function watchTree(dir, cb, onState, onError, watchFn = watch) {
|
|
|
11873
11966
|
const child = rel ? `${rel}/${String(fname)}` : String(fname);
|
|
11874
11967
|
cb(kind, child);
|
|
11875
11968
|
try {
|
|
11876
|
-
if (
|
|
11969
|
+
if (lstatSync6(join12(dir, child)).isDirectory()) addDir(child);
|
|
11877
11970
|
} catch {
|
|
11878
11971
|
}
|
|
11879
11972
|
});
|
|
@@ -11909,7 +12002,7 @@ function watchTree(dir, cb, onState, onError, watchFn = watch) {
|
|
|
11909
12002
|
const child = rel ? `${rel}/${name}` : name;
|
|
11910
12003
|
if (SKIP2.test(child + "/")) continue;
|
|
11911
12004
|
try {
|
|
11912
|
-
if (
|
|
12005
|
+
if (lstatSync6(join12(dir, child)).isDirectory()) walk2(child);
|
|
11913
12006
|
} catch {
|
|
11914
12007
|
}
|
|
11915
12008
|
}
|
|
@@ -11948,7 +12041,7 @@ function startWatcher(dir, log, policy, watchFn = watch) {
|
|
|
11948
12041
|
let healthWriteWarningEmitted = false;
|
|
11949
12042
|
const persistHealth = () => {
|
|
11950
12043
|
try {
|
|
11951
|
-
|
|
12044
|
+
atomicReplaceFile(healthPath, JSON.stringify(health) + "\n", 384);
|
|
11952
12045
|
healthWriteWarningEmitted = false;
|
|
11953
12046
|
} catch (e) {
|
|
11954
12047
|
if (!healthWriteWarningEmitted) {
|
|
@@ -11988,7 +12081,7 @@ function startWatcher(dir, log, policy, watchFn = watch) {
|
|
|
11988
12081
|
...s
|
|
11989
12082
|
};
|
|
11990
12083
|
try {
|
|
11991
|
-
|
|
12084
|
+
appendRegular(log, JSON.stringify(ev) + "\n");
|
|
11992
12085
|
health.event_count++;
|
|
11993
12086
|
health.last_append_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
11994
12087
|
persistHealth();
|
|
@@ -12051,6 +12144,7 @@ var init_watch = __esm({
|
|
|
12051
12144
|
"src/cli/watch.ts"() {
|
|
12052
12145
|
"use strict";
|
|
12053
12146
|
init_disk();
|
|
12147
|
+
init_safe_write();
|
|
12054
12148
|
init_policy_load();
|
|
12055
12149
|
init_policy();
|
|
12056
12150
|
init_build();
|
|
@@ -12316,15 +12410,15 @@ var init_fs_events = __esm({
|
|
|
12316
12410
|
});
|
|
12317
12411
|
|
|
12318
12412
|
// src/cli/audit.ts
|
|
12319
|
-
import { createHash as createHash6, randomBytes } from "node:crypto";
|
|
12320
|
-
import {
|
|
12413
|
+
import { createHash as createHash6, randomBytes as randomBytes2 } from "node:crypto";
|
|
12414
|
+
import { closeSync as closeSync4, existsSync as existsSync5, mkdirSync as mkdirSync5, openSync as openSync4, readSync as readSync3 } from "node:fs";
|
|
12321
12415
|
import { dirname as dirname4, isAbsolute as isAbsolute8, join as join13, resolve as resolve4 } from "node:path";
|
|
12322
12416
|
function sessionHash(sessionId) {
|
|
12323
12417
|
if (!sessionId) return void 0;
|
|
12324
12418
|
return "sha256:" + createHash6("sha256").update(sessionId).digest("hex").slice(0, 24);
|
|
12325
12419
|
}
|
|
12326
12420
|
function eventId() {
|
|
12327
|
-
return "sha256:" + createHash6("sha256").update(
|
|
12421
|
+
return "sha256:" + createHash6("sha256").update(randomBytes2(32)).digest("hex").slice(0, 32);
|
|
12328
12422
|
}
|
|
12329
12423
|
function configuredAuditPath(cwd, env = process.env) {
|
|
12330
12424
|
const value = env[AUDIT_LOG_ENV];
|
|
@@ -12362,7 +12456,7 @@ function recordAuditFindings(findings, context) {
|
|
|
12362
12456
|
};
|
|
12363
12457
|
return JSON.stringify(event);
|
|
12364
12458
|
});
|
|
12365
|
-
|
|
12459
|
+
appendRegular(path, lines.join("\n") + "\n");
|
|
12366
12460
|
} catch {
|
|
12367
12461
|
}
|
|
12368
12462
|
}
|
|
@@ -12576,7 +12670,7 @@ function runStats(opts = {}) {
|
|
|
12576
12670
|
const file = opts.file ? isAbsolute8(opts.file) ? opts.file : resolve4(cwd, opts.file) : configured && configured !== "auto" ? isAbsolute8(configured) ? configured : resolve4(cwd, configured) : defaultAuditPath(cwd);
|
|
12577
12671
|
const cutoff = opts.since ? parseSince(opts.since) : null;
|
|
12578
12672
|
if (!file) throw new Error("stats needs --file outside a Git repository");
|
|
12579
|
-
if (!
|
|
12673
|
+
if (!existsSync5(file)) {
|
|
12580
12674
|
if (explicitFile) throw new Error(`audit file not found: ${file}`);
|
|
12581
12675
|
const empty2 = summarizeAudit([]);
|
|
12582
12676
|
process.stdout.write(opts.json ? JSON.stringify(empty2) + "\n" : renderAuditStats(empty2));
|
|
@@ -12597,6 +12691,7 @@ var init_audit = __esm({
|
|
|
12597
12691
|
"src/cli/audit.ts"() {
|
|
12598
12692
|
"use strict";
|
|
12599
12693
|
init_repo_context();
|
|
12694
|
+
init_disk();
|
|
12600
12695
|
AUDIT_SCHEMA_VERSION = 1;
|
|
12601
12696
|
AUDIT_LOG_ENV = "TAMPERWARD_AUDIT_LOG";
|
|
12602
12697
|
MAX_AUDIT_LINE_BYTES = 16 * 1024;
|
|
@@ -12615,14 +12710,14 @@ var init_audit = __esm({
|
|
|
12615
12710
|
});
|
|
12616
12711
|
|
|
12617
12712
|
// src/cli/hook.ts
|
|
12618
|
-
import { readFileSync as
|
|
12713
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync6 } from "node:fs";
|
|
12619
12714
|
import { createHash as createHash7 } from "node:crypto";
|
|
12620
12715
|
function setSnapshotCache(cache3) {
|
|
12621
12716
|
snapshotCache = cache3;
|
|
12622
12717
|
}
|
|
12623
12718
|
function readStdin() {
|
|
12624
12719
|
try {
|
|
12625
|
-
return
|
|
12720
|
+
return readFileSync6(0, "utf8");
|
|
12626
12721
|
} catch (e) {
|
|
12627
12722
|
throw new HookInputError(`cannot read the hook payload on stdin: ${e instanceof Error ? e.message : String(e)}`);
|
|
12628
12723
|
}
|
|
@@ -12650,7 +12745,7 @@ function recordDenylog(blocks2) {
|
|
|
12650
12745
|
const log = process.env.TAMPERWARD_DENYLOG;
|
|
12651
12746
|
if (!log) return;
|
|
12652
12747
|
try {
|
|
12653
|
-
|
|
12748
|
+
appendRegular(log, blocks2.map((b) => b.rule).join(",") + "\n");
|
|
12654
12749
|
} catch {
|
|
12655
12750
|
}
|
|
12656
12751
|
}
|
|
@@ -12912,10 +13007,11 @@ function turnTransientBlocks(cwd, sessionId, policy, changes) {
|
|
|
12912
13007
|
recordObserverHealth(cwd, sessionId, telemetry.state, telemetry.reason);
|
|
12913
13008
|
}
|
|
12914
13009
|
const cp = cursorPath(cwd, sessionId);
|
|
12915
|
-
if (!
|
|
13010
|
+
if (!existsSync6(log)) return none;
|
|
12916
13011
|
let offset = 0;
|
|
12917
|
-
|
|
12918
|
-
|
|
13012
|
+
const cursorText = cp ? readStateFile(cp) : null;
|
|
13013
|
+
if (cursorText !== null) {
|
|
13014
|
+
const n2 = Number(cursorText);
|
|
12919
13015
|
offset = Number.isFinite(n2) ? n2 : 0;
|
|
12920
13016
|
}
|
|
12921
13017
|
const drained = drainEvents(log, offset);
|
|
@@ -12968,7 +13064,7 @@ function recordWarns(cwd, sessionId, warns) {
|
|
|
12968
13064
|
const log = process.env.TAMPERWARD_DENYLOG;
|
|
12969
13065
|
if (!log) return;
|
|
12970
13066
|
try {
|
|
12971
|
-
|
|
13067
|
+
appendRegular(log, warns.map((w) => `warn:${w.rule}:${w.file ?? ""}`).join("\n") + "\n");
|
|
12972
13068
|
} catch {
|
|
12973
13069
|
}
|
|
12974
13070
|
}
|
|
@@ -12978,7 +13074,7 @@ function recordObserverHealth(cwd, sessionId, state, reason) {
|
|
|
12978
13074
|
if (!log) return;
|
|
12979
13075
|
const detail = (reason ?? "").replace(/[\r\n]+/g, " ").trim();
|
|
12980
13076
|
try {
|
|
12981
|
-
|
|
13077
|
+
appendRegular(
|
|
12982
13078
|
log,
|
|
12983
13079
|
`warn:transient-observer:${state}${detail ? ":" + detail : ""}
|
|
12984
13080
|
`
|
|
@@ -13095,7 +13191,7 @@ var init_hook = __esm({
|
|
|
13095
13191
|
});
|
|
13096
13192
|
|
|
13097
13193
|
// src/ptree-cache.ts
|
|
13098
|
-
import { lstatSync as
|
|
13194
|
+
import { lstatSync as lstatSync7 } from "node:fs";
|
|
13099
13195
|
import { join as join14 } from "node:path";
|
|
13100
13196
|
function keyOf(st) {
|
|
13101
13197
|
return `${st.dev}:${st.ino}:${st.size}:${st.mode}:${st.mtimeNs}:${st.ctimeNs}`;
|
|
@@ -13149,7 +13245,7 @@ var init_ptree_cache = __esm({
|
|
|
13149
13245
|
const abs = join14(cwd, rel);
|
|
13150
13246
|
let st;
|
|
13151
13247
|
try {
|
|
13152
|
-
st =
|
|
13248
|
+
st = lstatSync7(abs, { bigint: true });
|
|
13153
13249
|
} catch {
|
|
13154
13250
|
this.map.delete(abs);
|
|
13155
13251
|
this.stats.misses++;
|
|
@@ -13171,7 +13267,7 @@ var init_ptree_cache = __esm({
|
|
|
13171
13267
|
const entry = compute();
|
|
13172
13268
|
let after;
|
|
13173
13269
|
try {
|
|
13174
|
-
after =
|
|
13270
|
+
after = lstatSync7(abs, { bigint: true });
|
|
13175
13271
|
} catch {
|
|
13176
13272
|
this.map.delete(abs);
|
|
13177
13273
|
return entry;
|
|
@@ -13189,13 +13285,13 @@ var init_ptree_cache = __esm({
|
|
|
13189
13285
|
});
|
|
13190
13286
|
|
|
13191
13287
|
// src/cli/hook-service.ts
|
|
13192
|
-
import { chmodSync, existsSync as
|
|
13288
|
+
import { chmodSync, existsSync as existsSync7, lstatSync as lstatSync8, mkdirSync as mkdirSync6, readFileSync as readFileSync7, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "node:fs";
|
|
13193
13289
|
import { createConnection as createConnection2, createServer } from "node:net";
|
|
13194
13290
|
import { realpathSync as realpathSync4 } from "node:fs";
|
|
13195
13291
|
import { sep } from "node:path";
|
|
13196
13292
|
function readServiceState(paths) {
|
|
13197
13293
|
try {
|
|
13198
|
-
const v = JSON.parse(
|
|
13294
|
+
const v = JSON.parse(readFileSync7(paths.state, "utf8"));
|
|
13199
13295
|
if (!isRecord(v)) return null;
|
|
13200
13296
|
const { pid, version, root, started_at } = v;
|
|
13201
13297
|
if (typeof pid !== "number" || typeof version !== "string" || typeof root !== "string" || typeof started_at !== "string") return null;
|
|
@@ -13272,13 +13368,13 @@ function withEnv(env, fn) {
|
|
|
13272
13368
|
}
|
|
13273
13369
|
function removeQuietly(p) {
|
|
13274
13370
|
try {
|
|
13275
|
-
|
|
13371
|
+
rmSync5(p, { force: true });
|
|
13276
13372
|
} catch {
|
|
13277
13373
|
}
|
|
13278
13374
|
}
|
|
13279
13375
|
function ensurePrivateDir(dir, uid) {
|
|
13280
|
-
if (!
|
|
13281
|
-
const st =
|
|
13376
|
+
if (!existsSync7(dir)) mkdirSync6(dir, { recursive: true, mode: 448 });
|
|
13377
|
+
const st = lstatSync8(dir);
|
|
13282
13378
|
if (!st.isDirectory()) throw new Error(`${dir} is not a directory`);
|
|
13283
13379
|
if (st.uid !== uid) throw new Error(`${dir} is owned by uid ${st.uid}, not ${uid}; refusing to serve from it`);
|
|
13284
13380
|
if ((st.mode & 63) !== 0) chmodSync(dir, 448);
|
|
@@ -13474,7 +13570,7 @@ async function stopHookService(paths, expectedRoot) {
|
|
|
13474
13570
|
process.kill(st.pid, "SIGTERM");
|
|
13475
13571
|
} catch {
|
|
13476
13572
|
}
|
|
13477
|
-
const gone = () => !pidAlive2(st.pid) || !
|
|
13573
|
+
const gone = () => !pidAlive2(st.pid) || !existsSync7(paths.socket);
|
|
13478
13574
|
const until = Date.now() + STOP_WAIT_MS;
|
|
13479
13575
|
while (!gone() && Date.now() < until) sleepSync(50);
|
|
13480
13576
|
if (!gone()) throw new Error(`hook service pid ${st.pid} did not exit within ${STOP_WAIT_MS / 1e3}s`);
|
|
@@ -13708,55 +13804,10 @@ var init_verifier_limits = __esm({
|
|
|
13708
13804
|
}
|
|
13709
13805
|
});
|
|
13710
13806
|
|
|
13711
|
-
// src/safe-write.ts
|
|
13712
|
-
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
13713
|
-
import { lstatSync as lstatSync8, renameSync as renameSync3, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "node:fs";
|
|
13714
|
-
function writeTargetKind(path) {
|
|
13715
|
-
let st;
|
|
13716
|
-
try {
|
|
13717
|
-
st = lstatSync8(path, { throwIfNoEntry: false });
|
|
13718
|
-
} catch (e) {
|
|
13719
|
-
if (errnoCode(e) === "ENOTDIR") return "absent";
|
|
13720
|
-
throw e;
|
|
13721
|
-
}
|
|
13722
|
-
if (!st) return "absent";
|
|
13723
|
-
if (st.isSymbolicLink()) return "symlink";
|
|
13724
|
-
return st.isFile() ? "file" : "irregular";
|
|
13725
|
-
}
|
|
13726
|
-
function refuseNonRegular(path) {
|
|
13727
|
-
switch (writeTargetKind(path)) {
|
|
13728
|
-
case "symlink":
|
|
13729
|
-
return "refusing: symlink \u2014 the target would be written instead of this path; replace the link with a regular file, then re-run";
|
|
13730
|
-
case "irregular":
|
|
13731
|
-
return "refusing: not a regular file \u2014 a directory or special file stands where a file is expected; remove it, then re-run";
|
|
13732
|
-
default:
|
|
13733
|
-
return null;
|
|
13734
|
-
}
|
|
13735
|
-
}
|
|
13736
|
-
function existingMode(path, fallback) {
|
|
13737
|
-
if (writeTargetKind(path) !== "file") return fallback;
|
|
13738
|
-
return lstatSync8(path).mode & 511;
|
|
13739
|
-
}
|
|
13740
|
-
function atomicReplaceFile(path, content, mode) {
|
|
13741
|
-
const tmp = `${path}.${process.pid}.${randomBytes2(8).toString("hex")}.tmp`;
|
|
13742
|
-
try {
|
|
13743
|
-
writeFileSync7(tmp, content, { encoding: "utf8", flag: "wx", mode });
|
|
13744
|
-
renameSync3(tmp, path);
|
|
13745
|
-
} finally {
|
|
13746
|
-
rmSync5(tmp, { force: true });
|
|
13747
|
-
}
|
|
13748
|
-
}
|
|
13749
|
-
var init_safe_write = __esm({
|
|
13750
|
-
"src/safe-write.ts"() {
|
|
13751
|
-
"use strict";
|
|
13752
|
-
init_narrow();
|
|
13753
|
-
}
|
|
13754
|
-
});
|
|
13755
|
-
|
|
13756
13807
|
// src/cli/init.ts
|
|
13757
13808
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
13758
13809
|
import { createHash as createHash8 } from "node:crypto";
|
|
13759
|
-
import { existsSync as
|
|
13810
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync8, realpathSync as realpathSync5 } from "node:fs";
|
|
13760
13811
|
import { basename as basename3, dirname as dirname5, isAbsolute as isAbsolute9, join as join15, relative as relative4, resolve as resolve6 } from "node:path";
|
|
13761
13812
|
function gitConfig(cwd, key2) {
|
|
13762
13813
|
try {
|
|
@@ -13850,34 +13901,34 @@ function verifierCandidates(cwd) {
|
|
|
13850
13901
|
if (!candidates.includes(command)) candidates.push(command);
|
|
13851
13902
|
};
|
|
13852
13903
|
try {
|
|
13853
|
-
const pkg = JSON.parse(
|
|
13904
|
+
const pkg = JSON.parse(readFileSync8(join15(cwd, "package.json"), "utf8"));
|
|
13854
13905
|
const test = isRecord(pkg) && isRecord(pkg.scripts) ? pkg.scripts.test : void 0;
|
|
13855
13906
|
if (typeof test === "string" && test.trim() !== "" && !/error:\s*no test specified/i.test(test)) add("npm test");
|
|
13856
13907
|
} catch {
|
|
13857
13908
|
}
|
|
13858
13909
|
try {
|
|
13859
|
-
const pyproject =
|
|
13910
|
+
const pyproject = readFileSync8(join15(cwd, "pyproject.toml"), "utf8");
|
|
13860
13911
|
if (/^\s*\[tool\.pytest(?:\.ini_options)?\]\s*$/m.test(pyproject)) add("pytest");
|
|
13861
13912
|
} catch {
|
|
13862
13913
|
}
|
|
13863
|
-
if (
|
|
13914
|
+
if (existsSync8(join15(cwd, "pytest.ini"))) add("pytest");
|
|
13864
13915
|
try {
|
|
13865
|
-
const setupCfg =
|
|
13916
|
+
const setupCfg = readFileSync8(join15(cwd, "setup.cfg"), "utf8");
|
|
13866
13917
|
if (/^\s*\[tool:pytest\]\s*$/m.test(setupCfg)) add("pytest");
|
|
13867
13918
|
} catch {
|
|
13868
13919
|
}
|
|
13869
13920
|
try {
|
|
13870
|
-
const tox =
|
|
13921
|
+
const tox = readFileSync8(join15(cwd, "tox.ini"), "utf8");
|
|
13871
13922
|
if (/^\s*\[tox\]\s*$/m.test(tox)) add("tox");
|
|
13872
13923
|
} catch {
|
|
13873
13924
|
}
|
|
13874
13925
|
try {
|
|
13875
|
-
const cargo =
|
|
13926
|
+
const cargo = readFileSync8(join15(cwd, "Cargo.toml"), "utf8");
|
|
13876
13927
|
if (/^\s*\[(?:package|workspace)\]\s*(?:#.*)?$/m.test(cargo)) add("cargo test");
|
|
13877
13928
|
} catch {
|
|
13878
13929
|
}
|
|
13879
13930
|
try {
|
|
13880
|
-
const goMod =
|
|
13931
|
+
const goMod = readFileSync8(join15(cwd, "go.mod"), "utf8");
|
|
13881
13932
|
if (/^\s*module\s+\S+\s*(?:\/\/.*)?$/m.test(goMod)) add("go test ./...");
|
|
13882
13933
|
} catch {
|
|
13883
13934
|
}
|
|
@@ -13920,7 +13971,7 @@ function planPolicy(cwd) {
|
|
|
13920
13971
|
const path = join15(cwd, POLICY_FILE);
|
|
13921
13972
|
const refused = refuseNonRegular(path);
|
|
13922
13973
|
if (refused) return { item: "policy", path: POLICY_FILE, status: "error", detail: refused };
|
|
13923
|
-
if (
|
|
13974
|
+
if (existsSync8(path)) {
|
|
13924
13975
|
try {
|
|
13925
13976
|
loadPolicy(cwd);
|
|
13926
13977
|
} catch (e) {
|
|
@@ -13939,7 +13990,7 @@ function planPolicy(cwd) {
|
|
|
13939
13990
|
function planGitignore(cwd) {
|
|
13940
13991
|
const rel = ".gitignore";
|
|
13941
13992
|
const path = join15(cwd, rel);
|
|
13942
|
-
if (!
|
|
13993
|
+
if (!existsSync8(join15(cwd, "node_modules"))) return null;
|
|
13943
13994
|
let existing = "";
|
|
13944
13995
|
let kind;
|
|
13945
13996
|
try {
|
|
@@ -13949,7 +14000,7 @@ function planGitignore(cwd) {
|
|
|
13949
14000
|
}
|
|
13950
14001
|
const refused = refuseNonRegular(path);
|
|
13951
14002
|
if (refused) return { item: "gitignore", path: rel, status: "error", detail: refused };
|
|
13952
|
-
if (kind === "file") existing =
|
|
14003
|
+
if (kind === "file") existing = readFileSync8(path, "utf8");
|
|
13953
14004
|
try {
|
|
13954
14005
|
const tracked = execFileSync6("git", ["ls-files", "--cached", "--", "node_modules"], {
|
|
13955
14006
|
cwd,
|
|
@@ -14004,10 +14055,10 @@ function planClaudeHooks(cwd) {
|
|
|
14004
14055
|
const refused = refuseNonRegular(path);
|
|
14005
14056
|
if (refused) return { item: "agent", path: rel, status: "error", detail: refused };
|
|
14006
14057
|
let settings = {};
|
|
14007
|
-
if (
|
|
14058
|
+
if (existsSync8(path)) {
|
|
14008
14059
|
let parsed;
|
|
14009
14060
|
try {
|
|
14010
|
-
parsed = JSON.parse(
|
|
14061
|
+
parsed = JSON.parse(readFileSync8(path, "utf8"));
|
|
14011
14062
|
} catch {
|
|
14012
14063
|
return {
|
|
14013
14064
|
item: "agent",
|
|
@@ -14056,7 +14107,7 @@ function planClaudeHooks(cwd) {
|
|
|
14056
14107
|
return {
|
|
14057
14108
|
item: "agent",
|
|
14058
14109
|
path: rel,
|
|
14059
|
-
status:
|
|
14110
|
+
status: existsSync8(path) ? "update" : "create",
|
|
14060
14111
|
detail: [
|
|
14061
14112
|
needPre && "wire PreToolUse deny",
|
|
14062
14113
|
needStop && "wire Stop sweep",
|
|
@@ -14100,7 +14151,7 @@ function hooksDir(cwd) {
|
|
|
14100
14151
|
if (out3) return resolve6(cwd, out3);
|
|
14101
14152
|
} catch {
|
|
14102
14153
|
}
|
|
14103
|
-
return
|
|
14154
|
+
return existsSync8(join15(cwd, ".git")) ? join15(cwd, ".git", "hooks") : null;
|
|
14104
14155
|
}
|
|
14105
14156
|
function display(cwd, path) {
|
|
14106
14157
|
const rel = relative4(cwd, path);
|
|
@@ -14127,11 +14178,11 @@ function planPreCommit(cwd) {
|
|
|
14127
14178
|
const skip = (detail) => ({ item: "pre-commit", path: "(none)", status: "skip", detail });
|
|
14128
14179
|
let path;
|
|
14129
14180
|
let note;
|
|
14130
|
-
if (
|
|
14181
|
+
if (existsSync8(join15(cwd, ".husky"))) {
|
|
14131
14182
|
path = join15(cwd, ".husky", "pre-commit");
|
|
14132
14183
|
note = "husky";
|
|
14133
14184
|
} else {
|
|
14134
|
-
const managed = MANAGED_HOOKS.find((m) => m.configs.some((c) =>
|
|
14185
|
+
const managed = MANAGED_HOOKS.find((m) => m.configs.some((c) => existsSync8(join15(cwd, c))));
|
|
14135
14186
|
if (managed) {
|
|
14136
14187
|
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}`);
|
|
14137
14188
|
}
|
|
@@ -14149,7 +14200,7 @@ function planPreCommit(cwd) {
|
|
|
14149
14200
|
const rel = display(cwd, path);
|
|
14150
14201
|
const refused = refuseNonRegular(path);
|
|
14151
14202
|
if (refused) return { item: "pre-commit", path: rel, status: "error", detail: refused };
|
|
14152
|
-
const existing =
|
|
14203
|
+
const existing = existsSync8(path) ? readFileSync8(path, "utf8") : null;
|
|
14153
14204
|
const hookMode = () => existingMode(path, 493) | 73;
|
|
14154
14205
|
if (existing === null) {
|
|
14155
14206
|
return {
|
|
@@ -14240,7 +14291,7 @@ function planCodeowners(cwd) {
|
|
|
14240
14291
|
const path = join15(cwd, existingRel ?? rel);
|
|
14241
14292
|
const refused = refuseNonRegular(path);
|
|
14242
14293
|
if (refused) return { item: "codeowners", path: existingRel ?? rel, status: "error", detail: refused };
|
|
14243
|
-
const existing = existingRel ?
|
|
14294
|
+
const existing = existingRel ? readFileSync8(path, "utf8") : null;
|
|
14244
14295
|
const missing = CODEOWNERS_PATHS.filter((p) => existing === null || !coveredBy(existing, p));
|
|
14245
14296
|
if (existingRel !== void 0 && missing.length === 0) {
|
|
14246
14297
|
return { item: "codeowners", path: existingRel, status: "ok", detail: "gate paths already have code owners" };
|
|
@@ -14280,7 +14331,7 @@ function planWorkflow(cwd, force) {
|
|
|
14280
14331
|
};
|
|
14281
14332
|
const refused = refuseNonRegular(path);
|
|
14282
14333
|
if (refused) return { item: "ci", path: rel, status: "error", detail: refused };
|
|
14283
|
-
if (!
|
|
14334
|
+
if (!existsSync8(path)) {
|
|
14284
14335
|
return {
|
|
14285
14336
|
item: "ci",
|
|
14286
14337
|
path: rel,
|
|
@@ -14291,7 +14342,7 @@ function planWorkflow(cwd, force) {
|
|
|
14291
14342
|
}
|
|
14292
14343
|
let src;
|
|
14293
14344
|
try {
|
|
14294
|
-
src =
|
|
14345
|
+
src = readFileSync8(path, "utf8");
|
|
14295
14346
|
} catch {
|
|
14296
14347
|
return { item: "ci", path: rel, status: "error", detail: "exists but cannot be read \u2014 refusing to overwrite" };
|
|
14297
14348
|
}
|
|
@@ -14638,10 +14689,10 @@ var init_fingerprint = __esm({
|
|
|
14638
14689
|
// src/dependency-env.ts
|
|
14639
14690
|
import { createHash as createHash10 } from "node:crypto";
|
|
14640
14691
|
import {
|
|
14641
|
-
existsSync as
|
|
14692
|
+
existsSync as existsSync9,
|
|
14642
14693
|
lstatSync as lstatSync9,
|
|
14643
14694
|
readdirSync as readdirSync3,
|
|
14644
|
-
readFileSync as
|
|
14695
|
+
readFileSync as readFileSync9,
|
|
14645
14696
|
readlinkSync as readlinkSync2,
|
|
14646
14697
|
realpathSync as realpathSync6,
|
|
14647
14698
|
statSync as statSync3
|
|
@@ -14699,7 +14750,7 @@ function fingerprintRoot(root, cwd, h) {
|
|
|
14699
14750
|
st = statSync3(path);
|
|
14700
14751
|
if (!st.isFile()) throw new Error("not a regular file");
|
|
14701
14752
|
h.update(label + "\0external-file\0" + path + "\0" + String(st.mode) + "\0");
|
|
14702
|
-
h.update(
|
|
14753
|
+
h.update(readFileSync9(path));
|
|
14703
14754
|
h.update("\0");
|
|
14704
14755
|
} catch (e) {
|
|
14705
14756
|
throw new Unattestable(
|
|
@@ -14733,7 +14784,7 @@ function fingerprintRoot(root, cwd, h) {
|
|
|
14733
14784
|
h.update(rel + "\0" + ident.kind + "\0" + String(ident.mode) + "\0");
|
|
14734
14785
|
if (ident.kind === "file") {
|
|
14735
14786
|
try {
|
|
14736
|
-
h.update(
|
|
14787
|
+
h.update(readFileSync9(path));
|
|
14737
14788
|
h.update("\0");
|
|
14738
14789
|
} catch (e) {
|
|
14739
14790
|
throw new Unattestable(
|
|
@@ -14792,7 +14843,7 @@ function snapshot(roots, probes, cwd) {
|
|
|
14792
14843
|
const h = createHash10("sha256");
|
|
14793
14844
|
for (const probe of probes) {
|
|
14794
14845
|
h.update(
|
|
14795
|
-
"probe\0" + probe.kind + "\0" + probe.path + "\0" + (
|
|
14846
|
+
"probe\0" + probe.kind + "\0" + probe.path + "\0" + (existsSync9(probe.path) ? "present" : "absent") + "\0"
|
|
14796
14847
|
);
|
|
14797
14848
|
}
|
|
14798
14849
|
for (const root of roots) fingerprintRoot(root, cwd, h);
|
|
@@ -14851,7 +14902,7 @@ function resolveExecutable(token, cwd, env) {
|
|
|
14851
14902
|
if (token.includes("/") || token.includes("\\")) {
|
|
14852
14903
|
const path = isAbsolute10(token) ? token : resolve7(cwd, token);
|
|
14853
14904
|
try {
|
|
14854
|
-
return
|
|
14905
|
+
return existsSync9(path) ? realpathSync6(path) : null;
|
|
14855
14906
|
} catch {
|
|
14856
14907
|
return null;
|
|
14857
14908
|
}
|
|
@@ -14859,7 +14910,7 @@ function resolveExecutable(token, cwd, env) {
|
|
|
14859
14910
|
for (const entry of (env.PATH ?? "").split(delimiter).filter(Boolean)) {
|
|
14860
14911
|
const candidate = resolve7(entry, token);
|
|
14861
14912
|
try {
|
|
14862
|
-
if (
|
|
14913
|
+
if (existsSync9(candidate) && statSync3(candidate).isFile()) return realpathSync6(candidate);
|
|
14863
14914
|
} catch {
|
|
14864
14915
|
}
|
|
14865
14916
|
}
|
|
@@ -14882,7 +14933,7 @@ function inferredVenvFromToken(token, cwd) {
|
|
|
14882
14933
|
const parentName = basename4(parent).toLowerCase();
|
|
14883
14934
|
if (parentName !== "bin" && parentName !== "scripts") return null;
|
|
14884
14935
|
const root = dirname6(parent);
|
|
14885
|
-
return
|
|
14936
|
+
return existsSync9(join16(root, "pyvenv.cfg")) ? root : null;
|
|
14886
14937
|
}
|
|
14887
14938
|
function unsupportedEcosystem(command, token) {
|
|
14888
14939
|
const name = token ? basename4(token).toLowerCase() : "";
|
|
@@ -14898,13 +14949,13 @@ function inferredVenv(executable) {
|
|
|
14898
14949
|
const parentName = basename4(parent).toLowerCase();
|
|
14899
14950
|
if (parentName !== "bin" && parentName !== "scripts") return null;
|
|
14900
14951
|
const root = dirname6(parent);
|
|
14901
|
-
return
|
|
14952
|
+
return existsSync9(join16(root, "pyvenv.cfg")) ? root : null;
|
|
14902
14953
|
}
|
|
14903
14954
|
function venvProblem(root) {
|
|
14904
14955
|
const cfg = join16(root, "pyvenv.cfg");
|
|
14905
|
-
if (!
|
|
14956
|
+
if (!existsSync9(cfg)) return "VIRTUAL_ENV " + JSON.stringify(root) + " has no pyvenv.cfg";
|
|
14906
14957
|
try {
|
|
14907
|
-
const body =
|
|
14958
|
+
const body = readFileSync9(cfg, "utf8");
|
|
14908
14959
|
if (/^\s*include-system-site-packages\s*=\s*true\s*$/im.test(body)) {
|
|
14909
14960
|
return "Python environment " + JSON.stringify(root) + " enables system site-packages; those external package roots are not bounded";
|
|
14910
14961
|
}
|
|
@@ -14929,7 +14980,7 @@ function discoverDependencyEnvironment(cwdInput, command, env = process.env) {
|
|
|
14929
14980
|
};
|
|
14930
14981
|
try {
|
|
14931
14982
|
const nodeModules = join16(cwd, "node_modules");
|
|
14932
|
-
if (
|
|
14983
|
+
if (existsSync9(nodeModules)) addRoot("node_modules", nodeModules);
|
|
14933
14984
|
else probes.push({ kind: "node_modules", path: nodeModules });
|
|
14934
14985
|
const token = firstExecutable(command);
|
|
14935
14986
|
const executable = resolveExecutable(token, cwd, env);
|
|
@@ -14941,7 +14992,7 @@ function discoverDependencyEnvironment(cwdInput, command, env = process.env) {
|
|
|
14941
14992
|
venv = resolve7(env.VIRTUAL_ENV);
|
|
14942
14993
|
} else {
|
|
14943
14994
|
venv = inferredVenv(executable) ?? inferredVenvFromToken(token, cwd);
|
|
14944
|
-
if (!venv && /(?:^|\s)uv\s+run(?:\s|$)/.test(command) &&
|
|
14995
|
+
if (!venv && /(?:^|\s)uv\s+run(?:\s|$)/.test(command) && existsSync9(join16(cwd, ".venv", "pyvenv.cfg"))) {
|
|
14945
14996
|
venv = join16(cwd, ".venv");
|
|
14946
14997
|
}
|
|
14947
14998
|
}
|
|
@@ -15046,7 +15097,7 @@ var init_dependency_env = __esm({
|
|
|
15046
15097
|
|
|
15047
15098
|
// src/suite-diagnostics.ts
|
|
15048
15099
|
import { spawnSync } from "node:child_process";
|
|
15049
|
-
import { mkdtempSync as mkdtempSync2, rmSync as rmSync6, writeFileSync as
|
|
15100
|
+
import { mkdtempSync as mkdtempSync2, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "node:fs";
|
|
15050
15101
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
15051
15102
|
import { join as join17 } from "node:path";
|
|
15052
15103
|
function emptySuiteDiagnostics() {
|
|
@@ -15132,7 +15183,7 @@ function runCapturedProcessSync(executable, args, opts) {
|
|
|
15132
15183
|
const configFile = join17(stateDir2, "config.json");
|
|
15133
15184
|
const backstop = opts.backstopMs ?? 3e4;
|
|
15134
15185
|
try {
|
|
15135
|
-
|
|
15186
|
+
writeFileSync7(
|
|
15136
15187
|
configFile,
|
|
15137
15188
|
JSON.stringify({
|
|
15138
15189
|
executable,
|
|
@@ -15420,7 +15471,7 @@ if (child) {
|
|
|
15420
15471
|
// src/verifier-backend.ts
|
|
15421
15472
|
import { createHash as createHash11, randomUUID } from "node:crypto";
|
|
15422
15473
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
15423
|
-
import { accessSync as accessSync2, constants as constants4, readFileSync as
|
|
15474
|
+
import { accessSync as accessSync2, constants as constants4, readFileSync as readFileSync10, realpathSync as realpathSync7, statSync as statSync4 } from "node:fs";
|
|
15424
15475
|
import { delimiter as delimiter2, dirname as dirname7, join as join18, resolve as resolve8 } from "node:path";
|
|
15425
15476
|
function identity() {
|
|
15426
15477
|
const uid = typeof process.getuid === "function" ? process.getuid() : null;
|
|
@@ -15465,7 +15516,7 @@ function findExecutable(name) {
|
|
|
15465
15516
|
return null;
|
|
15466
15517
|
}
|
|
15467
15518
|
function fileSha256(path) {
|
|
15468
|
-
return createHash11("sha256").update(
|
|
15519
|
+
return createHash11("sha256").update(readFileSync10(path)).digest("hex");
|
|
15469
15520
|
}
|
|
15470
15521
|
function engineClientEnv() {
|
|
15471
15522
|
return {
|
|
@@ -15899,7 +15950,7 @@ var init_verifier_backend = __esm({
|
|
|
15899
15950
|
// src/verification-state.ts
|
|
15900
15951
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
15901
15952
|
import { createHash as createHash12 } from "node:crypto";
|
|
15902
|
-
import { mkdirSync as mkdirSync8, readFileSync as
|
|
15953
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync11, rmSync as rmSync7, writeFileSync as writeFileSync8 } from "node:fs";
|
|
15903
15954
|
import { dirname as dirname8, join as join19 } from "node:path";
|
|
15904
15955
|
function git2(args, cwd) {
|
|
15905
15956
|
return execFileSync8("git", args, {
|
|
@@ -15958,7 +16009,7 @@ function interventionWiring(cwd) {
|
|
|
15958
16009
|
return sources.map(([source, path]) => {
|
|
15959
16010
|
let parsed;
|
|
15960
16011
|
try {
|
|
15961
|
-
parsed = JSON.parse(
|
|
16012
|
+
parsed = JSON.parse(readFileSync11(path, "utf8"));
|
|
15962
16013
|
} catch {
|
|
15963
16014
|
return { source, present: false };
|
|
15964
16015
|
}
|
|
@@ -16043,7 +16094,7 @@ function recordVerification(cwd, inputs, treeFingerprintValue) {
|
|
|
16043
16094
|
binding
|
|
16044
16095
|
};
|
|
16045
16096
|
mkdirSync8(dirname8(path), { recursive: true });
|
|
16046
|
-
|
|
16097
|
+
writeFileSync8(path, JSON.stringify(record) + "\n");
|
|
16047
16098
|
return true;
|
|
16048
16099
|
}
|
|
16049
16100
|
function invalidateVerificationRecordIfCurrent(cwd) {
|
|
@@ -16111,7 +16162,7 @@ function readVerificationRecord(cwd) {
|
|
|
16111
16162
|
if (!path) return null;
|
|
16112
16163
|
let raw;
|
|
16113
16164
|
try {
|
|
16114
|
-
raw =
|
|
16165
|
+
raw = readFileSync11(path, "utf8");
|
|
16115
16166
|
} catch {
|
|
16116
16167
|
return null;
|
|
16117
16168
|
}
|
|
@@ -16141,7 +16192,7 @@ function beginVerifying(cwd) {
|
|
|
16141
16192
|
started_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
16142
16193
|
};
|
|
16143
16194
|
mkdirSync8(dirname8(path), { recursive: true });
|
|
16144
|
-
|
|
16195
|
+
writeFileSync8(path, JSON.stringify(marker) + "\n");
|
|
16145
16196
|
return true;
|
|
16146
16197
|
} catch {
|
|
16147
16198
|
return false;
|
|
@@ -16160,7 +16211,7 @@ function readVerifyingMarker(cwd) {
|
|
|
16160
16211
|
if (!path) return null;
|
|
16161
16212
|
let parsed;
|
|
16162
16213
|
try {
|
|
16163
|
-
parsed = JSON.parse(
|
|
16214
|
+
parsed = JSON.parse(readFileSync11(path, "utf8"));
|
|
16164
16215
|
} catch {
|
|
16165
16216
|
return null;
|
|
16166
16217
|
}
|
|
@@ -16294,7 +16345,7 @@ var init_verification_state = __esm({
|
|
|
16294
16345
|
|
|
16295
16346
|
// src/verification-receipt.ts
|
|
16296
16347
|
import { createHash as createHash13 } from "node:crypto";
|
|
16297
|
-
import { mkdirSync as mkdirSync9, rmSync as rmSync8, writeFileSync as
|
|
16348
|
+
import { mkdirSync as mkdirSync9, rmSync as rmSync8, writeFileSync as writeFileSync9 } from "node:fs";
|
|
16298
16349
|
import { dirname as dirname9, join as join20 } from "node:path";
|
|
16299
16350
|
function isRecord5(v) {
|
|
16300
16351
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
@@ -16341,7 +16392,7 @@ function storeReceipt(cwd, receipt) {
|
|
|
16341
16392
|
if (!path) return false;
|
|
16342
16393
|
try {
|
|
16343
16394
|
mkdirSync9(dirname9(path), { recursive: true });
|
|
16344
|
-
|
|
16395
|
+
writeFileSync9(path, JSON.stringify(receipt) + "\n");
|
|
16345
16396
|
return true;
|
|
16346
16397
|
} catch {
|
|
16347
16398
|
return false;
|
|
@@ -16524,7 +16575,7 @@ var init_verification_receipt = __esm({
|
|
|
16524
16575
|
// src/cli/verify.ts
|
|
16525
16576
|
import { execFileSync as execFileSync9, spawnSync as spawnSync3 } from "node:child_process";
|
|
16526
16577
|
import { createHash as createHash14 } from "node:crypto";
|
|
16527
|
-
import { chmodSync as chmodSync2, cpSync, lstatSync as lstatSync10, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync3, readFileSync as
|
|
16578
|
+
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 writeFileSync10, existsSync as existsSync10 } from "node:fs";
|
|
16528
16579
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
16529
16580
|
import { dirname as dirname10, isAbsolute as isAbsolute11, join as join21, relative as relative6, resolve as resolve9, sep as sep4 } from "node:path";
|
|
16530
16581
|
function oracleAssuranceReport() {
|
|
@@ -16719,8 +16770,8 @@ function probeFilesystemCaseSensitivity(dir) {
|
|
|
16719
16770
|
const upper = join21(dir, ".tw-case-probe-A");
|
|
16720
16771
|
const lower = join21(dir, ".tw-case-probe-a");
|
|
16721
16772
|
try {
|
|
16722
|
-
|
|
16723
|
-
return !
|
|
16773
|
+
writeFileSync10(upper, "", { flag: "wx" });
|
|
16774
|
+
return !existsSync10(lower);
|
|
16724
16775
|
} finally {
|
|
16725
16776
|
rmSync9(upper, { force: true });
|
|
16726
16777
|
}
|
|
@@ -16784,7 +16835,7 @@ function overlayDigest(dest, paths) {
|
|
|
16784
16835
|
try {
|
|
16785
16836
|
const st = lstatSync10(p);
|
|
16786
16837
|
h.update(String(st.mode));
|
|
16787
|
-
h.update(st.isSymbolicLink() ? readlinkSync3(p) :
|
|
16838
|
+
h.update(st.isSymbolicLink() ? readlinkSync3(p) : readFileSync12(p));
|
|
16788
16839
|
} catch {
|
|
16789
16840
|
h.update("<gone>");
|
|
16790
16841
|
}
|
|
@@ -16822,7 +16873,7 @@ function overlayPristine(cwd, base, dest, policy, cmd, dependencyRoot, caseSensi
|
|
|
16822
16873
|
safeSymlink(target, out3, dest, `the base's ${e.path}`);
|
|
16823
16874
|
restoredLinks.push({ path: e.path, out: out3, target });
|
|
16824
16875
|
} else {
|
|
16825
|
-
|
|
16876
|
+
writeFileSync10(out3, content);
|
|
16826
16877
|
chmodSync2(out3, parseInt(e.mode.slice(-4), 8) & 511);
|
|
16827
16878
|
}
|
|
16828
16879
|
restored.push(e.path);
|
|
@@ -16847,7 +16898,7 @@ function suiteEnv(scratch) {
|
|
|
16847
16898
|
}
|
|
16848
16899
|
const userRc = join21(scratch, "npmrc-user");
|
|
16849
16900
|
const globalRc = join21(scratch, "npmrc-global");
|
|
16850
|
-
for (const f of [userRc, globalRc])
|
|
16901
|
+
for (const f of [userRc, globalRc]) writeFileSync10(f, "", { mode: 292 });
|
|
16851
16902
|
env.npm_config_userconfig = userRc;
|
|
16852
16903
|
env.npm_config_globalconfig = globalRc;
|
|
16853
16904
|
env.npm_config_node_options = " ";
|
|
@@ -17598,7 +17649,7 @@ var init_verify = __esm({
|
|
|
17598
17649
|
// src/cli/run.ts
|
|
17599
17650
|
import { execFileSync as execFileSync10, spawn, spawnSync as spawnSync4 } from "node:child_process";
|
|
17600
17651
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
17601
|
-
import { accessSync as accessSync3, constants as fsConstants, mkdtempSync as mkdtempSync4, readdirSync as readdirSync4, readFileSync as
|
|
17652
|
+
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 writeFileSync11 } from "node:fs";
|
|
17602
17653
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
17603
17654
|
import { dirname as dirname11, join as join22, resolve as resolve10 } from "node:path";
|
|
17604
17655
|
function authoritativeRunLifecyclePlatform(platform = process.platform) {
|
|
@@ -17695,7 +17746,7 @@ function runAgentSupervised(argv, cwd, budgetSecs, linuxPythonCandidates, lifecy
|
|
|
17695
17746
|
failure: trustedPython.reason ?? "trusted Linux python3 interpreter is unavailable"
|
|
17696
17747
|
};
|
|
17697
17748
|
}
|
|
17698
|
-
|
|
17749
|
+
writeFileSync11(agentEnvFile, JSON.stringify(process.env), { mode: 384 });
|
|
17699
17750
|
executable = trustedPython.path;
|
|
17700
17751
|
args = [
|
|
17701
17752
|
"-I",
|
|
@@ -17752,7 +17803,7 @@ function runAgentSupervised(argv, cwd, budgetSecs, linuxPythonCandidates, lifecy
|
|
|
17752
17803
|
}
|
|
17753
17804
|
let state = {};
|
|
17754
17805
|
try {
|
|
17755
|
-
state = JSON.parse(
|
|
17806
|
+
state = JSON.parse(readFileSync13(resultFile, "utf8"));
|
|
17756
17807
|
} catch {
|
|
17757
17808
|
return {
|
|
17758
17809
|
exit: 1,
|
|
@@ -17796,7 +17847,7 @@ function observerExited(pid) {
|
|
|
17796
17847
|
if (!pidAlive4(pid)) return true;
|
|
17797
17848
|
if (process.platform !== "linux") return false;
|
|
17798
17849
|
try {
|
|
17799
|
-
const stat =
|
|
17850
|
+
const stat = readFileSync13(`/proc/${pid}/stat`, "utf8");
|
|
17800
17851
|
const state = stat.slice(stat.lastIndexOf(")") + 2).split(" ")[0];
|
|
17801
17852
|
return state === "Z" || state === "X";
|
|
17802
17853
|
} catch (e) {
|
|
@@ -17918,7 +17969,7 @@ function git4(args, cwd) {
|
|
|
17918
17969
|
}
|
|
17919
17970
|
function nowTicks() {
|
|
17920
17971
|
try {
|
|
17921
|
-
return Math.floor(parseFloat(
|
|
17972
|
+
return Math.floor(parseFloat(readFileSync13("/proc/uptime", "utf8").split(" ")[0]) * 100);
|
|
17922
17973
|
} catch {
|
|
17923
17974
|
return Number.POSITIVE_INFINITY;
|
|
17924
17975
|
}
|
|
@@ -17941,7 +17992,7 @@ function survivorsHoldingTree(cwd, spawnedAfterTicks) {
|
|
|
17941
17992
|
const n2 = Number(pid);
|
|
17942
17993
|
if (n2 === process.pid) continue;
|
|
17943
17994
|
try {
|
|
17944
|
-
const stat =
|
|
17995
|
+
const stat = readFileSync13(`/proc/${pid}/stat`, "utf8");
|
|
17945
17996
|
const startTicks = Number(stat.slice(stat.lastIndexOf(")") + 2).split(" ")[19]);
|
|
17946
17997
|
if (!Number.isFinite(startTicks) || startTicks < spawnedAfterTicks) continue;
|
|
17947
17998
|
} catch {
|
|
@@ -18514,7 +18565,7 @@ raise SystemExit(0)
|
|
|
18514
18565
|
|
|
18515
18566
|
// src/cli/doctor.ts
|
|
18516
18567
|
import { execFileSync as execFileSync11 } from "node:child_process";
|
|
18517
|
-
import { existsSync as
|
|
18568
|
+
import { existsSync as existsSync11, readFileSync as readFileSync14, readdirSync as readdirSync5 } from "node:fs";
|
|
18518
18569
|
import { join as join23, resolve as resolve11 } from "node:path";
|
|
18519
18570
|
function lifecyclePlatformCheck(platform = process.platform, linuxPython = platform === "linux" ? trustedLinuxPython() : null) {
|
|
18520
18571
|
if (platform === "linux") {
|
|
@@ -18570,10 +18621,10 @@ function wiringState(status, authority) {
|
|
|
18570
18621
|
return authority ? "BROKEN" : "WARN";
|
|
18571
18622
|
}
|
|
18572
18623
|
function pinsInFile(path) {
|
|
18573
|
-
if (!
|
|
18624
|
+
if (!existsSync11(path)) return [];
|
|
18574
18625
|
let src = "";
|
|
18575
18626
|
try {
|
|
18576
|
-
src =
|
|
18627
|
+
src = readFileSync14(path, "utf8");
|
|
18577
18628
|
} catch {
|
|
18578
18629
|
return [];
|
|
18579
18630
|
}
|
|
@@ -18594,13 +18645,13 @@ function workflowPermissionCheck(cwd, workflowRels = [".github/workflows/tamperw
|
|
|
18594
18645
|
const warnings = [];
|
|
18595
18646
|
for (const rel of workflowRels) {
|
|
18596
18647
|
const path = resolve11(cwd, rel);
|
|
18597
|
-
if (!
|
|
18648
|
+
if (!existsSync11(path)) {
|
|
18598
18649
|
broken.push(`${rel} is missing`);
|
|
18599
18650
|
continue;
|
|
18600
18651
|
}
|
|
18601
18652
|
let doc;
|
|
18602
18653
|
try {
|
|
18603
|
-
doc = yaml.parse(
|
|
18654
|
+
doc = yaml.parse(readFileSync14(path, "utf8"));
|
|
18604
18655
|
} catch (e) {
|
|
18605
18656
|
broken.push(`${rel} is not valid YAML (${e instanceof Error ? e.message : String(e)})`);
|
|
18606
18657
|
continue;
|
|
@@ -18999,7 +19050,7 @@ function diagnose(opts = {}) {
|
|
|
18999
19050
|
} else {
|
|
19000
19051
|
const workflowDirRel = ".github/workflows";
|
|
19001
19052
|
const workflowDir = resolve11(cwd, workflowDirRel);
|
|
19002
|
-
if (!
|
|
19053
|
+
if (!existsSync11(workflowDir)) {
|
|
19003
19054
|
return fail("ci-verifier", `${workflowDirRel}: workflow directory does not exist`);
|
|
19004
19055
|
}
|
|
19005
19056
|
let entries;
|
|
@@ -19019,12 +19070,12 @@ function diagnose(opts = {}) {
|
|
|
19019
19070
|
const authorityWorkflows = [];
|
|
19020
19071
|
for (const workflowRel of workflowRels) {
|
|
19021
19072
|
const workflowPath = resolve11(cwd, workflowRel);
|
|
19022
|
-
if (!
|
|
19073
|
+
if (!existsSync11(workflowPath)) {
|
|
19023
19074
|
return fail("ci-verifier", `${workflowRel}: workflow does not exist`);
|
|
19024
19075
|
}
|
|
19025
19076
|
let doc;
|
|
19026
19077
|
try {
|
|
19027
|
-
doc = yaml.parse(
|
|
19078
|
+
doc = yaml.parse(readFileSync14(workflowPath, "utf8"));
|
|
19028
19079
|
} catch (e) {
|
|
19029
19080
|
return fail(
|
|
19030
19081
|
"ci-verifier",
|
|
@@ -19335,9 +19386,9 @@ var init_status2 = __esm({
|
|
|
19335
19386
|
// src/cli/trace-verify.ts
|
|
19336
19387
|
import { execFileSync as execFileSync12, spawnSync as spawnSync5 } from "node:child_process";
|
|
19337
19388
|
import {
|
|
19338
|
-
existsSync as
|
|
19389
|
+
existsSync as existsSync12,
|
|
19339
19390
|
mkdtempSync as mkdtempSync5,
|
|
19340
|
-
readFileSync as
|
|
19391
|
+
readFileSync as readFileSync15,
|
|
19341
19392
|
readdirSync as readdirSync6,
|
|
19342
19393
|
realpathSync as realpathSync9,
|
|
19343
19394
|
rmSync as rmSync11,
|
|
@@ -19594,7 +19645,7 @@ function materializeBase(base, cwd, dest) {
|
|
|
19594
19645
|
}
|
|
19595
19646
|
const hostModules = join24(cwd, "node_modules");
|
|
19596
19647
|
const tracedModules = join24(dest, "node_modules");
|
|
19597
|
-
if (
|
|
19648
|
+
if (existsSync12(hostModules) && !existsSync12(tracedModules)) {
|
|
19598
19649
|
symlinkSync2(resolve12(hostModules), tracedModules, "dir");
|
|
19599
19650
|
}
|
|
19600
19651
|
}
|
|
@@ -19651,7 +19702,7 @@ function straceOnce(root, command, budget) {
|
|
|
19651
19702
|
}
|
|
19652
19703
|
);
|
|
19653
19704
|
const logs = traced.error ? [] : traceFiles(prefix);
|
|
19654
|
-
const accesses = logs.flatMap((path) => parseStraceFileAccess(
|
|
19705
|
+
const accesses = logs.flatMap((path) => parseStraceFileAccess(readFileSync15(path, "utf8"), TRACE_ROOT));
|
|
19655
19706
|
const raw = {
|
|
19656
19707
|
spawnError: traced.error ? traced.error.message : null,
|
|
19657
19708
|
status: traced.status,
|
|
@@ -19906,7 +19957,7 @@ var init_immutable = __esm({
|
|
|
19906
19957
|
});
|
|
19907
19958
|
|
|
19908
19959
|
// src/runtimes.ts
|
|
19909
|
-
import { existsSync as
|
|
19960
|
+
import { existsSync as existsSync13, readFileSync as readFileSync16 } from "node:fs";
|
|
19910
19961
|
import { join as join25 } from "node:path";
|
|
19911
19962
|
function isRecord6(x) {
|
|
19912
19963
|
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
@@ -19936,8 +19987,8 @@ function claudeSettingsBeyondTamperward(cwd) {
|
|
|
19936
19987
|
const path = join25(cwd, ".claude", "settings.json");
|
|
19937
19988
|
let raw;
|
|
19938
19989
|
try {
|
|
19939
|
-
if (!
|
|
19940
|
-
raw =
|
|
19990
|
+
if (!existsSync13(path)) return false;
|
|
19991
|
+
raw = readFileSync16(path, "utf8");
|
|
19941
19992
|
} catch {
|
|
19942
19993
|
return false;
|
|
19943
19994
|
}
|
|
@@ -19963,7 +20014,7 @@ function detectRuntimes(cwd) {
|
|
|
19963
20014
|
for (const rt of KNOWN_RUNTIMES) {
|
|
19964
20015
|
const marker = rt.markers.find((m) => {
|
|
19965
20016
|
try {
|
|
19966
|
-
return
|
|
20017
|
+
return existsSync13(join25(cwd, m));
|
|
19967
20018
|
} catch {
|
|
19968
20019
|
return false;
|
|
19969
20020
|
}
|
|
@@ -20988,7 +21039,7 @@ var init_adapter3 = __esm({
|
|
|
20988
21039
|
|
|
20989
21040
|
// src/adapters/copilot-sdk/changes.ts
|
|
20990
21041
|
import { execFileSync as execFileSync13 } from "node:child_process";
|
|
20991
|
-
import { mkdtempSync as mkdtempSync6, writeFileSync as
|
|
21042
|
+
import { mkdtempSync as mkdtempSync6, writeFileSync as writeFileSync12, readFileSync as readFileSync17, rmSync as rmSync12, existsSync as existsSync14, realpathSync as realpathSync10 } from "node:fs";
|
|
20992
21043
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
20993
21044
|
import { basename as basename5, dirname as dirname12, isAbsolute as isAbsolute16, relative as relative11, resolve as resolve15, join as join26 } from "node:path";
|
|
20994
21045
|
function asStr4(v) {
|
|
@@ -21007,7 +21058,7 @@ function canonicalContainedTarget(abs, root) {
|
|
|
21007
21058
|
}
|
|
21008
21059
|
let dir = abs;
|
|
21009
21060
|
const tail = [];
|
|
21010
|
-
while (!
|
|
21061
|
+
while (!existsSync14(dir)) {
|
|
21011
21062
|
const parent = dirname12(dir);
|
|
21012
21063
|
if (parent === dir) break;
|
|
21013
21064
|
tail.unshift(basename5(dir));
|
|
@@ -21065,9 +21116,9 @@ function reconstructAfterViaGit(rawDiff, display2, before, isCreate) {
|
|
|
21065
21116
|
const dir = mkdtempSync6(join26(tmpdir7(), "hf-sdk-apply-"));
|
|
21066
21117
|
try {
|
|
21067
21118
|
const targetPath = join26(dir, TARGET);
|
|
21068
|
-
if (op !== "create")
|
|
21119
|
+
if (op !== "create") writeFileSync12(targetPath, before ?? "");
|
|
21069
21120
|
const patchPath = join26(dir, "change.patch");
|
|
21070
|
-
|
|
21121
|
+
writeFileSync12(patchPath, patch);
|
|
21071
21122
|
const git8 = (extra) => execFileSync13("git", ["apply", ...extra, patchPath], {
|
|
21072
21123
|
cwd: dir,
|
|
21073
21124
|
encoding: "utf8",
|
|
@@ -21082,7 +21133,7 @@ function reconstructAfterViaGit(rawDiff, display2, before, isCreate) {
|
|
|
21082
21133
|
if (statPath !== TARGET) throw new Error(`write diff reconstructs a different file (${statPath}) than the bound target`);
|
|
21083
21134
|
git8(["--check"]);
|
|
21084
21135
|
git8([]);
|
|
21085
|
-
return op === "delete" ? null :
|
|
21136
|
+
return op === "delete" ? null : readFileSync17(targetPath, "utf8");
|
|
21086
21137
|
} catch (e) {
|
|
21087
21138
|
throw new Error(`could not reconstruct the write to ${display2} from its diff via git apply: ${e instanceof Error ? e.message : String(e)}`);
|
|
21088
21139
|
} finally {
|
|
@@ -21835,7 +21886,7 @@ var init_runtime_qualification = __esm({
|
|
|
21835
21886
|
|
|
21836
21887
|
// src/cli/runtime.ts
|
|
21837
21888
|
import { execFileSync as execFileSync14 } from "node:child_process";
|
|
21838
|
-
import { existsSync as
|
|
21889
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync18, writeFileSync as writeFileSync13 } from "node:fs";
|
|
21839
21890
|
import { join as join27, dirname as dirname13 } from "node:path";
|
|
21840
21891
|
function storePath(cwd) {
|
|
21841
21892
|
const dir = gitDir(cwd);
|
|
@@ -21843,9 +21894,9 @@ function storePath(cwd) {
|
|
|
21843
21894
|
}
|
|
21844
21895
|
function readStore(cwd) {
|
|
21845
21896
|
const path = storePath(cwd);
|
|
21846
|
-
if (!path || !
|
|
21897
|
+
if (!path || !existsSync15(path)) return null;
|
|
21847
21898
|
try {
|
|
21848
|
-
const parsed = JSON.parse(
|
|
21899
|
+
const parsed = JSON.parse(readFileSync18(path, "utf8"));
|
|
21849
21900
|
if (parsed && typeof parsed === "object" && parsed.records && typeof parsed.records === "object") return parsed;
|
|
21850
21901
|
} catch {
|
|
21851
21902
|
return null;
|
|
@@ -21976,7 +22027,7 @@ function writeRecord(cwd, id, report2) {
|
|
|
21976
22027
|
store.updated_at = report2.timestamp;
|
|
21977
22028
|
try {
|
|
21978
22029
|
mkdirSync11(dirname13(path), { recursive: true });
|
|
21979
|
-
|
|
22030
|
+
writeFileSync13(path, JSON.stringify(store, null, 2) + "\n", { mode: 384 });
|
|
21980
22031
|
return true;
|
|
21981
22032
|
} catch {
|
|
21982
22033
|
return false;
|
|
@@ -22014,9 +22065,9 @@ function resolveHookConfigHash(canonicalId, cwd) {
|
|
|
22014
22065
|
"github-copilot-cli": join27(cwd, ".github", "hooks", "tamperward.json")
|
|
22015
22066
|
};
|
|
22016
22067
|
const file = files[canonicalId];
|
|
22017
|
-
if (!file || !
|
|
22068
|
+
if (!file || !existsSync15(file)) return null;
|
|
22018
22069
|
try {
|
|
22019
|
-
const raw =
|
|
22070
|
+
const raw = readFileSync18(file, "utf8");
|
|
22020
22071
|
let hooks = raw;
|
|
22021
22072
|
try {
|
|
22022
22073
|
const parsed = JSON.parse(raw);
|
|
@@ -22295,7 +22346,7 @@ var init_runtime = __esm({
|
|
|
22295
22346
|
|
|
22296
22347
|
// src/cli/onboard.ts
|
|
22297
22348
|
import { execFileSync as execFileSync15 } from "node:child_process";
|
|
22298
|
-
import { lstatSync as lstatSync11, mkdtempSync as mkdtempSync7, readFileSync as
|
|
22349
|
+
import { lstatSync as lstatSync11, mkdtempSync as mkdtempSync7, readFileSync as readFileSync19, realpathSync as realpathSync11, rmSync as rmSync13 } from "node:fs";
|
|
22299
22350
|
import { tmpdir as tmpdir8 } from "node:os";
|
|
22300
22351
|
import { join as join28, relative as relative12, resolve as resolve16, sep as sep6 } from "node:path";
|
|
22301
22352
|
import { createInterface } from "node:readline";
|
|
@@ -22368,7 +22419,7 @@ function writeVerifyCommand(cwd, command) {
|
|
|
22368
22419
|
return `${POLICY_FILE} is not a regular file; refusing to follow or replace a symlink or special file`;
|
|
22369
22420
|
}
|
|
22370
22421
|
const mode = existingMode(path, 420);
|
|
22371
|
-
const original = kind === "file" ?
|
|
22422
|
+
const original = kind === "file" ? readFileSync19(path, "utf8") : null;
|
|
22372
22423
|
let next;
|
|
22373
22424
|
try {
|
|
22374
22425
|
const doc = parseDocument(original && original.trim() ? original : "version: 1\n");
|
|
@@ -23023,7 +23074,7 @@ var init_capture = __esm({
|
|
|
23023
23074
|
|
|
23024
23075
|
// src/research/manifest.ts
|
|
23025
23076
|
import { createHash as createHash16 } from "node:crypto";
|
|
23026
|
-
import { readFileSync as
|
|
23077
|
+
import { readFileSync as readFileSync20 } from "node:fs";
|
|
23027
23078
|
import { dirname as dirname14, resolve as resolve18 } from "node:path";
|
|
23028
23079
|
function taskFrom(raw, index, manifestDir) {
|
|
23029
23080
|
const where = `task #${index + 1}`;
|
|
@@ -23057,7 +23108,7 @@ function readManifest(path) {
|
|
|
23057
23108
|
const abs = resolve18(path);
|
|
23058
23109
|
let bytes;
|
|
23059
23110
|
try {
|
|
23060
|
-
bytes =
|
|
23111
|
+
bytes = readFileSync20(abs);
|
|
23061
23112
|
} catch (e) {
|
|
23062
23113
|
throw new ResearchError(`cannot read task manifest ${abs}: ${e instanceof Error ? e.message : String(e)}`);
|
|
23063
23114
|
}
|
|
@@ -23476,7 +23527,7 @@ var init_record = __esm({
|
|
|
23476
23527
|
// src/research/run.ts
|
|
23477
23528
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
23478
23529
|
import { execFileSync as execFileSync16 } from "node:child_process";
|
|
23479
|
-
import { closeSync as closeSync5, existsSync as
|
|
23530
|
+
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 writeFileSync14, writeSync as writeSync2 } from "node:fs";
|
|
23480
23531
|
import { hostname } from "node:os";
|
|
23481
23532
|
import { join as join29, resolve as resolve19 } from "node:path";
|
|
23482
23533
|
function git7(args, cwd) {
|
|
@@ -23490,7 +23541,7 @@ function researchLockPath(ledger) {
|
|
|
23490
23541
|
}
|
|
23491
23542
|
function readLockOwner(path) {
|
|
23492
23543
|
try {
|
|
23493
|
-
const parsed = JSON.parse(
|
|
23544
|
+
const parsed = JSON.parse(readFileSync21(path, "utf8"));
|
|
23494
23545
|
if (!isRecord(parsed) || typeof parsed.pid !== "number" || !Number.isInteger(parsed.pid) || parsed.pid <= 0) return null;
|
|
23495
23546
|
if (typeof parsed.host !== "string" || typeof parsed.started_at !== "string" || typeof parsed.token !== "string") return null;
|
|
23496
23547
|
return { pid: parsed.pid, host: parsed.host, started_at: parsed.started_at, token: parsed.token };
|
|
@@ -23513,7 +23564,7 @@ function lockHolder(path) {
|
|
|
23513
23564
|
function acquireResearchLock(ledger, breakStaleLock = false) {
|
|
23514
23565
|
mkdirSync12(ledger, { recursive: true });
|
|
23515
23566
|
const path = researchLockPath(ledger);
|
|
23516
|
-
if (breakStaleLock &&
|
|
23567
|
+
if (breakStaleLock && existsSync16(path)) {
|
|
23517
23568
|
const owner2 = readLockOwner(path);
|
|
23518
23569
|
if (!owner2) {
|
|
23519
23570
|
throw new ResearchError(`research output ${ledger} has an unreadable lock at ${path}; verify no run is active, then remove it deliberately`);
|
|
@@ -23557,7 +23608,7 @@ function acquireResearchLock(ledger, breakStaleLock = false) {
|
|
|
23557
23608
|
let fd = -1;
|
|
23558
23609
|
try {
|
|
23559
23610
|
fd = openSync5(path, "wx", 384);
|
|
23560
|
-
|
|
23611
|
+
writeSync2(fd, text);
|
|
23561
23612
|
closeSync5(fd);
|
|
23562
23613
|
fd = -1;
|
|
23563
23614
|
} catch (e) {
|
|
@@ -23575,7 +23626,7 @@ function acquireResearchLock(ledger, breakStaleLock = false) {
|
|
|
23575
23626
|
if (released) return;
|
|
23576
23627
|
released = true;
|
|
23577
23628
|
try {
|
|
23578
|
-
if (
|
|
23629
|
+
if (readFileSync21(path, "utf8") === text) unlinkSync(path);
|
|
23579
23630
|
} catch {
|
|
23580
23631
|
}
|
|
23581
23632
|
}
|
|
@@ -23584,7 +23635,7 @@ function acquireResearchLock(ledger, breakStaleLock = false) {
|
|
|
23584
23635
|
function resumableRecord(path, expected) {
|
|
23585
23636
|
let raw;
|
|
23586
23637
|
try {
|
|
23587
|
-
raw = JSON.parse(
|
|
23638
|
+
raw = JSON.parse(readFileSync21(path, "utf8"));
|
|
23588
23639
|
} catch (e) {
|
|
23589
23640
|
throw new ResearchError(`ledger record ${path} is malformed (${errorMessage(e).split("\n")[0]}); remove it to regenerate the pair, or use a new --out`);
|
|
23590
23641
|
}
|
|
@@ -23621,7 +23672,7 @@ function resumableRecord(path, expected) {
|
|
|
23621
23672
|
}
|
|
23622
23673
|
function writeRecordAtomically(path, text) {
|
|
23623
23674
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
23624
|
-
|
|
23675
|
+
writeFileSync14(tmp, text);
|
|
23625
23676
|
renameSync4(tmp, path);
|
|
23626
23677
|
}
|
|
23627
23678
|
function cloneArgs(repo, ws3) {
|
|
@@ -23886,7 +23937,7 @@ function runResearch(opts) {
|
|
|
23886
23937
|
try {
|
|
23887
23938
|
for (let pair = 1; pair <= pairs; pair++) {
|
|
23888
23939
|
const path = pairRecordPath(ledger, task.id, pair);
|
|
23889
|
-
if (!
|
|
23940
|
+
if (!existsSync16(path)) continue;
|
|
23890
23941
|
const existing = resumableRecord(path, {
|
|
23891
23942
|
task: task.id,
|
|
23892
23943
|
pair,
|
|
@@ -24006,7 +24057,7 @@ var init_run2 = __esm({
|
|
|
24006
24057
|
});
|
|
24007
24058
|
|
|
24008
24059
|
// src/research/ledger-files.ts
|
|
24009
|
-
import { closeSync as closeSync6, constants as constants5, fstatSync as fstatSync3, lstatSync as lstatSync12, openSync as openSync6, readFileSync as
|
|
24060
|
+
import { closeSync as closeSync6, constants as constants5, fstatSync as fstatSync3, lstatSync as lstatSync12, openSync as openSync6, readFileSync as readFileSync22, readdirSync as readdirSync7, realpathSync as realpathSync12 } from "node:fs";
|
|
24010
24061
|
import { join as join30, resolve as resolve20 } from "node:path";
|
|
24011
24062
|
function lstatOrNull(path) {
|
|
24012
24063
|
try {
|
|
@@ -24049,7 +24100,7 @@ function readRegularFile(path, realPairsDir, name) {
|
|
|
24049
24100
|
if (!opened.isFile() || !sameInode || opened.nlink !== 1) {
|
|
24050
24101
|
throw new ResearchError(`ledger record ${path} changed between listing and reading; refusing to read it`);
|
|
24051
24102
|
}
|
|
24052
|
-
return
|
|
24103
|
+
return readFileSync22(fd);
|
|
24053
24104
|
} finally {
|
|
24054
24105
|
closeSync6(fd);
|
|
24055
24106
|
}
|
|
@@ -24222,7 +24273,7 @@ var init_summarize = __esm({
|
|
|
24222
24273
|
|
|
24223
24274
|
// src/research/init.ts
|
|
24224
24275
|
import { createHash as createHash17 } from "node:crypto";
|
|
24225
|
-
import { existsSync as
|
|
24276
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync13, readFileSync as readFileSync23, writeFileSync as writeFileSync15 } from "node:fs";
|
|
24226
24277
|
import { basename as basename6, dirname as dirname15, resolve as resolve21 } from "node:path";
|
|
24227
24278
|
function idFrom(repo) {
|
|
24228
24279
|
const clean = repo.replace(/[\\/]$/, "").split(/[\\/]/).pop() || "task";
|
|
@@ -24234,7 +24285,7 @@ function createResearchManifest(opts) {
|
|
|
24234
24285
|
if (!opts.prompt) throw new ResearchError("research init requires --prompt");
|
|
24235
24286
|
if (!opts.verifyCommand) throw new ResearchError("research init requires --verify-command");
|
|
24236
24287
|
const out3 = resolve21(opts.out);
|
|
24237
|
-
if (
|
|
24288
|
+
if (existsSync17(out3)) throw new ResearchError(`research init refuses to overwrite ${out3}; choose a new path`);
|
|
24238
24289
|
const id = opts.id ?? idFrom(opts.repo);
|
|
24239
24290
|
if (!/^[A-Za-z0-9._-]+$/.test(id)) throw new ResearchError(`research init id must match [A-Za-z0-9._-] (got "${id}")`);
|
|
24240
24291
|
if (opts.verifyBudget !== void 0 && (!Number.isFinite(opts.verifyBudget) || opts.verifyBudget <= 0)) {
|
|
@@ -24252,7 +24303,7 @@ function createResearchManifest(opts) {
|
|
|
24252
24303
|
};
|
|
24253
24304
|
const text = JSON.stringify(doc, null, 2) + "\n";
|
|
24254
24305
|
mkdirSync13(dirname15(out3), { recursive: true });
|
|
24255
|
-
|
|
24306
|
+
writeFileSync15(out3, text, { flag: "wx", mode: 384 });
|
|
24256
24307
|
const parsed = readManifest(out3);
|
|
24257
24308
|
if (parsed.tasks.length !== 1 || parsed.tasks[0].id !== id) throw new ResearchError(`research init wrote an invalid manifest ${out3}`);
|
|
24258
24309
|
return out3;
|
|
@@ -24274,7 +24325,7 @@ function runResearchInit(opts) {
|
|
|
24274
24325
|
}
|
|
24275
24326
|
}
|
|
24276
24327
|
function requireHash(path) {
|
|
24277
|
-
return createHash17("sha256").update(
|
|
24328
|
+
return createHash17("sha256").update(readFileSync23(path)).digest("hex");
|
|
24278
24329
|
}
|
|
24279
24330
|
var init_init2 = __esm({
|
|
24280
24331
|
"src/research/init.ts"() {
|
|
@@ -24342,7 +24393,7 @@ var init_report2 = __esm({
|
|
|
24342
24393
|
import { createHash as createHash18 } from "node:crypto";
|
|
24343
24394
|
import { isDeepStrictEqual } from "node:util";
|
|
24344
24395
|
import { gzipSync, gunzipSync } from "node:zlib";
|
|
24345
|
-
import { mkdirSync as mkdirSync14, readFileSync as
|
|
24396
|
+
import { mkdirSync as mkdirSync14, readFileSync as readFileSync24, writeFileSync as writeFileSync16 } from "node:fs";
|
|
24346
24397
|
import { dirname as dirname16, resolve as resolve22 } from "node:path";
|
|
24347
24398
|
function octal(value, width) {
|
|
24348
24399
|
return value.toString(8).padStart(width - 1, "0") + "\0";
|
|
@@ -24448,7 +24499,7 @@ function jsonBytes(value) {
|
|
|
24448
24499
|
function validateResearchBundle(path) {
|
|
24449
24500
|
let files;
|
|
24450
24501
|
try {
|
|
24451
|
-
files = parseTar(gunzipSync(
|
|
24502
|
+
files = parseTar(gunzipSync(readFileSync24(resolve22(path))));
|
|
24452
24503
|
} catch (e) {
|
|
24453
24504
|
throw new ResearchError(`cannot read research bundle ${path}: ${e instanceof Error ? e.message : String(e)}`);
|
|
24454
24505
|
}
|
|
@@ -24518,7 +24569,7 @@ function createResearchBundle(opts) {
|
|
|
24518
24569
|
const { records, entries } = packagedRecords(ledger);
|
|
24519
24570
|
const summary = summarizeRecords(records);
|
|
24520
24571
|
if (opts.manifest) {
|
|
24521
|
-
const manifest =
|
|
24572
|
+
const manifest = readFileSync24(resolve22(opts.manifest));
|
|
24522
24573
|
const sha3 = createHash18("sha256").update(manifest).digest("hex");
|
|
24523
24574
|
if (sha3 !== summary.manifest_sha256) throw new ResearchError(`manifest sha256 ${sha3} does not match ledger ${summary.manifest_sha256}`);
|
|
24524
24575
|
entries.push({ name: "manifest.json", bytes: manifest });
|
|
@@ -24542,7 +24593,7 @@ function createResearchBundle(opts) {
|
|
|
24542
24593
|
entries.push({ name: "provenance.json", bytes: jsonBytes(provenance) });
|
|
24543
24594
|
const out3 = resolve22(opts.out);
|
|
24544
24595
|
mkdirSync14(dirname16(out3), { recursive: true });
|
|
24545
|
-
|
|
24596
|
+
writeFileSync16(out3, gzipSync(makeTar(entries)), { flag: "wx", mode: 384 });
|
|
24546
24597
|
return out3;
|
|
24547
24598
|
}
|
|
24548
24599
|
function runResearchBundle(opts) {
|
|
@@ -24689,7 +24740,7 @@ var init_research = __esm({
|
|
|
24689
24740
|
});
|
|
24690
24741
|
|
|
24691
24742
|
// src/cli/receipt.ts
|
|
24692
|
-
import { appendFileSync as
|
|
24743
|
+
import { appendFileSync as appendFileSync3, readFileSync as readFileSync25, writeFileSync as writeFileSync17 } from "node:fs";
|
|
24693
24744
|
function parseReceipt(args) {
|
|
24694
24745
|
const [sub, ...rest] = args;
|
|
24695
24746
|
const exportOpts = {};
|
|
@@ -24791,7 +24842,7 @@ function runReceiptExport(opts = {}) {
|
|
|
24791
24842
|
const serialized = JSON.stringify(receipt) + "\n";
|
|
24792
24843
|
if (opts.out) {
|
|
24793
24844
|
try {
|
|
24794
|
-
|
|
24845
|
+
writeFileSync17(opts.out, serialized);
|
|
24795
24846
|
} catch (e) {
|
|
24796
24847
|
process.stderr.write(`tamperward: could not write receipt to ${opts.out} (${e instanceof Error ? e.message : String(e)})
|
|
24797
24848
|
`);
|
|
@@ -24816,7 +24867,7 @@ function ciAdjudicate(cwd, opts) {
|
|
|
24816
24867
|
if (opts.ciResult !== void 0) {
|
|
24817
24868
|
let doc;
|
|
24818
24869
|
try {
|
|
24819
|
-
doc = JSON.parse(
|
|
24870
|
+
doc = JSON.parse(readFileSync25(opts.ciResult, "utf8"));
|
|
24820
24871
|
} catch (e) {
|
|
24821
24872
|
return {
|
|
24822
24873
|
ci: { verdict: "CANNOT_VERIFY", binding, binding_error: `unreadable CI verify result: ${e instanceof Error ? e.message : String(e)}` },
|
|
@@ -24962,7 +25013,7 @@ function loadClaimedReceipt(path) {
|
|
|
24962
25013
|
}
|
|
24963
25014
|
let raw;
|
|
24964
25015
|
try {
|
|
24965
|
-
raw =
|
|
25016
|
+
raw = readFileSync25(path, "utf8");
|
|
24966
25017
|
} catch (e) {
|
|
24967
25018
|
return { disposition: "MALFORMED", detail: `receipt file could not be read (${e instanceof Error ? e.message : String(e)})` };
|
|
24968
25019
|
}
|
|
@@ -25013,7 +25064,7 @@ function writeJobSummary(r, receipt, ciBinding, adjudicatedTree) {
|
|
|
25013
25064
|
for (const d of r.divergence) md.push(`- ${d}`);
|
|
25014
25065
|
md.push("");
|
|
25015
25066
|
try {
|
|
25016
|
-
|
|
25067
|
+
appendFileSync3(path, md.join("\n") + "\n");
|
|
25017
25068
|
} catch {
|
|
25018
25069
|
}
|
|
25019
25070
|
}
|
|
@@ -25823,7 +25874,7 @@ var init_main = __esm({
|
|
|
25823
25874
|
// src/cli/index.ts
|
|
25824
25875
|
init_hook_client();
|
|
25825
25876
|
init_exit();
|
|
25826
|
-
import { readFileSync as
|
|
25877
|
+
import { readFileSync as readFileSync26 } from "node:fs";
|
|
25827
25878
|
function loadMain() {
|
|
25828
25879
|
return Promise.resolve().then(() => (init_main(), main_exports));
|
|
25829
25880
|
}
|
|
@@ -25836,7 +25887,7 @@ async function launch(argv) {
|
|
|
25836
25887
|
if (kind && hookServiceEnabled()) {
|
|
25837
25888
|
let raw = null;
|
|
25838
25889
|
try {
|
|
25839
|
-
raw =
|
|
25890
|
+
raw = readFileSync26(0, "utf8");
|
|
25840
25891
|
} catch {
|
|
25841
25892
|
raw = null;
|
|
25842
25893
|
}
|