coderifts 4.4.0 → 4.6.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,71 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.6.0
4
+
5
+ **Version pick:** the parallel Cursor-hook round claimed **4.5.0**
6
+ (`8eab5f9`, `packages/cli/package.json` 4.5.0). This command takes the next
7
+ free minor. (4.5.0's CHANGELOG entry was not written in that round; the
8
+ commit message is the record of `coderifts cursor-hook` + `hook install
9
+ --cursor`.)
10
+
11
+ ### Added
12
+ - **`coderifts init --agents`** — one command that wires a repository for
13
+ governed agent work. Four pieces:
14
+ 1. repo-level MCP config per host (never one file for all):
15
+ Claude Code `.mcp.json` uses `mcpServers.coderifts` with **`type":"http"`
16
+ + `url`** (a `url` without `type` is skipped — measured
17
+ code.claude.com/docs/en/mcp 2026-08-22); Cursor `.cursor/mcp.json` uses
18
+ **`url` and no `type`** (measured docs.cursor.com). Gemini `httpUrl` is
19
+ extension-level — this command does not write it.
20
+ 2. generated agent rule files, via **`writeAgentHostFiles`** extracted from
21
+ `agent-setup` (not a second copy). Cursor `.mdc` is included because the
22
+ 4.5.0 round landed it.
23
+ 3. host hook where one exists: `installClaudeHook` and (4.5.0)
24
+ `installCursorHook` — JSON-merge, `.bak`, idempotent. `--no-hook` skips.
25
+ 4. `.github/workflows/coderifts.yml` at `coderifts/contract-gate@v0`, with
26
+ `require-verified-monitoring` commented (honest default: false).
27
+ `--no-workflow` skips. Existing workflow files are never clobbered.
28
+ - `--hosts=claude,cursor,all` (default `all`), `--dry-run` (plan, no write),
29
+ `--check` (which of the four pieces are present).
30
+ - Idempotent re-run: unchanged files are skipped; JSON MCP configs are merged
31
+ (other servers preserved, `.bak` alongside any file it modifies).
32
+ - Summary names created / merged / skipped and WHY, the next manual step
33
+ (add `CODERIFTS_API_KEY` to repo secrets — the CLI never writes a key),
34
+ and what this does **not** do: enable branch protection
35
+ (ENFORCEMENT.md), make raw host tools inescapable, or enforce the
36
+ workflow until the required check is turned on in repo settings.
37
+
38
+ ### Shared vs new
39
+ - **Shared:** `writeAgentHostFiles` (extracted from `agent-setup`);
40
+ `installClaudeHook` / `installCursorHook` (`silent` + `dryRun` passed
41
+ through).
42
+ - **New:** `src/mcp-repo-config.js`, `src/contract-gate-workflow.js`,
43
+ `src/commands/init-agents.js`.
44
+
45
+ ## 4.4.1
46
+
47
+ **Sequencing:** `@coderifts/agent-guard` **9.0.0** is the verifier of record
48
+ for `deploy-gate` (TOKEN mode). Publish **guard 9.0.0 first**, then this CLI.
49
+ 4.4.0 against 9.0.0 would DENY `unverified_receipt_view` (unstamped computed
50
+ view).
51
+
52
+ ### Changed
53
+ - **TOKEN mode.** `deployBind` passes `{ token, decision_result, registry |
54
+ pinnedKeyPem }` to `deployGate`. The CLI never sends an unstamped
55
+ `currently_authorized` view. The §154 matrix view path is stamped with
56
+ `asVerifiedDeployReceiptView` (`view_spec: 'deploy-receipt-view.v1'`).
57
+ - **One verdict, one WHY.** Guard 9.0.0 is the cause. The app kernel still
58
+ verifies for 842 rendering (corroboration + envelope `blocking_reasons`)
59
+ but does not produce a second deny. `authz_reason` equals the gate
60
+ `reason`. JSON `causes_agree` is true when kernel maps to the same cause.
61
+ - **`MIN_GUARD_MAJOR` 8 → 9.** Dependency range `^9.0.0`.
62
+
63
+ ### Migration
64
+ - Requires `@coderifts/agent-guard@9.0.0`. Local test against unpublished
65
+ 9.0.0: install the packed tarball into `node_modules` while keeping the
66
+ declared range `^9.0.0` (`file:` is rejected by `assert-guard-major` at
67
+ publish).
68
+
3
69
  ## 4.4.0
4
70
 
5
71
  **Behaviour change (breaking for anyone relying on a forged receipt file)** —
package/README.md CHANGED
@@ -61,6 +61,42 @@ Interactive configuration generator. Creates a `.coderifts.yml` file with indust
61
61
  - `microservices-internal`
62
62
  - `ai-agent-platform`
63
63
 
