coderifts 4.9.0 → 4.10.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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.10.0
4
+
5
+ ### Added
6
+ - **`coderifts init --agents --strict`** writes the STRICT contract-gate
7
+ workflow: `require-verified-monitoring: 'true'` (plus attestation /
8
+ keyring inputs). The default template is unchanged (monitoring stays
9
+ commented / false).
10
+
3
11
  ## 4.9.0
4
12
 
5
13
  ### Fixed
package/README.md CHANGED
@@ -75,6 +75,7 @@ coderifts init --agents --hosts=cursor # Cursor only
75
75
  coderifts init --agents --hosts=copilot # GitHub Copilot / VS Code only
76
76
  coderifts init --agents --no-hook # skip host hook install
77
77
  coderifts init --agents --no-workflow # skip .github/workflows/coderifts.yml
78
+ coderifts init --agents --strict # STRICT: require-verified-monitoring: true
78
79
  coderifts init --agents --check # which of the four pieces are present
79
80
  ```
80
81
 
@@ -83,7 +84,7 @@ coderifts init --agents --check # which of the four pieces are present
83
84
  | **MCP config** | `.mcp.json` (Claude Code), `.cursor/mcp.json` (Cursor), `.vscode/mcp.json` (Copilot / VS Code) | Three shapes, never normalised into one: Claude `mcpServers` + `type: "http"` + `url`; Cursor `mcpServers` + `url` only (no `type`); Copilot **`servers`** (not `mcpServers`) + `type: "http"` + `url`. Never `httpUrl` (that is Gemini, extension-level — this command does not write it). |
84
85
  | **Agent rules** | generated host files via `agent-setup`'s writer | `AGENTS.md` is always written. Claude also gets `CLAUDE.md`; Cursor also gets `.cursor/rules/coderifts.mdc`; Copilot also gets `.github/copilot-instructions.md`. `--hosts=all` adds LangGraph and OpenAI instructions. (`coderifts init agent` is a different command — it writes a `.coderifts.yml` template.) |
85
86
  | **Host hook** | `.claude/settings.json`, `.cursor/hooks.json` | Reuses `hook install --claude` / `--cursor` (JSON-merge, backup, idempotent). Copilot shares Claude's `.claude/settings.json` — VS Code reads it by default. |
86
- | **CI workflow** | `.github/workflows/coderifts.yml` | `coderifts/contract-gate@v0`. `require-verified-monitoring` is commented (honest default: **false**) |
87
+ | **CI workflow** | `.github/workflows/coderifts.yml` | `coderifts/contract-gate@v0`. Default: `require-verified-monitoring` commented (honest default: **false**). `--strict`: the same file with `require-verified-monitoring: 'true'` |
87
88
 
88
89
  **Next manual step:** add `CODERIFTS_API_KEY` to the repository secrets. The
89
90
  CLI never writes a key anywhere.
package/bin/coderifts.js CHANGED
@@ -95,6 +95,7 @@ program
95
95
  .option('--hosts <list>', 'With --agents: claude, cursor, copilot, or all (default: all)', 'all')
96
96
  .option('--no-hook', 'With --agents: skip host hook install')
97
97
  .option('--no-workflow', 'With --agents: skip writing .github/workflows/coderifts.yml')
98
+ .option('--strict', 'With --agents: STRICT workflow (require-verified-monitoring: true)')
98
99
  .option('--dry-run', 'With --agents: print the plan without writing')
99
100
  .option('--check', 'With --agents: report which of the four pieces are present (no write)')
100
101
  .option('--out <dir>', 'With --agents: target directory (default: cwd)')
@@ -118,6 +119,7 @@ program
118
119
  dryRun: !!options.dryRun,
119
120
  check: !!options.check,
120
121
  out: options.out,
122
+ strict: !!options.strict,
121
123
  });
122
124
  if (result && typeof result.exitCode === 'number') {
123
125
  process.exitCode = result.exitCode;
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: "4.9.0",
3031
+ version: "4.10.0",
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",
@@ -210222,6 +210222,46 @@ jobs:
210222
210222
  # monitoring-attestation: \${{ vars.CODERIFTS_MONITORING_ATTESTATION }}
210223
210223
  # monitoring-keyring: \${{ github.workspace }}/.coderifts/monitoring-keys.json
210224
210224
  `;
