coderifts 8.5.0 → 8.6.1
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/CHANGELOG.md +11 -0
- package/dist/.build-source-sha +1 -1
- package/dist/cli.js +100 -18
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 8.6.1 - 2026-09-09
|
|
6
|
+
|
|
7
|
+
The generated strict workflow pins contract-gate v0.9.2 (12a2673), following the gate release.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## 8.6.0 - 2026-09-08
|
|
11
|
+
|
|
12
|
+
- `--check` recognizes the SHA-pinned strict workflow (`coderifts/contract-gate@<40-hex>`, not only `@v0`), with states MISSING / PRESENT_UNPINNED / PRESENT_STALE / PRESENT_CURRENT; strict `--check` passes only PRESENT_CURRENT, and a generate-then-check round-trip exits 0.
|
|
13
|
+
- The generated strict workflow pins contract-gate v0.9.1 (df9d6a5), not the stale v0.9.0.
|
|
14
|
+
|
|
15
|
+
|
|
5
16
|
## 8.5.0 - 2026-09-07
|
|
6
17
|
|
|
7
18
|
The generated check-summary reads the rulesets API when there is no classic branch protection (a ruleset-governed repo no longer reports protection_not_configured). The quickstart's Atomic example carries the issuer-grant keyring. The strict workflow template pins contract-gate at d1c348d (v0.9.0), the current gate commit.
|
package/dist/.build-source-sha
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$comment": "GENERATED by scripts/build.js. sha256 over src/**.js + bin/**.js (path + bytes). test/build-freshness.test.js recomputes it; a mismatch means dist/cli.js is stale.",
|
|
3
|
-
"sha256": "
|
|
3
|
+
"sha256": "d6989104c6fcc12b512fc6dee0dd50970cd88364d9e2bec09c6c50fb019c5f14",
|
|
4
4
|
"file_count": 49
|
|
5
5
|
}
|
package/dist/cli.js
CHANGED
|
@@ -3028,7 +3028,7 @@ var require_package = __commonJS({
|
|
|
3028
3028
|
"package.json"(exports2, module2) {
|
|
3029
3029
|
module2.exports = {
|
|
3030
3030
|
name: "coderifts",
|
|
3031
|
-
version: "8.
|
|
3031
|
+
version: "8.6.1",
|
|
3032
3032
|
description: "Detect breaking API changes from the command line. Works locally or with the CodeRifts cloud API.",
|
|
3033
3033
|
author: "CodeRifts <hello@coderifts.com>",
|
|
3034
3034
|
license: "MIT",
|
|
@@ -231520,10 +231520,10 @@ var require_gate_pin = __commonJS({
|
|
|
231520
231520
|
"src/generated/gate-pin.json"(exports2, module2) {
|
|
231521
231521
|
module2.exports = {
|
|
231522
231522
|
repo: "coderifts/contract-gate",
|
|
231523
|
-
sha: "
|
|
231524
|
-
tag: "v0.9.
|
|
231523
|
+
sha: "12a2673d9bf094a1a97cb1387348018332a5c33f",
|
|
231524
|
+
tag: "v0.9.2",
|
|
231525
231525
|
resolved_from: "https://github.com/coderifts/contract-gate refs/tags/v0",
|
|
231526
|
-
resolved_at: "2026-09-
|
|
231526
|
+
resolved_at: "2026-09-09T18:05:11Z",
|
|
231527
231527
|
note: "STRICT template pins this full commit SHA (GitHub: only a full SHA is immutable). v0 is a tag we move on every release, so it is NOT a pin. Re-run scripts/generate-gate-pin.js on each gate release; Dependabot bumps adopters."
|
|
231528
231528
|
};
|
|
231529
231529
|
}
|
|
@@ -231554,6 +231554,7 @@ var require_contract_gate_workflow = __commonJS({
|
|
|
231554
231554
|
"use strict";
|
|
231555
231555
|
var fs = require("fs");
|
|
231556
231556
|
var path = require("path");
|
|
231557
|
+
var yaml = require_js_yaml();
|
|
231557
231558
|
var WORKFLOW_REL = ".github/workflows/coderifts.yml";
|
|
231558
231559
|
var GATE_ACTION = "coderifts/contract-gate@v0";
|
|
231559
231560
|
var GATE_PIN = require_gate_pin();
|
|
@@ -231743,16 +231744,71 @@ jobs:
|
|
|
231743
231744
|
writeFile(dest, body);
|
|
231744
231745
|
return { action: "create", relPath: WORKFLOW_REL, reason: "created", exitCode: 0 };
|
|
231745
231746
|
}
|
|
231746
|
-
|
|
231747
|
+
var WORKFLOW_STATES = Object.freeze({
|
|
231748
|
+
MISSING: "MISSING",
|
|
231749
|
+
PRESENT_CURRENT: "PRESENT_CURRENT",
|
|
231750
|
+
PRESENT_STALE: "PRESENT_STALE",
|
|
231751
|
+
PRESENT_UNPINNED: "PRESENT_UNPINNED"
|
|
231752
|
+
});
|
|
231753
|
+
var SHA_RE = /^[0-9a-f]{40}$/i;
|
|
231754
|
+
var GATE_USES_RE = /^\s*-?\s*uses:\s*coderifts\/contract-gate@([0-9a-f]{40}|v[^\s#]+)/m;
|
|
231755
|
+
function parseGateUsesRef(uses) {
|
|
231756
|
+
const raw = String(uses || "").trim();
|
|
231757
|
+
const at = raw.lastIndexOf("@");
|
|
231758
|
+
if (at <= 0) return null;
|
|
231759
|
+
if (raw.slice(0, at) !== "coderifts/contract-gate") return null;
|
|
231760
|
+
return raw.slice(at + 1);
|
|
231761
|
+
}
|
|
231762
|
+
function extractContractGateRef(body) {
|
|
231763
|
+
try {
|
|
231764
|
+
const doc = yaml.load(String(body || ""));
|
|
231765
|
+
const jobs = doc && doc.jobs && typeof doc.jobs === "object" ? doc.jobs : {};
|
|
231766
|
+
for (const job of Object.values(jobs)) {
|
|
231767
|
+
if (!job || typeof job !== "object" || !Array.isArray(job.steps)) continue;
|
|
231768
|
+
for (const step of job.steps) {
|
|
231769
|
+
if (!step || typeof step !== "object" || step.uses == null) continue;
|
|
231770
|
+
const ref = parseGateUsesRef(step.uses);
|
|
231771
|
+
if (ref) return ref;
|
|
231772
|
+
}
|
|
231773
|
+
}
|
|
231774
|
+
} catch {
|
|
231775
|
+
}
|
|
231776
|
+
const m = String(body || "").match(GATE_USES_RE);
|
|
231777
|
+
return m ? m[1] : null;
|
|
231778
|
+
}
|
|
231779
|
+
function workflowState(outDir, deps = {}) {
|
|
231747
231780
|
const exists = deps.exists || fs.existsSync.bind(fs);
|
|
231748
231781
|
const readFile = deps.readFile || ((p) => fs.readFileSync(p, "utf8"));
|
|
231782
|
+
const expected = GATE_PIN.sha;
|
|
231783
|
+
const empty = { state: WORKFLOW_STATES.MISSING, ref: null, sha: null, expected };
|
|
231749
231784
|
const fp = path.join(outDir, WORKFLOW_REL);
|
|
231750
|
-
if (!exists(fp)) return
|
|
231785
|
+
if (!exists(fp)) return empty;
|
|
231786
|
+
let body;
|
|
231751
231787
|
try {
|
|
231752
|
-
|
|
231788
|
+
body = readFile(fp);
|
|
231753
231789
|
} catch {
|
|
231754
|
-
return
|
|
231790
|
+
return empty;
|
|
231755
231791
|
}
|
|
231792
|
+
const ref = extractContractGateRef(body);
|
|
231793
|
+
if (!ref) return empty;
|
|
231794
|
+
if (SHA_RE.test(ref)) {
|
|
231795
|
+
const sha = ref.toLowerCase();
|
|
231796
|
+
return {
|
|
231797
|
+
state: sha === expected ? WORKFLOW_STATES.PRESENT_CURRENT : WORKFLOW_STATES.PRESENT_STALE,
|
|
231798
|
+
ref,
|
|
231799
|
+
sha,
|
|
231800
|
+
expected
|
|
231801
|
+
};
|
|
231802
|
+
}
|
|
231803
|
+
return { state: WORKFLOW_STATES.PRESENT_UNPINNED, ref, sha: null, expected };
|
|
231804
|
+
}
|
|
231805
|
+
function workflowPresent(outDir, deps = {}) {
|
|
231806
|
+
return workflowState(outDir, deps).state !== WORKFLOW_STATES.MISSING;
|
|
231807
|
+
}
|
|
231808
|
+
function workflowCheckOk(state, strict) {
|
|
231809
|
+
if (state === WORKFLOW_STATES.MISSING) return false;
|
|
231810
|
+
if (strict) return state === WORKFLOW_STATES.PRESENT_CURRENT;
|
|
231811
|
+
return true;
|
|
231756
231812
|
}
|
|
231757
231813
|
module2.exports = {
|
|
231758
231814
|
WORKFLOW_REL,
|
|
@@ -231766,7 +231822,11 @@ jobs:
|
|
|
231766
231822
|
pinnedActionRef,
|
|
231767
231823
|
ENFORCEMENT_DOC,
|
|
231768
231824
|
writeContractGateWorkflow,
|
|
231769
|
-
workflowPresent
|
|
231825
|
+
workflowPresent,
|
|
231826
|
+
workflowState,
|
|
231827
|
+
workflowCheckOk,
|
|
231828
|
+
extractContractGateRef,
|
|
231829
|
+
WORKFLOW_STATES
|
|
231770
231830
|
};
|
|
231771
231831
|
}
|
|
231772
231832
|
});
|
|
@@ -235063,9 +235123,13 @@ var require_init_agents = __commonJS({
|
|
|
235063
235123
|
var {
|
|
235064
235124
|
WORKFLOW_REL,
|
|
235065
235125
|
GATE_ACTION,
|
|
235126
|
+
GATE_ACTION_STRICT,
|
|
235127
|
+
GATE_PIN,
|
|
235066
235128
|
ENFORCEMENT_DOC,
|
|
235067
235129
|
writeContractGateWorkflow,
|
|
235068
|
-
|
|
235130
|
+
workflowState,
|
|
235131
|
+
workflowCheckOk,
|
|
235132
|
+
WORKFLOW_STATES
|
|
235069
235133
|
} = require_contract_gate_workflow();
|
|
235070
235134
|
var { writeAtomicV2, CONFIG_REL, WIRING_REL } = require_atomic_v2();
|
|
235071
235135
|
if (process.env.NO_COLOR) chalk.level = 0;
|
|
@@ -235075,7 +235139,7 @@ var require_init_agents = __commonJS({
|
|
|
235075
235139
|
1. repo-level MCP config (per host: .mcp.json / .cursor/mcp.json / .vscode/mcp.json)
|
|
235076
235140
|
2. generated agent rule files (reuses agent-setup)
|
|
235077
235141
|
3. host hook (Claude Code / VS Code Copilot via .claude/settings.json; Cursor via .cursor/hooks.json)
|
|
235078
|
-
4. .github/workflows/coderifts.yml (coderifts/contract-gate
|
|
235142
|
+
4. .github/workflows/coderifts.yml (default @v0; --strict pins coderifts/contract-gate@<40-hex>)
|
|
235079
235143
|
|
|
235080
235144
|
--hosts <list> claude, cursor, copilot, or all (default: all)
|
|
235081
235145
|
--no-hook Skip host hook install
|
|
@@ -235195,6 +235259,9 @@ ${USAGE}`
|
|
|
235195
235259
|
if (options.workflow === false) return false;
|
|
235196
235260
|
return true;
|
|
235197
235261
|
}
|
|
235262
|
+
function wantStrictWorkflow(options) {
|
|
235263
|
+
return !!(options.strict || options.atomicV2);
|
|
235264
|
+
}
|
|
235198
235265
|
function padVerb(verb) {
|
|
235199
235266
|
return String(verb).padEnd(7, " ");
|
|
235200
235267
|
}
|
|
@@ -235239,7 +235306,8 @@ ${USAGE}`
|
|
|
235239
235306
|
}
|
|
235240
235307
|
}
|
|
235241
235308
|
const workflowWanted = wantWorkflow(options);
|
|
235242
|
-
const
|
|
235309
|
+
const wf = workflowWanted ? workflowState(outDir, fsDeps) : { state: WORKFLOW_STATES.MISSING, ref: null, sha: null, expected: GATE_PIN.sha };
|
|
235310
|
+
const wfOk = !workflowWanted || workflowCheckOk(wf.state, wantStrictWorkflow(options));
|
|
235243
235311
|
const atomicWanted = options.atomicV2 === true;
|
|
235244
235312
|
const atomicMissing = [];
|
|
235245
235313
|
const atomicPresent = [];
|
|
@@ -235259,8 +235327,12 @@ ${USAGE}`
|
|
|
235259
235327
|
},
|
|
235260
235328
|
workflow: {
|
|
235261
235329
|
wanted: workflowWanted,
|
|
235262
|
-
present:
|
|
235263
|
-
|
|
235330
|
+
present: wfOk,
|
|
235331
|
+
state: workflowWanted ? wf.state : null,
|
|
235332
|
+
ref: wf.ref || null,
|
|
235333
|
+
sha: wf.sha || null,
|
|
235334
|
+
expected: wf.expected,
|
|
235335
|
+
missing: workflowWanted && !wfOk ? [WORKFLOW_REL] : []
|
|
235264
235336
|
},
|
|
235265
235337
|
atomicV2: {
|
|
235266
235338
|
wanted: atomicWanted,
|
|
@@ -235268,7 +235340,7 @@ ${USAGE}`
|
|
|
235268
235340
|
missing: atomicMissing
|
|
235269
235341
|
}
|
|
235270
235342
|
};
|
|
235271
|
-
const missingCount = mcpMissing.length + rulesMissing.length + hooksMissing.length + (workflowWanted && !
|
|
235343
|
+
const missingCount = mcpMissing.length + rulesMissing.length + hooksMissing.length + (workflowWanted && !wfOk ? 1 : 0) + atomicMissing.length;
|
|
235272
235344
|
return {
|
|
235273
235345
|
exitCode: missingCount === 0 ? 0 : 1,
|
|
235274
235346
|
pieces,
|
|
@@ -235299,7 +235371,16 @@ ${USAGE}`
|
|
|
235299
235371
|
if (!pieces.workflow.wanted) {
|
|
235300
235372
|
log(" CI workflow: skipped (--no-workflow)");
|
|
235301
235373
|
} else {
|
|
235302
|
-
|
|
235374
|
+
const st = pieces.workflow.state || WORKFLOW_STATES.MISSING;
|
|
235375
|
+
let detail = WORKFLOW_REL;
|
|
235376
|
+
if (st === WORKFLOW_STATES.PRESENT_CURRENT && pieces.workflow.sha) {
|
|
235377
|
+
detail = `${WORKFLOW_REL} @ ${pieces.workflow.sha}${GATE_PIN.tag ? ` # ${GATE_PIN.tag}` : ""}`;
|
|
235378
|
+
} else if (st === WORKFLOW_STATES.PRESENT_STALE && pieces.workflow.sha) {
|
|
235379
|
+
detail = `pinned ${pieces.workflow.sha.slice(0, 12)}\u2026; current ${String(pieces.workflow.expected || "").slice(0, 12)}\u2026`;
|
|
235380
|
+
} else if (st === WORKFLOW_STATES.PRESENT_UNPINNED && pieces.workflow.ref) {
|
|
235381
|
+
detail = `coderifts/contract-gate@${pieces.workflow.ref}`;
|
|
235382
|
+
}
|
|
235383
|
+
log(` CI workflow: ${st} (${detail})`);
|
|
235303
235384
|
}
|
|
235304
235385
|
if (pieces.atomicV2 && pieces.atomicV2.wanted) {
|
|
235305
235386
|
const st = pieces.atomicV2.missing.length === 0 ? "present" : "missing";
|
|
@@ -235426,12 +235507,13 @@ ${USAGE}`
|
|
|
235426
235507
|
if (!wantWorkflow(options)) {
|
|
235427
235508
|
items.push({ section: "workflow", action: "skip", relPath: WORKFLOW_REL, note: "--no-workflow" });
|
|
235428
235509
|
} else {
|
|
235429
|
-
const
|
|
235510
|
+
const strictWf = wantStrictWorkflow(options);
|
|
235511
|
+
const r = writeContractGateWorkflow({ outDir, dryRun, strict: strictWf, ...fsDeps });
|
|
235430
235512
|
items.push({
|
|
235431
235513
|
section: "workflow",
|
|
235432
235514
|
action: r.action,
|
|
235433
235515
|
relPath: r.relPath,
|
|
235434
|
-
note: r.action === "create" ?
|
|
235516
|
+
note: r.action === "create" ? strictWf ? `${GATE_ACTION_STRICT} (STRICT require-verified-monitoring + require-grant; cr.exec.v2)` : GATE_ACTION : r.reason
|
|
235435
235517
|
});
|
|
235436
235518
|
}
|
|
235437
235519
|
if (options.atomicV2) {
|
package/package.json
CHANGED