64
+ ### `coderifts init --agents`
65
+
66
+ One command that wires **this repository** for governed agent work. Re-run is
67
+ a no-op. Existing JSON is merged (never clobbered); a `.bak` sits next to any
68
+ file it modifies.
69
+
70
+ ```bash
71
+ coderifts init --agents # all hosts, all four pieces
72
+ coderifts init --agents --dry-run # plan only — writes nothing
73
+ coderifts init --agents --hosts=claude # Claude Code only
74
+ coderifts init --agents --hosts=cursor # Cursor only
75
+ coderifts init --agents --no-hook # skip host hook install
76
+ coderifts init --agents --no-workflow # skip .github/workflows/coderifts.yml
77
+ coderifts init --agents --check # which of the four pieces are present
78
+ ```
79
+
80
+ | Piece | What it writes | Host-specific shape |
81
+ |-------|----------------|---------------------|
82
+ | **MCP config** | `.mcp.json` (Claude Code), `.cursor/mcp.json` (Cursor) | Claude: `mcpServers.coderifts` with `type: "http"` + `url`. Cursor: `url` only (no `type`). Never `httpUrl` (that is Gemini, extension-level — this command does not write it). |
83
+ | **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`. `--hosts=all` adds Copilot, LangGraph, and OpenAI instructions. (`coderifts init agent` is a different command — it writes a `.coderifts.yml` template.) |
84
+ | **Host hook** | `.claude/settings.json`, `.cursor/hooks.json` | Reuses `hook install --claude` / `--cursor` (JSON-merge, backup, idempotent) |
85
+ | **CI workflow** | `.github/workflows/coderifts.yml` | `coderifts/contract-gate@v0`. `require-verified-monitoring` is commented (honest default: **false**) |
86
+
87
+ **Next manual step:** add `CODERIFTS_API_KEY` to the repository secrets. The
88
+ CLI never writes a key anywhere.
89
+
90
+ **This command does not:** enable branch protection (see
91
+ [ENFORCEMENT.md](https://github.com/coderifts/contract-gate/blob/main/ENFORCEMENT.md)),
92
+ make raw host tools inescapable, or enforce the workflow until
93
+ `CodeRifts / contract-gate` is a required check in repo settings.
94
+
95
+ The three separate commands this replaces for a fresh repo: `coderifts
96
+ agent-setup`, `coderifts hook install --claude` (and `--cursor`), plus a
97
+ hand-copied workflow file. Repo-level MCP config was generated by nothing
98
+ before 4.6.0.
99
+
64
100
  ### `coderifts login`
65
101
 
66
102
  Save your CodeRifts API key for cloud features. Get a free key at [app.coderifts.com/api/signup](https://app.coderifts.com/api/signup).
@@ -101,13 +137,17 @@ Gate a **deploy** on the current `{ environment, artifact }` using a **signed**
101
137
  preflight receipt. Fail-closed by default (842 / hook pattern). The CD sibling of
102
138
  `publish-gate` / the merge-gate App check.
103
139
 
104
- The CLI **verifies locally** (Ed25519 against the key registry, kid status /
105
- retired-window, body-hash over the decision envelope, expiry with ID104
106
- leeway, intended-context bind of operation / environment / artifact /
107
- fingerprint). Crypto is the app kernel (`verifyReceipt` +
108
- `evaluateVerifyAuthorization`)not reimplemented here. Then it binds the
109
- **computed** receipt view into the validated `deployGate` from
110
- `@coderifts/agent-guard`. No scoring is reimplemented.
140
+ **Verification contract split (4.4.1 / guard 9.0.0):**
141
+
142
+ - **Verdict:** `@coderifts/agent-guard` `deployGate` **TOKEN mode** is the
143
+ verifier of record. The CLI passes `{ token, decision_result, registry |
144
+ pinnedKeyPem }` — it never sends an unstamped `currently_authorized` view.
145
+ - **WHY (842):** the CLI still runs the app kernel (`verifyReceipt` +
146
+ `evaluateVerifyAuthorization`) to corroborate `verify_status` and to print
147
+ envelope `blocking_reasons`. That is **not** a second verdict: one cause
148
+ (the gate `reason`), one WHY.
149
+
150
+ Crypto is not reimplemented in the CLI. No scoring is reimplemented.
111
151
 
112
152
  **`--receipt` contract:** the file MUST carry the signed chain receipt token
113
153
  (`token` / `chain_receipt` / `receipt.token` / `decision_result.receipt.token`)
package/bin/coderifts.js CHANGED
@@ -86,10 +86,49 @@ program
86
86
  });
87
87
 
88
88
  // ── init command ──
89
+ // `init [template]` writes a policy YAML. `init --agents` is a different path:
90
+ // it wires MCP config + agent rules + host hook + the CI gate workflow.
89
91
  program
90
92
  .command('init [template]')
91
- .description('Generate a .coderifts.yml from a policy template (startup, growth, fintech, public-api, microservices)')
92
- .action(async (template) => {
93
+ .description('Generate a .coderifts.yml from a policy template, or wire governed agent work (--agents)')
94
+ .option('--agents', 'Wire this repo for governed agent work (MCP config, rule files, host hook, CI gate)')
95
+ .option('--hosts <list>', 'With --agents: claude, cursor, or all (default: all)', 'all')
96
+ .option('--no-hook', 'With --agents: skip host hook install')
97
+ .option('--no-workflow', 'With --agents: skip writing .github/workflows/coderifts.yml')
98
+ .option('--dry-run', 'With --agents: print the plan without writing')
99
+ .option('--check', 'With --agents: report which of the four pieces are present (no write)')
100
+ .option('--out <dir>', 'With --agents: target directory (default: cwd)')
101
+ .action(async (template, options) => {
102
+ const {
103
+ runInitAgents,
104
+ agentFlagsRequireAgents,
105
+ AGENT_FLAGS_REQUIRE_AGENTS,
106
+ AGENTS_NO_TEMPLATE,
107
+ } = require('../src/commands/init-agents');
108
+ if (options.agents) {
109
+ if (template) {
110
+ console.error(AGENTS_NO_TEMPLATE);
111
+ process.exitCode = 1;
112
+ return;
113
+ }
114
+ const result = runInitAgents({
115
+ hosts: options.hosts,
116
+ hook: options.hook,
117
+ workflow: options.workflow,
118
+ dryRun: !!options.dryRun,
119
+ check: !!options.check,
120
+ out: options.out,
121
+ });
122
+ if (result && typeof result.exitCode === 'number') {
123
+ process.exitCode = result.exitCode;
124
+ }
125
+ return;
126
+ }
127
+ if (agentFlagsRequireAgents(options)) {
128
+ console.error(AGENT_FLAGS_REQUIRE_AGENTS);
129
+ process.exitCode = 1;
130
+ return;
131
+ }
93
132
  const { init } = require('../src/commands/init');
94
133
  await init(template);
95
134
  });
@@ -278,6 +317,27 @@ program
278
317
  }
279
318
  });
280
319
 
320
+ // ── cursor-hook — Cursor preToolUse ({"permission":"deny"} on stdout; also exit 2) ──
321
+ program
322
+ .command('cursor-hook')
323
+ .description(
324
+ 'Cursor preToolUse gate: deny contract-touching Write|Delete on BLOCK/STOP/REQUEST_APPROVAL. '
325
+ + 'Emits {permission,user_message,agent_message} on stdout. Cursor does not enforce "ask" for '
326
+ + 'preToolUse, so REQUEST_APPROVAL maps to deny. Fail-closed on unparseable stdin.',
327
+ )
328
+ .addHelpText('after', () => {
329
+ const { USAGE } = require('../src/commands/cursor-hook');
330
+ return `\n${USAGE}\n`;
331
+ })
332
+ .action(async () => {
333
+ const { runCursorHook } = require('../src/commands/cursor-hook');
334
+ const fsMod = require('fs');
335
+ let stdin = '';
336
+ try { stdin = fsMod.readFileSync(0, 'utf8'); } catch { stdin = ''; }
337
+ const code = await runCursorHook({ argv: process.argv.slice(3), stdin });
338
+ if (typeof code === 'number') process.exitCode = code;
339
+ });
340
+
281
341
  // ── hook command group ──
282
342
  const hookCmd = program
283
343
  .command('hook')
@@ -287,12 +347,14 @@ hookCmd
287
347
  .command('install')
288
348
  .description('Install the CodeRifts pre-push hook in the current Git repo')
289
349
  .option('--claude', 'Write Claude Code PreToolUse hook to .claude/settings.json (JSON-merge)')
290
- .option('--global', 'With --claude: write ~/.claude/settings.json instead of the project file')
291
- .option('--log <path>', 'With --claude: embed CODERIFTS_GUARD_EVENT_LOG and CODERIFTS_SESSION_ID in the command')
350
+ .option('--cursor', 'Write Cursor preToolUse hook to .cursor/hooks.json (JSON-merge, failClosed:true)')
351
+ .option('--global', 'With --claude/--cursor: write the ~/ config instead of the project file')
352
+ .option('--log <path>', 'With --claude/--cursor: embed CODERIFTS_GUARD_EVENT_LOG and CODERIFTS_SESSION_ID in the command')
292
353
  .action((options) => {
293
354
  const { install } = require('../src/commands/hook');
294
355
  install({
295
356
  claude: !!options.claude,
357
+ cursor: !!options.cursor,
296
358
  global: !!options.global,
297
359
  log: options.log,
298
360
  });