tamperward 1.13.0 → 1.14.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/dist/cli/index.js +49 -5
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -215,9 +215,13 @@ function enrich(c, beforeReader, afterReader) {
|
|
|
215
215
|
const after = c.op !== "delete" ? afterReader(c.path) : null;
|
|
216
216
|
return { ...c, before, after };
|
|
217
217
|
}
|
|
218
|
+
function assertRev(rev) {
|
|
219
|
+
if (rev.startsWith("-")) throw new Error(`refusing a revision that git would read as an option: ${rev}`);
|
|
220
|
+
return rev;
|
|
221
|
+
}
|
|
218
222
|
function mergeBaseOf(base, head, opts = {}) {
|
|
219
223
|
try {
|
|
220
|
-
return git(["merge-base", base, head], opts.cwd).trim() || base;
|
|
224
|
+
return git(["merge-base", assertRev(base), assertRev(head)], opts.cwd).trim() || base;
|
|
221
225
|
} catch {
|
|
222
226
|
return base;
|
|
223
227
|
}
|
|
@@ -254,6 +258,8 @@ function diffSince(rev, opts = {}) {
|
|
|
254
258
|
);
|
|
255
259
|
}
|
|
256
260
|
function diffRange(base, head, opts = {}) {
|
|
261
|
+
assertRev(base);
|
|
262
|
+
assertRev(head);
|
|
257
263
|
const raw = git(["diff", "--no-color", "-M", `${base}...${head}`], opts.cwd);
|
|
258
264
|
const mergeBase = mergeBaseOf(base, head, opts);
|
|
259
265
|
return parseDiff(raw).map(
|
|
@@ -447,7 +453,36 @@ function defaultPolicy(version = 1) {
|
|
|
447
453
|
// .test.tsx/.spec.tsx (hono, zustand) slipped the glob, so legit test-file casts blocked
|
|
448
454
|
// instead of warning. Kept ADDITIVE (originals + new extensions) so the policy-diff sees a
|
|
449
455
|
// strengthening, not a narrowing. picomatch expands the brace.
|
|
450
|
-
|
|
456
|
+
// test-skip, test-deletion and test-content-removal all gate on this
|
|
457
|
+
// class, so a repo it does not match gets rules that can NEVER fire —
|
|
458
|
+
// protection that is silently absent rather than visibly off. The JS/TS
|
|
459
|
+
// list shipped alone; these are the conventional layouts of the other
|
|
460
|
+
// ecosystems `init` is run in. (P2-13, external review.)
|
|
461
|
+
tests: [
|
|
462
|
+
// JavaScript / TypeScript
|
|
463
|
+
"**/*.test.ts",
|
|
464
|
+
"**/*.spec.ts",
|
|
465
|
+
"**/*.{test,spec}.{tsx,cts,mts,js,jsx,cjs,mjs}",
|
|
466
|
+
"**/__tests__/**",
|
|
467
|
+
// Python (pytest / unittest layouts)
|
|
468
|
+
"**/test_*.py",
|
|
469
|
+
"**/*_test.py",
|
|
470
|
+
"**/conftest.py",
|
|
471
|
+
// Go
|
|
472
|
+
"**/*_test.go",
|
|
473
|
+
// Rust (integration tests live in tests/, unit tests inline)
|
|
474
|
+
"**/tests/**/*.rs",
|
|
475
|
+
// Ruby (RSpec / minitest)
|
|
476
|
+
"**/*_spec.rb",
|
|
477
|
+
"**/*_test.rb",
|
|
478
|
+
// Java / Kotlin / Scala (Maven & Gradle convention)
|
|
479
|
+
"**/src/test/**",
|
|
480
|
+
// PHP (PHPUnit)
|
|
481
|
+
"**/*Test.php",
|
|
482
|
+
// C# (.NET)
|
|
483
|
+
"**/*Tests.cs",
|
|
484
|
+
"**/*Test.cs"
|
|
485
|
+
],
|
|
451
486
|
config: [
|
|
452
487
|
"**/jest.config.*",
|
|
453
488
|
"**/vitest.config.*",
|
|
@@ -1819,15 +1854,21 @@ function annotations(findings) {
|
|
|
1819
1854
|
function cell(s) {
|
|
1820
1855
|
return s.replace(/\s+/g, " ").replace(/\|/g, "\\|").trim();
|
|
1821
1856
|
}
|
|
1857
|
+
function mdCode(s) {
|
|
1858
|
+
return s.replace(/`/g, "'").replace(/[\r\n]/g, " ");
|
|
1859
|
+
}
|
|
1860
|
+
function mdUrl(s) {
|
|
1861
|
+
return s.replace(/[()<> \r\n"'`\\]/g, (c) => "%" + c.charCodeAt(0).toString(16).padStart(2, "0").toUpperCase());
|
|
1862
|
+
}
|
|
1822
1863
|
function locationCell(f, env) {
|
|
1823
1864
|
if (!f.file) return "`(command)`";
|
|
1824
1865
|
const label = `${f.file}${f.line ? `:${f.line}` : ""}`;
|
|
1825
1866
|
const server = env.GITHUB_SERVER_URL;
|
|
1826
1867
|
const repo = env.GITHUB_REPOSITORY;
|
|
1827
1868
|
const sha2 = env.GITHUB_SHA;
|
|
1828
|
-
if (!server || !repo || !sha2) return `\`${cell(label)}\``;
|
|
1869
|
+
if (!server || !repo || !sha2) return `\`${cell(mdCode(label))}\``;
|
|
1829
1870
|
const frag = f.line ? `#L${f.line}` : "";
|
|
1830
|
-
return `[\`${cell(label)}\`](${server}/${repo}/blob/${sha2}/${f.file}${frag})`;
|
|
1871
|
+
return `[\`${cell(mdCode(label))}\`](${server}/${repo}/blob/${sha2}/${mdUrl(f.file)}${frag})`;
|
|
1831
1872
|
}
|
|
1832
1873
|
function renderSummary(input, env = process.env) {
|
|
1833
1874
|
const findings = orderFindings(input.findings);
|
|
@@ -2766,7 +2807,9 @@ function planClaudeHooks(cwd) {
|
|
|
2766
2807
|
apply: () => {
|
|
2767
2808
|
if (needPre) {
|
|
2768
2809
|
(hooks.PreToolUse ??= []).push({
|
|
2769
|
-
|
|
2810
|
+
// NotebookEdit is modelled by the adapter but was absent here, so
|
|
2811
|
+
// that branch was unreachable in the wiring we install. (P2-12.)
|
|
2812
|
+
matcher: "Bash|Edit|Write|MultiEdit|NotebookEdit",
|
|
2770
2813
|
hooks: [{ type: "command", command: HOOK_CMD }]
|
|
2771
2814
|
});
|
|
2772
2815
|
}
|
|
@@ -2861,6 +2904,7 @@ function git2(args, cwd) {
|
|
|
2861
2904
|
return execFileSync4("git", args, { cwd, encoding: "utf8", maxBuffer: 1 << 28 });
|
|
2862
2905
|
}
|
|
2863
2906
|
function resolveBase(base, cwd) {
|
|
2907
|
+
assertRev(base);
|
|
2864
2908
|
const rev = git2(["rev-parse", "--verify", `${base}^{commit}`], cwd).trim();
|
|
2865
2909
|
try {
|
|
2866
2910
|
return git2(["merge-base", rev, "HEAD"], cwd).trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tamperward",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.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",
|