tamperward 2.29.12 → 2.29.13
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 +77 -17
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -18237,18 +18237,69 @@ var init_trace_verify = __esm({
|
|
|
18237
18237
|
});
|
|
18238
18238
|
|
|
18239
18239
|
// src/runtimes.ts
|
|
18240
|
-
import { existsSync as existsSync17 } from "node:fs";
|
|
18240
|
+
import { existsSync as existsSync17, readFileSync as readFileSync21 } from "node:fs";
|
|
18241
18241
|
import { join as join23 } from "node:path";
|
|
18242
|
+
function isRecord4(x) {
|
|
18243
|
+
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
18244
|
+
}
|
|
18245
|
+
function hooksBeyondTamperward(hooks) {
|
|
18246
|
+
if (!isRecord4(hooks)) return hooks != null;
|
|
18247
|
+
for (const entries of Object.values(hooks)) {
|
|
18248
|
+
if (!Array.isArray(entries)) {
|
|
18249
|
+
if (entries != null) return true;
|
|
18250
|
+
continue;
|
|
18251
|
+
}
|
|
18252
|
+
for (const entry of entries) {
|
|
18253
|
+
const hs = isRecord4(entry) ? entry.hooks : null;
|
|
18254
|
+
if (!Array.isArray(hs)) {
|
|
18255
|
+
if (hs != null) return true;
|
|
18256
|
+
continue;
|
|
18257
|
+
}
|
|
18258
|
+
for (const h of hs) {
|
|
18259
|
+
const cmd = isRecord4(h) ? String(h.command ?? "") : "";
|
|
18260
|
+
if (!/tamperward/.test(cmd)) return true;
|
|
18261
|
+
}
|
|
18262
|
+
}
|
|
18263
|
+
}
|
|
18264
|
+
return false;
|
|
18265
|
+
}
|
|
18266
|
+
function claudeSettingsBeyondTamperward(cwd) {
|
|
18267
|
+
const path = join23(cwd, ".claude", "settings.json");
|
|
18268
|
+
let raw;
|
|
18269
|
+
try {
|
|
18270
|
+
if (!existsSync17(path)) return false;
|
|
18271
|
+
raw = readFileSync21(path, "utf8");
|
|
18272
|
+
} catch {
|
|
18273
|
+
return false;
|
|
18274
|
+
}
|
|
18275
|
+
let parsed;
|
|
18276
|
+
try {
|
|
18277
|
+
parsed = JSON.parse(raw);
|
|
18278
|
+
} catch {
|
|
18279
|
+
return raw.trim().length > 0;
|
|
18280
|
+
}
|
|
18281
|
+
if (!isRecord4(parsed)) return raw.trim().length > 0;
|
|
18282
|
+
for (const [key2, value] of Object.entries(parsed)) {
|
|
18283
|
+
if (key2 === "disableAllHooks") continue;
|
|
18284
|
+
if (key2 === "hooks") {
|
|
18285
|
+
if (hooksBeyondTamperward(value)) return true;
|
|
18286
|
+
continue;
|
|
18287
|
+
}
|
|
18288
|
+
return true;
|
|
18289
|
+
}
|
|
18290
|
+
return false;
|
|
18291
|
+
}
|
|
18242
18292
|
function detectRuntimes(cwd) {
|
|
18243
18293
|
const found = [];
|
|
18244
18294
|
for (const rt of KNOWN_RUNTIMES) {
|
|
18245
|
-
const
|
|
18295
|
+
const marker = rt.markers.find((m) => {
|
|
18246
18296
|
try {
|
|
18247
18297
|
return existsSync17(join23(cwd, m));
|
|
18248
18298
|
} catch {
|
|
18249
18299
|
return false;
|
|
18250
18300
|
}
|
|
18251
18301
|
});
|
|
18302
|
+
const matchedMarker = marker ?? rt.detectExtra?.(cwd) ?? void 0;
|
|
18252
18303
|
if (matchedMarker !== void 0) found.push({ ...rt, matchedMarker });
|
|
18253
18304
|
}
|
|
18254
18305
|
return found;
|
|
@@ -18268,10 +18319,14 @@ function detectionHeadline(detected) {
|
|
|
18268
18319
|
return `Detected ${detected.length} agent runtimes: ${parts.join(", ")}.`;
|
|
18269
18320
|
}
|
|
18270
18321
|
function neutralOnlyCaveat(detected) {
|
|
18271
|
-
|
|
18272
|
-
|
|
18273
|
-
const
|
|
18274
|
-
|
|
18322
|
+
const neutral = detected.filter((r) => r.steering === "neutral");
|
|
18323
|
+
if (neutral.length === 0) return null;
|
|
18324
|
+
const names = neutral.map((r) => r.label).join(", ");
|
|
18325
|
+
const tracking = [...new Set(neutral.map((r) => r.adapterTracking).filter(Boolean))].join(", ");
|
|
18326
|
+
const claudeAlso = hasInLoopRuntime(detected);
|
|
18327
|
+
const lead = claudeAlso ? `In-loop steering (deny-before-execute) ships for Claude Code only today: Claude Code here gets it, but on ${names} your live protection is ` : `In-loop steering (deny-before-execute) ships for Claude Code only today, so on ${names} your live protection is `;
|
|
18328
|
+
const tail = claudeAlso ? "" : " The Claude hook wiring is still written and is inert unless Claude Code runs in this repository.";
|
|
18329
|
+
return `${lead}the agent-neutral layers: pre-commit and CI.${tail}${tracking ? ` A native in-loop adapter is tracked in ${tracking}.` : ""}`;
|
|
18275
18330
|
}
|
|
18276
18331
|
var KNOWN_RUNTIMES;
|
|
18277
18332
|
var init_runtimes = __esm({
|
|
@@ -18280,8 +18335,13 @@ var init_runtimes = __esm({
|
|
|
18280
18335
|
KNOWN_RUNTIMES = [
|
|
18281
18336
|
{
|
|
18282
18337
|
id: "claude-code",
|
|
18338
|
+
// Markers are Claude Code files `init` never writes, so detection never mistakes
|
|
18339
|
+
// TamperWard's own generated `.claude/settings.json` for evidence a human runs
|
|
18340
|
+
// Claude here (#526). `detectExtra` looks at that generated file's CONTENT for
|
|
18341
|
+
// real use (configuration beyond the two hooks init merges in).
|
|
18283
18342
|
label: "Claude Code",
|
|
18284
|
-
markers: [".claude/settings.json", ".claude"],
|
|
18343
|
+
markers: ["CLAUDE.md", ".claude/settings.local.json", ".claude/commands", ".claude/agents"],
|
|
18344
|
+
detectExtra: (cwd) => claudeSettingsBeyondTamperward(cwd) ? ".claude/settings.json" : null,
|
|
18285
18345
|
steering: "in-loop",
|
|
18286
18346
|
note: "native in-loop steering (PreToolUse deny + Stop sweep) plus the agent-neutral layers."
|
|
18287
18347
|
},
|
|
@@ -18315,7 +18375,7 @@ var init_runtimes = __esm({
|
|
|
18315
18375
|
|
|
18316
18376
|
// src/cli/onboard.ts
|
|
18317
18377
|
import { execFileSync as execFileSync12 } from "node:child_process";
|
|
18318
|
-
import { lstatSync as lstatSync10, mkdtempSync as mkdtempSync6, readFileSync as
|
|
18378
|
+
import { lstatSync as lstatSync10, mkdtempSync as mkdtempSync6, readFileSync as readFileSync22, realpathSync as realpathSync11, rmSync as rmSync10 } from "node:fs";
|
|
18319
18379
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
18320
18380
|
import { join as join24, relative as relative7, resolve as resolve12, sep as sep5 } from "node:path";
|
|
18321
18381
|
import { createInterface } from "node:readline";
|
|
@@ -18391,7 +18451,7 @@ function writeVerifyCommand(cwd, command) {
|
|
|
18391
18451
|
return `${POLICY_FILE} is not a regular file; refusing to follow or replace a symlink or special file`;
|
|
18392
18452
|
}
|
|
18393
18453
|
const mode = existingMode(path, 420);
|
|
18394
|
-
const original = kind === "file" ?
|
|
18454
|
+
const original = kind === "file" ? readFileSync22(path, "utf8") : null;
|
|
18395
18455
|
let next;
|
|
18396
18456
|
try {
|
|
18397
18457
|
const doc = parseDocument(original && original.trim() ? original : "version: 1\n");
|
|
@@ -18992,7 +19052,7 @@ var init_capture = __esm({
|
|
|
18992
19052
|
|
|
18993
19053
|
// src/research/manifest.ts
|
|
18994
19054
|
import { createHash as createHash13 } from "node:crypto";
|
|
18995
|
-
import { readFileSync as
|
|
19055
|
+
import { readFileSync as readFileSync23 } from "node:fs";
|
|
18996
19056
|
import { dirname as dirname10, resolve as resolve14 } from "node:path";
|
|
18997
19057
|
function taskFrom(raw, index, manifestDir) {
|
|
18998
19058
|
const where = `task #${index + 1}`;
|
|
@@ -19026,7 +19086,7 @@ function readManifest(path) {
|
|
|
19026
19086
|
const abs = resolve14(path);
|
|
19027
19087
|
let bytes;
|
|
19028
19088
|
try {
|
|
19029
|
-
bytes =
|
|
19089
|
+
bytes = readFileSync23(abs);
|
|
19030
19090
|
} catch (e) {
|
|
19031
19091
|
throw new ResearchError(`cannot read task manifest ${abs}: ${e instanceof Error ? e.message : String(e)}`);
|
|
19032
19092
|
}
|
|
@@ -19238,7 +19298,7 @@ var init_record = __esm({
|
|
|
19238
19298
|
|
|
19239
19299
|
// src/research/run.ts
|
|
19240
19300
|
import { execFileSync as execFileSync13 } from "node:child_process";
|
|
19241
|
-
import { existsSync as existsSync18, mkdirSync as mkdirSync9, readFileSync as
|
|
19301
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync9, readFileSync as readFileSync24, renameSync as renameSync4, rmSync as rmSync11, writeFileSync as writeFileSync11 } from "node:fs";
|
|
19242
19302
|
import { join as join25, resolve as resolve15 } from "node:path";
|
|
19243
19303
|
function git6(args, cwd) {
|
|
19244
19304
|
return execFileSync13("git", args, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
|
|
@@ -19249,7 +19309,7 @@ function pairRecordPath(ledger, task, pair) {
|
|
|
19249
19309
|
function resumableRecord(path, expected) {
|
|
19250
19310
|
let raw;
|
|
19251
19311
|
try {
|
|
19252
|
-
raw = JSON.parse(
|
|
19312
|
+
raw = JSON.parse(readFileSync24(path, "utf8"));
|
|
19253
19313
|
} catch (e) {
|
|
19254
19314
|
throw new ResearchError(`ledger record ${path} is malformed (${errorMessage(e).split("\n")[0]}); remove it to regenerate the pair, or use a new --out`);
|
|
19255
19315
|
}
|
|
@@ -19672,7 +19732,7 @@ var init_run2 = __esm({
|
|
|
19672
19732
|
});
|
|
19673
19733
|
|
|
19674
19734
|
// src/research/summarize.ts
|
|
19675
|
-
import { readdirSync as readdirSync7, readFileSync as
|
|
19735
|
+
import { readdirSync as readdirSync7, readFileSync as readFileSync25 } from "node:fs";
|
|
19676
19736
|
import { join as join26, resolve as resolve16 } from "node:path";
|
|
19677
19737
|
function readLedger2(dir) {
|
|
19678
19738
|
const pairsDir = join26(resolve16(dir), "pairs");
|
|
@@ -19687,7 +19747,7 @@ function readLedger2(dir) {
|
|
|
19687
19747
|
const path = join26(pairsDir, n);
|
|
19688
19748
|
let raw;
|
|
19689
19749
|
try {
|
|
19690
|
-
raw = JSON.parse(
|
|
19750
|
+
raw = JSON.parse(readFileSync25(path, "utf8"));
|
|
19691
19751
|
} catch (e) {
|
|
19692
19752
|
throw new ResearchError(`ledger record ${path} is not valid JSON: ${errorMessage(e)}`);
|
|
19693
19753
|
}
|
|
@@ -20394,7 +20454,7 @@ var init_main = __esm({
|
|
|
20394
20454
|
// src/cli/index.ts
|
|
20395
20455
|
init_hook_client();
|
|
20396
20456
|
init_exit();
|
|
20397
|
-
import { readFileSync as
|
|
20457
|
+
import { readFileSync as readFileSync26 } from "node:fs";
|
|
20398
20458
|
function loadMain() {
|
|
20399
20459
|
return Promise.resolve().then(() => (init_main(), main_exports));
|
|
20400
20460
|
}
|
|
@@ -20407,7 +20467,7 @@ async function launch(argv) {
|
|
|
20407
20467
|
if (kind && hookServiceEnabled()) {
|
|
20408
20468
|
let raw = null;
|
|
20409
20469
|
try {
|
|
20410
|
-
raw =
|
|
20470
|
+
raw = readFileSync26(0, "utf8");
|
|
20411
20471
|
} catch {
|
|
20412
20472
|
raw = null;
|
|
20413
20473
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tamperward",
|
|
3
|
-
"version": "2.29.
|
|
3
|
+
"version": "2.29.13",
|
|
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",
|