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 +66 -0
- package/README.md +47 -7
- package/bin/coderifts.js +66 -4
- package/dist/cli.js +5010 -1416
- package/package.json +2 -2
- package/scripts/assert-guard-major.js +2 -1
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
`
|
|
109
|
-
**
|
|
110
|
-
|
|
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
|
|
92
|
-
.
|
|
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('--
|
|
291
|
-
.option('--
|
|
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
|
});
|