tamperward 2.26.0 → 2.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli/index.js +69 -37
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -98,7 +98,7 @@ Earlier controlled experiments → **[the research series](./docs/blog/index.md)
|
|
|
98
98
|
> Read the round as a pair — the bets before, the outcome after:
|
|
99
99
|
> [How round 4 is built to be hard to fool](./docs/blog/how-round-4-is-built-to-be-hard-to-fool.md)
|
|
100
100
|
> (preregistration, no numbers) →
|
|
101
|
-
> [The prevention bet didn't replicate. No surviving tampering was certified clean.](./docs/blog/
|
|
101
|
+
> [The prevention bet didn't replicate. No surviving tampering was certified clean.](./docs/blog/the-prevention-bet-didnt-replicate-no-surviving-tampering-was-certified-clean.md)
|
|
102
102
|
> (results). Round 4.1, a second agent runtime over the same frozen pool, is the
|
|
103
103
|
> next registered step ([SPEC §9.1](./SPEC.md#91-maturity-milestones)).
|
|
104
104
|
|
package/dist/cli/index.js
CHANGED
|
@@ -1090,7 +1090,7 @@ var init_trusted = __esm({
|
|
|
1090
1090
|
|
|
1091
1091
|
// src/repo-context.ts
|
|
1092
1092
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
1093
|
-
import { accessSync, constants as constants2, existsSync as existsSync2, statSync } from "node:fs";
|
|
1093
|
+
import { accessSync, constants as constants2, existsSync as existsSync2, realpathSync as realpathSync3, statSync } from "node:fs";
|
|
1094
1094
|
import { isAbsolute as isAbsolute3, resolve } from "node:path";
|
|
1095
1095
|
function rev(cwd, flag) {
|
|
1096
1096
|
try {
|
|
@@ -1123,6 +1123,27 @@ function repoContext(cwd) {
|
|
|
1123
1123
|
function repoRoot(cwd) {
|
|
1124
1124
|
return repoContext(cwd)?.root ?? cwd;
|
|
1125
1125
|
}
|
|
1126
|
+
function validateClaimAgainstRoot(claimedCwd, trustedRoot, base) {
|
|
1127
|
+
if (claimedCwd === void 0) return { ok: true, trustedRoot };
|
|
1128
|
+
if (typeof claimedCwd !== "string" || claimedCwd.trim() === "") return { ok: false, rejected: "malformed cwd claim" };
|
|
1129
|
+
const abs = isAbsolute3(claimedCwd) ? claimedCwd : resolve(base, claimedCwd);
|
|
1130
|
+
let realClaim;
|
|
1131
|
+
try {
|
|
1132
|
+
realClaim = realpathSync3(abs);
|
|
1133
|
+
} catch (e) {
|
|
1134
|
+
return { ok: false, rejected: `cwd claim path cannot be resolved (${abs}: ${e instanceof Error ? e.message : String(e)})` };
|
|
1135
|
+
}
|
|
1136
|
+
let realTrusted;
|
|
1137
|
+
try {
|
|
1138
|
+
realTrusted = realpathSync3(trustedRoot);
|
|
1139
|
+
} catch {
|
|
1140
|
+
realTrusted = trustedRoot;
|
|
1141
|
+
}
|
|
1142
|
+
const ctx = repoContext(realClaim);
|
|
1143
|
+
if (!ctx) return { ok: false, rejected: `cwd claim resolves to no repository (${realClaim})` };
|
|
1144
|
+
if (ctx.root !== realTrusted) return { ok: false, rejected: `cwd claim resolves to a different repository (${ctx.root} != trusted ${realTrusted})` };
|
|
1145
|
+
return { ok: true, trustedRoot: realTrusted };
|
|
1146
|
+
}
|
|
1126
1147
|
function outsideRepository(cwd) {
|
|
1127
1148
|
const key2 = resolve(cwd);
|
|
1128
1149
|
let isDir;
|
|
@@ -11863,10 +11884,7 @@ function failClosed(kind, detail) {
|
|
|
11863
11884
|
};
|
|
11864
11885
|
return verdict([f], kind);
|
|
11865
11886
|
}
|
|
11866
|
-
function
|
|
11867
|
-
if (blocks2.length === 0) return { exitCode: 0, stdout: "" };
|
|
11868
|
-
recordDenylog(blocks2);
|
|
11869
|
-
const reason = formatDenial(blocks2);
|
|
11887
|
+
function denyWire(reason, kind) {
|
|
11870
11888
|
const payload = kind === "PreToolUse" ? {
|
|
11871
11889
|
hookSpecificOutput: {
|
|
11872
11890
|
hookEventName: "PreToolUse",
|
|
@@ -11874,7 +11892,13 @@ function verdict(blocks2, kind) {
|
|
|
11874
11892
|
permissionDecisionReason: reason
|
|
11875
11893
|
}
|
|
11876
11894
|
} : { decision: "block", reason };
|
|
11877
|
-
return
|
|
11895
|
+
return JSON.stringify(payload) + "\n";
|
|
11896
|
+
}
|
|
11897
|
+
function verdict(blocks2, kind) {
|
|
11898
|
+
if (blocks2.length === 0) return { exitCode: 0, stdout: "" };
|
|
11899
|
+
recordDenylog(blocks2);
|
|
11900
|
+
const reason = formatDenial(blocks2);
|
|
11901
|
+
return { exitCode: 0, stdout: denyWire(reason, kind) };
|
|
11878
11902
|
}
|
|
11879
11903
|
function fileChanges(changes) {
|
|
11880
11904
|
return changes.filter((c) => c.kind === "file");
|
|
@@ -12052,9 +12076,13 @@ function sanctionPredictedWrites(cwd, sessionId, policy, changes) {
|
|
|
12052
12076
|
}
|
|
12053
12077
|
if (dirty) savePtree(cwd, sessionId, tree);
|
|
12054
12078
|
}
|
|
12055
|
-
function preToolUseVerdict(input, defaultCwd) {
|
|
12079
|
+
function preToolUseVerdict(input, defaultCwd, trustedRoot) {
|
|
12056
12080
|
try {
|
|
12057
12081
|
const sessionCwd = input.cwd ?? defaultCwd ?? process.cwd();
|
|
12082
|
+
if (trustedRoot !== void 0) {
|
|
12083
|
+
const v = validateClaimAgainstRoot(input.cwd, trustedRoot, defaultCwd ?? process.cwd());
|
|
12084
|
+
if (!v.ok) return failClosed("PreToolUse", `repository identity claim rejected: ${v.rejected}`);
|
|
12085
|
+
}
|
|
12058
12086
|
const cwd = repoRoot(sessionCwd);
|
|
12059
12087
|
turnBaseline(cwd, input.session_id);
|
|
12060
12088
|
const policy = loadPolicy(cwd);
|
|
@@ -12161,9 +12189,13 @@ function recordObserverHealth(state, reason) {
|
|
|
12161
12189
|
} catch {
|
|
12162
12190
|
}
|
|
12163
12191
|
}
|
|
12164
|
-
function stopVerdict(input, defaultCwd) {
|
|
12192
|
+
function stopVerdict(input, defaultCwd, trustedRoot) {
|
|
12165
12193
|
if (input.stop_hook_active) return { exitCode: 0, stdout: "" };
|
|
12166
12194
|
const sessionCwd = input.cwd ?? defaultCwd ?? process.cwd();
|
|
12195
|
+
if (trustedRoot !== void 0) {
|
|
12196
|
+
const v = validateClaimAgainstRoot(input.cwd, trustedRoot, defaultCwd ?? process.cwd());
|
|
12197
|
+
if (!v.ok) return failClosed("Stop", `repository identity claim rejected: ${v.rejected}`);
|
|
12198
|
+
}
|
|
12167
12199
|
const ctx = repoContext(sessionCwd);
|
|
12168
12200
|
if (!ctx) {
|
|
12169
12201
|
const why = outsideRepository(sessionCwd);
|
|
@@ -12206,16 +12238,16 @@ function emit(r) {
|
|
|
12206
12238
|
if (r.stdout) process.stdout.write(r.stdout);
|
|
12207
12239
|
return r.exitCode;
|
|
12208
12240
|
}
|
|
12209
|
-
function preToolUseFromRaw(raw, defaultCwd) {
|
|
12241
|
+
function preToolUseFromRaw(raw, defaultCwd, trustedRoot) {
|
|
12210
12242
|
try {
|
|
12211
|
-
return preToolUseVerdict(parseInput(raw), defaultCwd);
|
|
12243
|
+
return preToolUseVerdict(parseInput(raw), defaultCwd, trustedRoot);
|
|
12212
12244
|
} catch (e) {
|
|
12213
12245
|
return failClosed("PreToolUse", errText2(e));
|
|
12214
12246
|
}
|
|
12215
12247
|
}
|
|
12216
|
-
function stopFromRaw(raw, defaultCwd) {
|
|
12248
|
+
function stopFromRaw(raw, defaultCwd, trustedRoot) {
|
|
12217
12249
|
try {
|
|
12218
|
-
return stopVerdict(parseInput(raw), defaultCwd);
|
|
12250
|
+
return stopVerdict(parseInput(raw), defaultCwd, trustedRoot);
|
|
12219
12251
|
} catch (e) {
|
|
12220
12252
|
return failClosed("Stop", errText2(e));
|
|
12221
12253
|
}
|
|
@@ -12361,7 +12393,7 @@ var init_ptree_cache = __esm({
|
|
|
12361
12393
|
// src/cli/hook-service.ts
|
|
12362
12394
|
import { chmodSync, existsSync as existsSync10, lstatSync as lstatSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync11, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "node:fs";
|
|
12363
12395
|
import { createConnection as createConnection2, createServer } from "node:net";
|
|
12364
|
-
import { realpathSync as
|
|
12396
|
+
import { realpathSync as realpathSync4 } from "node:fs";
|
|
12365
12397
|
import { sep } from "node:path";
|
|
12366
12398
|
function readServiceState(paths) {
|
|
12367
12399
|
try {
|
|
@@ -12399,7 +12431,7 @@ function listening(socket) {
|
|
|
12399
12431
|
function within(root, cwd) {
|
|
12400
12432
|
let real;
|
|
12401
12433
|
try {
|
|
12402
|
-
real =
|
|
12434
|
+
real = realpathSync4(cwd);
|
|
12403
12435
|
} catch {
|
|
12404
12436
|
return false;
|
|
12405
12437
|
}
|
|
@@ -12464,7 +12496,7 @@ async function startHookService(opts) {
|
|
|
12464
12496
|
if (uid === void 0) throw new Error("no uid on this platform; refusing to start");
|
|
12465
12497
|
let root;
|
|
12466
12498
|
try {
|
|
12467
|
-
root =
|
|
12499
|
+
root = realpathSync4(repoRoot(realpathSync4(opts.root)));
|
|
12468
12500
|
} catch {
|
|
12469
12501
|
throw new Error(`cannot resolve ${opts.root}`);
|
|
12470
12502
|
}
|
|
@@ -12831,7 +12863,7 @@ var init_safe_write = __esm({
|
|
|
12831
12863
|
// src/cli/init.ts
|
|
12832
12864
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
12833
12865
|
import { createHash as createHash6 } from "node:crypto";
|
|
12834
|
-
import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync12, realpathSync as
|
|
12866
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync12, realpathSync as realpathSync5 } from "node:fs";
|
|
12835
12867
|
import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute8, join as join14, relative as relative3, resolve as resolve4 } from "node:path";
|
|
12836
12868
|
function gitConfig(cwd, key2) {
|
|
12837
12869
|
try {
|
|
@@ -13409,7 +13441,7 @@ function planned(item, path, plan) {
|
|
|
13409
13441
|
}
|
|
13410
13442
|
function sameDir(a, b) {
|
|
13411
13443
|
try {
|
|
13412
|
-
return
|
|
13444
|
+
return realpathSync5(a) === realpathSync5(b);
|
|
13413
13445
|
} catch {
|
|
13414
13446
|
return false;
|
|
13415
13447
|
}
|
|
@@ -13665,7 +13697,7 @@ import {
|
|
|
13665
13697
|
readdirSync as readdirSync3,
|
|
13666
13698
|
readFileSync as readFileSync13,
|
|
13667
13699
|
readlinkSync as readlinkSync2,
|
|
13668
|
-
realpathSync as
|
|
13700
|
+
realpathSync as realpathSync6,
|
|
13669
13701
|
statSync as statSync3
|
|
13670
13702
|
} from "node:fs";
|
|
13671
13703
|
import {
|
|
@@ -13697,7 +13729,7 @@ function fingerprintRoot(root, cwd, h) {
|
|
|
13697
13729
|
let currentReal;
|
|
13698
13730
|
try {
|
|
13699
13731
|
rootStat = lstatSync8(root.path);
|
|
13700
|
-
currentReal =
|
|
13732
|
+
currentReal = realpathSync6(root.path);
|
|
13701
13733
|
} catch (e) {
|
|
13702
13734
|
throw new Unattestable(
|
|
13703
13735
|
root.kind + " root " + JSON.stringify(root.path) + " can no longer be resolved (" + (e instanceof Error ? e.message : String(e)) + ")"
|
|
@@ -13713,7 +13745,7 @@ function fingerprintRoot(root, cwd, h) {
|
|
|
13713
13745
|
}
|
|
13714
13746
|
h.update("root\0" + root.kind + "\0" + root.path + "\0" + root.realPath + "\0" + String(rootStat.mode) + "\0");
|
|
13715
13747
|
if (rootStat.isSymbolicLink()) h.update(readlinkSync2(root.path) + "\0");
|
|
13716
|
-
const cwdReal =
|
|
13748
|
+
const cwdReal = realpathSync6(cwd);
|
|
13717
13749
|
const visited = /* @__PURE__ */ new Set();
|
|
13718
13750
|
const hashFile = (path, label) => {
|
|
13719
13751
|
let st;
|
|
@@ -13730,7 +13762,7 @@ function fingerprintRoot(root, cwd, h) {
|
|
|
13730
13762
|
}
|
|
13731
13763
|
};
|
|
13732
13764
|
const walk2 = (dir, namespace) => {
|
|
13733
|
-
const realDir =
|
|
13765
|
+
const realDir = realpathSync6(dir);
|
|
13734
13766
|
if (visited.has(realDir)) return;
|
|
13735
13767
|
visited.add(realDir);
|
|
13736
13768
|
let entries;
|
|
@@ -13780,7 +13812,7 @@ function fingerprintRoot(root, cwd, h) {
|
|
|
13780
13812
|
h.update(target + "\0");
|
|
13781
13813
|
let resolved;
|
|
13782
13814
|
try {
|
|
13783
|
-
resolved =
|
|
13815
|
+
resolved = realpathSync6(path);
|
|
13784
13816
|
} catch {
|
|
13785
13817
|
continue;
|
|
13786
13818
|
}
|
|
@@ -13835,7 +13867,7 @@ function freezeRoot(kind, path) {
|
|
|
13835
13867
|
if (!statSync3(path).isDirectory()) {
|
|
13836
13868
|
throw new Error("not a directory");
|
|
13837
13869
|
}
|
|
13838
|
-
return { kind, path: resolve5(path), realPath:
|
|
13870
|
+
return { kind, path: resolve5(path), realPath: realpathSync6(path) };
|
|
13839
13871
|
} catch (e) {
|
|
13840
13872
|
throw new Unattestable(
|
|
13841
13873
|
kind + " root " + JSON.stringify(path) + " is not resolvable (" + (e instanceof Error ? e.message : String(e)) + ")"
|
|
@@ -13873,7 +13905,7 @@ function resolveExecutable(token, cwd, env) {
|
|
|
13873
13905
|
if (token.includes("/") || token.includes("\\")) {
|
|
13874
13906
|
const path = isAbsolute9(token) ? token : resolve5(cwd, token);
|
|
13875
13907
|
try {
|
|
13876
|
-
return existsSync12(path) ?
|
|
13908
|
+
return existsSync12(path) ? realpathSync6(path) : null;
|
|
13877
13909
|
} catch {
|
|
13878
13910
|
return null;
|
|
13879
13911
|
}
|
|
@@ -13881,7 +13913,7 @@ function resolveExecutable(token, cwd, env) {
|
|
|
13881
13913
|
for (const entry of (env.PATH ?? "").split(delimiter).filter(Boolean)) {
|
|
13882
13914
|
const candidate = resolve5(entry, token);
|
|
13883
13915
|
try {
|
|
13884
|
-
if (existsSync12(candidate) && statSync3(candidate).isFile()) return
|
|
13916
|
+
if (existsSync12(candidate) && statSync3(candidate).isFile()) return realpathSync6(candidate);
|
|
13885
13917
|
} catch {
|
|
13886
13918
|
}
|
|
13887
13919
|
}
|
|
@@ -14387,7 +14419,7 @@ if (child) {
|
|
|
14387
14419
|
// src/verifier-backend.ts
|
|
14388
14420
|
import { createHash as createHash9, randomUUID } from "node:crypto";
|
|
14389
14421
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
14390
|
-
import { accessSync as accessSync2, constants as constants3, readFileSync as readFileSync15, realpathSync as
|
|
14422
|
+
import { accessSync as accessSync2, constants as constants3, readFileSync as readFileSync15, realpathSync as realpathSync7, statSync as statSync4 } from "node:fs";
|
|
14391
14423
|
import { delimiter as delimiter2, dirname as dirname6, join as join17, resolve as resolve6 } from "node:path";
|
|
14392
14424
|
function identity() {
|
|
14393
14425
|
const uid = typeof process.getuid === "function" ? process.getuid() : null;
|
|
@@ -14425,7 +14457,7 @@ function findExecutable(name) {
|
|
|
14425
14457
|
const candidate = join17(raw, name);
|
|
14426
14458
|
try {
|
|
14427
14459
|
accessSync2(candidate, constants3.X_OK);
|
|
14428
|
-
return
|
|
14460
|
+
return realpathSync7(candidate);
|
|
14429
14461
|
} catch {
|
|
14430
14462
|
}
|
|
14431
14463
|
}
|
|
@@ -14500,7 +14532,7 @@ function inspectImageMetadata(enginePath, host, image) {
|
|
|
14500
14532
|
function engineStable(backend) {
|
|
14501
14533
|
if (!backend.enginePath || !backend.engineSha256) return false;
|
|
14502
14534
|
try {
|
|
14503
|
-
if (
|
|
14535
|
+
if (realpathSync7(backend.enginePath) !== backend.enginePath) return false;
|
|
14504
14536
|
if (replaceableByCaller(backend.enginePath)) return false;
|
|
14505
14537
|
return fileSha256(backend.enginePath) === backend.engineSha256;
|
|
14506
14538
|
} catch {
|
|
@@ -15741,7 +15773,7 @@ var init_verify = __esm({
|
|
|
15741
15773
|
// src/cli/run.ts
|
|
15742
15774
|
import { execFileSync as execFileSync9, spawn, spawnSync as spawnSync4 } from "node:child_process";
|
|
15743
15775
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
15744
|
-
import { accessSync as accessSync3, constants as fsConstants, mkdtempSync as mkdtempSync4, readdirSync as readdirSync4, readFileSync as readFileSync17, readlinkSync as readlinkSync4, realpathSync as
|
|
15776
|
+
import { accessSync as accessSync3, constants as fsConstants, mkdtempSync as mkdtempSync4, readdirSync as readdirSync4, readFileSync as readFileSync17, readlinkSync as readlinkSync4, realpathSync as realpathSync9, rmSync as rmSync8, statSync as statSync5, writeFileSync as writeFileSync10 } from "node:fs";
|
|
15745
15777
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
15746
15778
|
import { dirname as dirname8, join as join19, resolve as resolve8 } from "node:path";
|
|
15747
15779
|
function authoritativeRunLifecyclePlatform(platform = process.platform) {
|
|
@@ -15796,7 +15828,7 @@ function trustedLinuxPython(candidates = DEFAULT_TRUSTED_PYTHON_CANDIDATES) {
|
|
|
15796
15828
|
}
|
|
15797
15829
|
for (const candidate of candidates) {
|
|
15798
15830
|
try {
|
|
15799
|
-
const real =
|
|
15831
|
+
const real = realpathSync9(candidate);
|
|
15800
15832
|
const st = statSync5(real);
|
|
15801
15833
|
if (!st.isFile() || writableByCaller2(real)) continue;
|
|
15802
15834
|
const probe = spawnSync4(
|
|
@@ -16070,7 +16102,7 @@ function survivorsHoldingTree(cwd, spawnedAfterTicks) {
|
|
|
16070
16102
|
const out3 = [];
|
|
16071
16103
|
let real;
|
|
16072
16104
|
try {
|
|
16073
|
-
real =
|
|
16105
|
+
real = realpathSync9(cwd);
|
|
16074
16106
|
} catch {
|
|
16075
16107
|
return out3;
|
|
16076
16108
|
}
|
|
@@ -17292,7 +17324,7 @@ import {
|
|
|
17292
17324
|
mkdtempSync as mkdtempSync5,
|
|
17293
17325
|
readFileSync as readFileSync19,
|
|
17294
17326
|
readdirSync as readdirSync6,
|
|
17295
|
-
realpathSync as
|
|
17327
|
+
realpathSync as realpathSync10,
|
|
17296
17328
|
rmSync as rmSync9,
|
|
17297
17329
|
symlinkSync as symlinkSync2
|
|
17298
17330
|
} from "node:fs";
|
|
@@ -17440,7 +17472,7 @@ function rewriteTraceRoot(accesses, actualRoot) {
|
|
|
17440
17472
|
if (!inside3(actualRoot, abs)) return { ...item, path: abs };
|
|
17441
17473
|
const rel = relative6(actualRoot, abs).split(sep4).join("/");
|
|
17442
17474
|
try {
|
|
17443
|
-
const real = resolve10(
|
|
17475
|
+
const real = resolve10(realpathSync10(abs));
|
|
17444
17476
|
if (!inside3(actualRoot, real)) return { ...item, path: real };
|
|
17445
17477
|
} catch {
|
|
17446
17478
|
}
|
|
@@ -17676,7 +17708,7 @@ var init_trace_verify = __esm({
|
|
|
17676
17708
|
|
|
17677
17709
|
// src/cli/onboard.ts
|
|
17678
17710
|
import { execFileSync as execFileSync12 } from "node:child_process";
|
|
17679
|
-
import { lstatSync as lstatSync10, mkdtempSync as mkdtempSync6, readFileSync as readFileSync20, realpathSync as
|
|
17711
|
+
import { lstatSync as lstatSync10, mkdtempSync as mkdtempSync6, readFileSync as readFileSync20, realpathSync as realpathSync11, rmSync as rmSync10 } from "node:fs";
|
|
17680
17712
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
17681
17713
|
import { join as join22, relative as relative7, resolve as resolve11, sep as sep5 } from "node:path";
|
|
17682
17714
|
import { createInterface } from "node:readline";
|
|
@@ -17818,7 +17850,7 @@ async function runOnboard(opts, io = {}) {
|
|
|
17818
17850
|
const cwd = resolve11(rootText);
|
|
17819
17851
|
let sameRoot = cwd === requestedCwd;
|
|
17820
17852
|
try {
|
|
17821
|
-
sameRoot =
|
|
17853
|
+
sameRoot = realpathSync11(cwd) === realpathSync11(requestedCwd);
|
|
17822
17854
|
} catch {
|
|
17823
17855
|
}
|
|
17824
17856
|
if (!sameRoot) {
|
|
@@ -18156,8 +18188,8 @@ function runDemo(cwd, head, runners, out3) {
|
|
|
18156
18188
|
let worktreeRoot;
|
|
18157
18189
|
let realTarget;
|
|
18158
18190
|
try {
|
|
18159
|
-
worktreeRoot =
|
|
18160
|
-
realTarget =
|
|
18191
|
+
worktreeRoot = realpathSync11(wt);
|
|
18192
|
+
realTarget = realpathSync11(targetPath);
|
|
18161
18193
|
} catch {
|
|
18162
18194
|
out3("Demo skipped: the selected test could not be resolved safely inside the disposable worktree.");
|
|
18163
18195
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tamperward",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.27.0",
|
|
4
4
|
"description": "The deterministic agent-integrity gate. One ruleset, evaluated on the actual diff/commands as a verdict, enforced everywhere a change can be made.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "hexrift",
|