210225
+ var STRICT_WORKFLOW_BODY = `# Written by \`coderifts init --agents --strict\`. Re-run is a no-op when this file already exists.
210226
+ #
210227
+ # STRICT template: require-verified-monitoring is ON.
210228
+ # This workflow POSTS the Check Run named exactly:
210229
+ # CodeRifts / contract-gate
210230
+ # It does NOT enable branch protection and it does NOT make that check required.
210231
+ # Turn the check on in repo settings to enforce (${ENFORCEMENT_DOC}).
210232
+ #
210233
+ # Copied from the gate repo example (examples/contract-gate.yml) \u2014 action at @v0.
210234
+ name: CodeRifts Contract Gate
210235
+
210236
+ # Run on EVERY pull request. Do NOT add paths: filters \u2014 a required check that
210237
+ # never runs leaves the PR mergeable (see ENFORCEMENT.md, "fail-closed on absence").
210238
+ on:
210239
+ pull_request:
210240
+
210241
+ permissions:
210242
+ checks: write
210243
+ contents: read
210244
+
210245
+ jobs:
210246
+ contract-gate:
210247
+ runs-on: ubuntu-latest
210248
+ steps:
210249
+ - uses: actions/checkout@v4
210250
+ with:
210251
+ # REQUIRED: the gate derives the change set from git diff base...head.
210252
+ fetch-depth: 0
210253
+
210254
+ - uses: ${GATE_ACTION}
210255
+ with:
210256
+ api-key: \${{ secrets.CODERIFTS_API_KEY }}
210257
+ # api-url: https://app.coderifts.com # override only for self-hosted
210258
+ require-verified-monitoring: 'true'
210259
+ monitoring-attestation: \${{ vars.CODERIFTS_MONITORING_ATTESTATION }}
210260
+ monitoring-keyring: \${{ github.workspace }}/.coderifts/monitoring-keys.json
210261
+ `;
210262
+ function workflowBody(strict) {
210263
+ return strict ? STRICT_WORKFLOW_BODY : WORKFLOW_BODY;
210264
+ }
210225
210265
  function writeContractGateWorkflow(opts = {}) {
210226
210266
  const outDir = opts.outDir;
210227
210267
  const dest = path.join(outDir, WORKFLOW_REL);
@@ -210232,6 +210272,7 @@ jobs:
210232
210272
  fs.writeFileSync(p, c, "utf8");
210233
210273
  });
210234
210274
  const dryRun = !!opts.dryRun;
210275
+ const body = workflowBody(!!opts.strict);
210235
210276
  if (exists(dest)) {
210236
210277
  let onDisk = "";
210237
210278
  try {
@@ -210239,13 +210280,13 @@ jobs:
210239
210280
  } catch {
210240
210281
  onDisk = "";
210241
210282
  }
210242
- const reason = onDisk === WORKFLOW_BODY ? "already present, identical" : "exists; installer does not clobber workflows";
210283
+ const reason = onDisk === body ? "already present, identical" : "exists; installer does not clobber workflows";
210243
210284
  return { action: "skip", relPath: WORKFLOW_REL, reason, exitCode: 0 };
210244
210285
  }
210245
210286
  if (dryRun) {
210246
210287
  return { action: "create", relPath: WORKFLOW_REL, reason: "created", exitCode: 0, dryRun: true };
210247
210288
  }
210248
- writeFile(dest, WORKFLOW_BODY);
210289
+ writeFile(dest, body);
210249
210290
  return { action: "create", relPath: WORKFLOW_REL, reason: "created", exitCode: 0 };
210250
210291
  }
