coderifts 8.0.1 → 8.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coderifts",
3
- "version": "8.0.1",
3
+ "version": "8.1.0",
4
4
  "description": "Detect breaking API changes from the command line. Works locally or with the CodeRifts cloud API.",
5
5
  "author": "CodeRifts <hello@coderifts.com>",
6
6
  "license": "MIT",
@@ -36,7 +36,7 @@
36
36
  "homepage": "https://coderifts.com",
37
37
  "bugs": "https://github.com/coderifts/app/issues",
38
38
  "engines": {
39
- "node": ">=18.0.0"
39
+ "node": ">=20.0.0"
40
40
  },
41
41
  "scripts": {
42
42
  "build": "node scripts/copy-corpus.js && node scripts/build.js",
@@ -46,7 +46,7 @@
46
46
  "test": "node --test test/*.test.js"
47
47
  },
48
48
  "dependencies": {
49
- "@coderifts/agent-guard": "^15.1.0",
49
+ "@coderifts/agent-guard": "^16.0.0",
50
50
  "chalk": "^4.1.2",
51
51
  "cli-table3": "^0.6.4",
52
52
  "commander": "^12.0.0",
@@ -60,7 +60,7 @@
60
60
  "json-schema-ref-parser": "npm:@apidevtools/json-schema-ref-parser@^11.7.3",
61
61
  "form-data": "^4.0.6",
62
62
  "axios": ">=1.18.0",
63
- "fast-uri": ">=3.1.5",
63
+ "fast-uri": ">=4.1.3",
64
64
  "brace-expansion": "5.0.9"
65
65
  },
66
66
  "devDependencies": {
@@ -73,13 +73,16 @@
73
73
  * asVerifiedDeployReceiptView, DEPLOY_RECEIPT_VIEW_SPEC and matchGlob — no DeployGateReason
74
74
  * exhaustive switch, no V2 config-conflict throw. The raise is installer-facing: the range
75
75
  * is what `npm i -g coderifts` resolves.)
76
+ * 8.1.0: floor raised to 16 (published guard 16.0.0 is on npm; 16 makes UNGUARDED_MUTATION
77
+ * fail-closed the default. The CLI range must match so `npm i -g coderifts` installs the guard
78
+ * whose default the docs describe, not the 15.x advisory-default it shipped alongside before.)
76
79
  */
77
80
 
78
81
  const fs = require('fs');
79
82
  const path = require('path');
80
83
 
81
84
  /** Minimum acceptable major for @coderifts/agent-guard in THIS package (the CLI). */
82
- const MIN_GUARD_MAJOR = 15;
85
+ const MIN_GUARD_MAJOR = 16;
83
86
  const DEP = '@coderifts/agent-guard';
84
87
 
85
88
  /**
package/scripts/build.js CHANGED
@@ -8,6 +8,8 @@
8
8
  */
9
9
 
10
10
  const path = require('path');
11
+ const fs = require('fs');
12
+ const crypto = require('crypto');
11
13
  const esbuild = require('esbuild');
12
14
 
13
15
  const stub = path.join(__dirname, '..', 'src', 'logger-stub.js');
@@ -35,6 +37,48 @@ esbuild.build({
35
37
  });
36
38
  },
37
39
  }],
40
+ }).then(() => {
41
+ // ── 1353: build freshness ────────────────────────────────────────────────────────────────
42
+ //
43
+ // MEASURED 2026-09-04: dist/cli.js still printed the pre-1305 verdict a day after the source
44
+ // fix. `prepublishOnly` DOES run the build — the premise that it did not is wrong — so the
45
+ // PUBLISHED artifact was never at risk. The gap is LOCAL: dist/ is gitignored and the globally
46
+ // linked `coderifts` points straight at it, so a developer edits src, sees a green suite over
47
+ // src, and runs a stale binary. So does the reviewer.
48
+ //
49
+ // The build records a fingerprint of the sources it consumed; test/build-freshness.test.js
50
+ // recomputes it and fails when dist is behind — catching what a suite over src alone cannot.
51
+ //
52
+ // CONTENT-ADDRESSED, not timestamps: mtimes move on checkout, rebase and copy without the bytes
53
+ // changing, and a freshness check that cries wolf gets deleted.
54
+ const root = path.join(__dirname, '..');
55
+ const files = [];
56
+ const walk = (dir) => {
57
+ if (!fs.existsSync(dir)) return;
58
+ for (const e of fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
59
+ if (e.name === 'node_modules' || e.name.startsWith('.')) continue;
60
+ const full = path.join(dir, e.name);
61
+ if (e.isDirectory()) walk(full);
62
+ else if (e.name.endsWith('.js')) files.push(full);
63
+ }
64
+ };
65
+ walk(path.join(root, 'src'));
66
+ walk(path.join(root, 'bin'));
67
+ const h = crypto.createHash('sha256');
68
+ for (const f of files.sort()) {
69
+ h.update(path.relative(root, f));
70
+ h.update('\0');
71
+ h.update(fs.readFileSync(f));
72
+ h.update('\0');
73
+ }
74
+ const sha256 = h.digest('hex');
75
+ fs.writeFileSync(path.join(root, 'dist', '.build-source-sha'), `${JSON.stringify({
76
+ $comment: 'GENERATED by scripts/build.js. sha256 over src/**.js + bin/**.js (path + bytes). '
77
+ + 'test/build-freshness.test.js recomputes it; a mismatch means dist/cli.js is stale.',
78
+ sha256,
79
+ file_count: files.length,
80
+ }, null, 2)}\n`);
81
+ process.stdout.write(`build: source fingerprint ${sha256.slice(0, 12)}… over ${files.length} files\n`);
38
82
  }).catch((err) => {
39
83
  console.error(err);
40
84
  process.exit(1);