210251
210292
  function workflowPresent(outDir, deps = {}) {
@@ -210262,6 +210303,7 @@ jobs:
210262
210303
  module2.exports = {
210263
210304
  WORKFLOW_REL,
210264
210305
  WORKFLOW_BODY,
210306
+ STRICT_WORKFLOW_BODY,
210265
210307
  GATE_ACTION,
210266
210308
  ENFORCEMENT_DOC,
210267
210309
  writeContractGateWorkflow,
@@ -210293,7 +210335,7 @@ var require_init_agents = __commonJS({
210293
210335
  workflowPresent
210294
210336
  } = require_contract_gate_workflow();
210295
210337
  if (process.env.NO_COLOR) chalk.level = 0;
210296
- var USAGE = `Usage: coderifts init --agents [--hosts=claude,cursor,copilot,all] [--no-hook] [--no-workflow] [--dry-run] [--check] [--out <dir>]
210338
+ var USAGE = `Usage: coderifts init --agents [--hosts=claude,cursor,copilot,all] [--no-hook] [--no-workflow] [--strict] [--dry-run] [--check] [--out <dir>]
210297
210339
 
210298
210340
  Wire this repository for governed agent work in ONE command:
210299
210341
  1. repo-level MCP config (per host: .mcp.json / .cursor/mcp.json / .vscode/mcp.json)
@@ -210304,6 +210346,7 @@ var require_init_agents = __commonJS({
210304
210346
  --hosts <list> claude, cursor, copilot, or all (default: all)
210305
210347
  --no-hook Skip host hook install
210306
210348
  --no-workflow Skip writing the CI workflow
210349
+ --strict STRICT workflow: require-verified-monitoring: true (default template stays false)
210307
210350
  --dry-run Print the plan without writing
210308
210351
  --check Report which of the four pieces are present (no write)
210309
210352
  --out <dir> Target directory (default: cwd)
@@ -210363,9 +210406,9 @@ ${USAGE}`
210363
210406
  return { hosts, allRules: false };
210364
210407
  }
210365
210408
  function agentFlagsRequireAgents(options = {}) {
210366
- return !!(options.check || options.dryRun || options.out || options.hosts != null && String(options.hosts) !== "all" || options.hook === false || options.workflow === false || options.noHook === true || options.noWorkflow === true);
210409
+ return !!(options.check || options.dryRun || options.out || options.hosts != null && String(options.hosts) !== "all" || options.hook === false || options.workflow === false || options.noHook === true || options.noWorkflow === true || options.strict === true);
210367
210410
  }
210368
- var AGENT_FLAGS_REQUIRE_AGENTS = "Error: --check/--dry-run/--out/--hosts/--no-hook/--no-workflow require --agents";
210411
+ var AGENT_FLAGS_REQUIRE_AGENTS = "Error: --check/--dry-run/--out/--hosts/--no-hook/--no-workflow/--strict require --agents";
210369
210412
  var AGENTS_NO_TEMPLATE = "Error: init --agents does not take a template. Did you mean `coderifts init --agents` (not `coderifts init agent`)?";
210370
210413
  function rulePathsForHosts(hosts, allRules) {
210371
210414
  const out = [SHARED_RULE];
@@ -210628,12 +210671,12 @@ ${USAGE}`
210628
210671
  if (!wantWorkflow(options)) {
210629
210672
  items.push({ section: "workflow", action: "skip", relPath: WORKFLOW_REL, note: "--no-workflow" });
210630
210673
  } else {
210631
- const r = writeContractGateWorkflow({ outDir, dryRun, ...fsDeps });
210674
+ const r = writeContractGateWorkflow({ outDir, dryRun, strict: !!options.strict, ...fsDeps });
210632
210675
  items.push({
210633
210676
  section: "workflow",
210634
210677
  action: r.action,
210635
210678
  relPath: r.relPath,
210636
- note: r.action === "create" ? `${GATE_ACTION}` : r.reason
210679
+ note: r.action === "create" ? options.strict ? `${GATE_ACTION} (STRICT require-verified-monitoring)` : GATE_ACTION : r.reason
210637
210680
  });
210638
210681
  }
210639
210682
  const created = items.filter((i) => i.action === "create").length;
@@ -241087,7 +241130,7 @@ program.command("registry-gate [dir]").description("Admit a directory of OpenAPI
241087
241130
  process.exitCode = code;
241088
241131
  process.exit(code);
241089
241132
  });
241090
- program.command("init [template]").description("Generate a .coderifts.yml from a policy template, or wire governed agent work (--agents)").option("--agents", "Wire this repo for governed agent work (MCP config, rule files, host hook, CI gate)").option("--hosts <list>", "With --agents: claude, cursor, copilot, or all (default: all)", "all").option("--no-hook", "With --agents: skip host hook install").option("--no-workflow", "With --agents: skip writing .github/workflows/coderifts.yml").option("--dry-run", "With --agents: print the plan without writing").option("--check", "With --agents: report which of the four pieces are present (no write)").option("--out <dir>", "With --agents: target directory (default: cwd)").action(async (template, options) => {
241133
+ program.command("init [template]").description("Generate a .coderifts.yml from a policy template, or wire governed agent work (--agents)").option("--agents", "Wire this repo for governed agent work (MCP config, rule files, host hook, CI gate)").option("--hosts <list>", "With --agents: claude, cursor, copilot, or all (default: all)", "all").option("--no-hook", "With --agents: skip host hook install").option("--no-workflow", "With --agents: skip writing .github/workflows/coderifts.yml").option("--strict", "With --agents: STRICT workflow (require-verified-monitoring: true)").option("--dry-run", "With --agents: print the plan without writing").option("--check", "With --agents: report which of the four pieces are present (no write)").option("--out <dir>", "With --agents: target directory (default: cwd)").action(async (template, options) => {
241091
241134
  const {
241092
241135
  runInitAgents,
241093
241136
  agentFlagsRequireAgents,
@@ -241106,7 +241149,8 @@ program.command("init [template]").description("Generate a .coderifts.yml from a
241106
241149
  workflow: options.workflow,
241107
241150
  dryRun: !!options.dryRun,
241108
241151
  check: !!options.check,
241109
- out: options.out
241152
+ out: options.out,
241153
+ strict: !!options.strict
241110
241154
  });
241111
241155
  if (result && typeof result.exitCode === "number") {
241112
241156
  process.exitCode = result.exitCode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coderifts",
3
- "version": "4.9.0",
3
+ "version": "4.10.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",