coderifts 3.2.0 → 3.3.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/README.md +188 -2
- package/bin/coderifts.js +34 -4
- package/dist/cli.js +3864 -470
- package/package.json +4 -3
- package/scripts/assert-guard-major.js +125 -0
package/README.md
CHANGED
|
@@ -94,6 +94,57 @@ is **never** treated as a silent NEW_ARTIFACT pass.
|
|
|
94
94
|
|
|
95
95
|
On success the command prints a **receipt reference** when the preflight path issues one.
|
|
96
96
|
|
|
97
|
+
### `coderifts deploy-gate`
|
|
98
|
+
|
|
99
|
+
Gate a **deploy** on the current `{ environment, artifact }` using a preflight
|
|
100
|
+
receipt (phase-1 advisory). The CD sibling of `publish-gate` / the merge-gate
|
|
101
|
+
App check. Composes the validated `deployGate` from `@coderifts/agent-guard` —
|
|
102
|
+
the CLI only binds env + artifact + receipt + observed CD enforcement. No
|
|
103
|
+
scoring is reimplemented here.
|
|
104
|
+
|
|
105
|
+
Phase 1 **reports** and exits **0** even on a gate deny, unless the step is
|
|
106
|
+
marked enforcing (`--enforce` or `CODERIFTS_DEPLOY_ENFORCE=true`), in which
|
|
107
|
+
case a failure exits **1**. Missing `--env` / `--artifact` is a usage error
|
|
108
|
+
(exit **1**). No receipt → pending (never a fabricated allow).
|
|
109
|
+
|
|
110
|
+
| Flag | Description | Default |
|
|
111
|
+
|------|-------------|---------|
|
|
112
|
+
| `--env <environment>` | Target environment (e.g. `production`, `staging`) | required |
|
|
113
|
+
| `--artifact <artifact_id>` | Immutable artifact identity (content digest or commit SHA) | required |
|
|
114
|
+
| `--receipt <file>` | Path to the deploy-scoped receipt JSON from preflight | none |
|
|
115
|
+
| `--json` | Binding result as JSON | `false` |
|
|
116
|
+
| `--enforce` | Attest ENFORCING and exit non-zero on a gate failure | `false` |
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
coderifts deploy-gate --env production --artifact "$SHA" --receipt receipt.json
|
|
120
|
+
coderifts deploy-gate --env production --artifact "$SHA" --receipt receipt.json --enforce
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### `coderifts outcome <kind>`
|
|
124
|
+
|
|
125
|
+
Report a **post-hoc** observed outcome for a past `decision_id` to
|
|
126
|
+
`POST /api/v1/outcomes`. Records the **caller's assertion** (your deploy job
|
|
127
|
+
knows success/failure) — the command does **not** itself verify the deploy.
|
|
128
|
+
|
|
129
|
+
`kind` is a closed set: `deploy_succeeded`, `deploy_failed`, `rolled_back`,
|
|
130
|
+
`consumer_break_reported`, `remediation_verified_working`,
|
|
131
|
+
`false_positive_reported`, `other_reported`.
|
|
132
|
+
|
|
133
|
+
Requires a cloud API key (`coderifts login` or `CODERIFTS_API_KEY`). Reporter
|
|
134
|
+
is derived from the key. Exit **0** on success, **1** on usage / API error.
|
|
135
|
+
|
|
136
|
+
| Flag | Description | Default |
|
|
137
|
+
|------|-------------|---------|
|
|
138
|
+
| `--decision <decision_id>` | `decision_result.decision_id` (required) | none |
|
|
139
|
+
| `--observed-at <iso>` | When the outcome was observed (ISO-8601) | now |
|
|
140
|
+
| `--details <json>` | Optional JSON object/array bound to the row | none |
|
|
141
|
+
| `--json` | Print the API response JSON | `false` |
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
coderifts outcome deploy_succeeded --decision "$DECISION_ID"
|
|
145
|
+
coderifts outcome deploy_failed --decision "$DECISION_ID" --json
|
|
146
|
+
```
|
|
147
|
+
|
|
97
148
|
### `coderifts registry-gate [dir]`
|
|
98
149
|
|
|
99
150
|
Local **registry admission gate** for a directory of OpenAPI/Swagger specs
|
|
@@ -185,6 +236,64 @@ git config coderifts.specPath api/openapi.yaml # default if omitted
|
|
|
185
236
|
- **User** `~/.claude/settings.json` — personal; applies to all projects on this machine.
|
|
186
237
|
- Matcher is case-sensitive tool names/regex. Exit-2 blocking is **Claude Code** semantics; the same decision discipline at push-time is the git pre-push hook above.
|
|
187
238
|
|
|
239
|
+
**`CODERIFTS_STRICT` (opt-in, not a package guarantee):** env `1` or `true`
|
|
240
|
+
(case-insensitive) hardens **enforcement-relevant** soft sites into **exit 2
|
|
241
|
+
(BLOCK)** — “governance did not run” must not read as ALLOW. Hardened: missing
|
|
242
|
+
API key; API unreachable (network/timeout/error); disk unreadable on the
|
|
243
|
+
contract path; Edit/MultiEdit apply failure on the contract path. Still soft
|
|
244
|
+
even in strict: non-spec path, identical content, unparseable stdin, missing
|
|
245
|
+
`file_path`, WARN/REQUIRE_APPROVAL (governance ran), real ALLOW. Unset/empty →
|
|
246
|
+
identical to the default soft UX. Hosts choose strict for CI/prod.
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
CODERIFTS_STRICT=1 coderifts claude-hook
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### `coderifts status [repo]`
|
|
253
|
+
|
|
254
|
+
**Read-only** cross-layer enforcement report (Runtime / Merge / Deploy, plus
|
|
255
|
+
Content). Calls `GET /api/v1/enforcement-status` and prints the statuses the
|
|
256
|
+
endpoint measured — no GitHub writes, no branch-protection changes. Pair with
|
|
257
|
+
`coderifts enforce` (that command **acts**; this one only **shows**).
|
|
258
|
+
|
|
259
|
+
Requires a cloud API key. Distinct from `coderifts hook status` (local
|
|
260
|
+
pre-push hook install state). Exit **0** on a successful read, **1** on
|
|
261
|
+
missing/invalid repo, missing key, or API error.
|
|
262
|
+
|
|
263
|
+
| Flag | Description | Default |
|
|
264
|
+
|------|-------------|---------|
|
|
265
|
+
| `[repo]` / `--repo <owner/repo>` | Repository | none (required) |
|
|
266
|
+
| `--json` | Machine-readable JSON (raw API body) | `false` |
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
coderifts status owner/repo
|
|
270
|
+
coderifts status --repo owner/repo --json
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### `coderifts enforce [repo]`
|
|
274
|
+
|
|
275
|
+
Close enforcement gaps by chaining existing setup commands: Merge →
|
|
276
|
+
`setup-required-check`; Runtime → `hook install` (apply only) + agent-guard
|
|
277
|
+
guidance; Deploy → `deploy-gate` CD-step guidance; Content → guidance only.
|
|
278
|
+
**Dry-run by default** (`--apply` to mutate). Does not bypass underlying
|
|
279
|
+
command safety. Does not label Runtime/Content as server ENFORCING. Does not
|
|
280
|
+
upgrade UNKNOWN.
|
|
281
|
+
|
|
282
|
+
Requires a cloud API key for the status read. Merge `--apply` uses your local
|
|
283
|
+
`gh` credentials, not the CodeRifts API key. Exit **0** when no chained step
|
|
284
|
+
failed, **1** on missing repo/key, API error, or any apply failure.
|
|
285
|
+
|
|
286
|
+
| Flag | Description | Default |
|
|
287
|
+
|------|-------------|---------|
|
|
288
|
+
| `[repo]` / `--repo <owner/repo>` | Repository | none (required) |
|
|
289
|
+
| `--apply` | Run underlying setup commands | dry-run |
|
|
290
|
+
| `--json` | Machine-readable JSON result | `false` |
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
coderifts enforce owner/repo
|
|
294
|
+
coderifts enforce --repo owner/repo --apply
|
|
295
|
+
```
|
|
296
|
+
|
|
188
297
|
### Agent host files (`coderifts agent-setup`)
|
|
189
298
|
|
|
190
299
|
Writes the six CodeRifts agent-host rule files into the current repo (or `--out <dir>`):
|
|
@@ -210,6 +319,28 @@ re-sync with `node scripts/sync-cli-agent-host-embed.js` when the rule source ch
|
|
|
210
319
|
|
|
211
320
|
Policy template for agent/MCP APIs: `coderifts init ai-agent` (aliases: `agent`, `mcp`).
|
|
212
321
|
|
|
322
|
+
### Copilot MCP configs (`coderifts copilot-setup`)
|
|
323
|
+
|
|
324
|
+
Writes GitHub Copilot MCP configs from the canonical tool names. Root keys
|
|
325
|
+
differ: VS Code uses `servers`; Copilot cloud Settings paste uses `mcpServers`.
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
coderifts copilot-setup # write (skip existing files)
|
|
329
|
+
coderifts copilot-setup --force # overwrite
|
|
330
|
+
coderifts copilot-setup --check # drift vs embedded content (exit 1 on drift)
|
|
331
|
+
coderifts copilot-setup --out ./docs # custom root
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
| Flag | Description | Default |
|
|
335
|
+
|------|-------------|---------|
|
|
336
|
+
| `--out <dir>` | Target directory | cwd |
|
|
337
|
+
| `--check` | Exit 0 if on-disk files match embedded content; exit 1 on drift | `false` |
|
|
338
|
+
| `--force` | Overwrite existing files | skip collisions |
|
|
339
|
+
|
|
340
|
+
Writes: `.vscode/mcp.json`, `copilot-cloud-agent-mcp.json`,
|
|
341
|
+
`copilot-custom-agent-mcp.frontmatter.md`, `docs/copilot-mcp.md`. Unknown flags
|
|
342
|
+
exit 1 (never silently ignored).
|
|
343
|
+
|
|
213
344
|
### Required check wizard (`coderifts setup-required-check`)
|
|
214
345
|
|
|
215
346
|
Guided setup so **CodeRifts / contract-gate** is a **required status check** on
|
|
@@ -245,6 +376,57 @@ coderifts setup-required-check --apply
|
|
|
245
376
|
coderifts setup-required-check --branch main
|
|
246
377
|
```
|
|
247
378
|
|
|
379
|
+
### `coderifts lock [repo]`
|
|
380
|
+
|
|
381
|
+
Fetch the observed agent-contract lockfile (`coderifts.lock` v1) from
|
|
382
|
+
`GET /api/v1/lock`, **or** `--check` MCP drift of a locked manifest against a
|
|
383
|
+
live one (`scoreMcpRisk`). `--check` is **monitor only** — it does not block.
|
|
384
|
+
Unreachable live → status `unreachable` (not drift). Lock v1 records
|
|
385
|
+
agents/ops, not MCP tool bodies; pass `--locked-manifest` (or additive
|
|
386
|
+
`mcp_manifests` on the lockfile) for `--check`.
|
|
387
|
+
|
|
388
|
+
Requires a cloud API key for write mode.
|
|
389
|
+
|
|
390
|
+
| Flag | Description | Default |
|
|
391
|
+
|------|-------------|---------|
|
|
392
|
+
| `[repo]` / `--repo <owner/repo>` | Repository | none (write mode) |
|
|
393
|
+
| `--out <path>` | Output path | `coderifts.lock` |
|
|
394
|
+
| `--json` | stdout-only JSON (write: lock doc; check: drift report) | `false` |
|
|
395
|
+
| `--check` | Compare locked vs live MCP manifest | `false` |
|
|
396
|
+
| `--locked-manifest <path>` | Baseline MCP manifest JSON (`tools[]`) for `--check` | none |
|
|
397
|
+
| `--live-manifest <path>` | Live MCP manifest JSON for `--check` | none |
|
|
398
|
+
| `--live-url <url>` | Fetch live MCP manifest JSON from URL for `--check` | none |
|
|
399
|
+
| `--lockfile <path>` | Read `coderifts.lock` for additive `mcp_manifests` | none |
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
coderifts lock owner/repo
|
|
403
|
+
coderifts lock --check --locked-manifest mcp.json --live-manifest live.json
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
**`--check` exit codes** (from `lock.js`): `0` unchanged; `3` drift; `2`
|
|
407
|
+
unreachable / missing locked or live (not clean); `1` usage/error.
|
|
408
|
+
|
|
409
|
+
### `coderifts adopt`
|
|
410
|
+
|
|
411
|
+
Counterfactual report: what CodeRifts **would have done** on contract-artifact
|
|
412
|
+
changes in **local git** history. Extracts spec-only paths (not source files
|
|
413
|
+
whose names happen to contain “openapi”), then runs
|
|
414
|
+
`buildCounterfactualReport`. Step B (GitHub API + outcome correlation) is not
|
|
415
|
+
this command. Not a git repository → fail-closed (`GIT_ERROR`, exit **1**).
|
|
416
|
+
Success → exit **0**.
|
|
417
|
+
|
|
418
|
+
| Flag | Description | Default |
|
|
419
|
+
|------|-------------|---------|
|
|
420
|
+
| `--days <n>` | Look back N days (`git log --since`) | last 50 commits if neither flag set |
|
|
421
|
+
| `--commits <n>` | Last N commits | last 50 commits if neither flag set |
|
|
422
|
+
| `--json` | Machine-readable JSON report (analyzer logs silenced) | `false` |
|
|
423
|
+
|
|
424
|
+
```bash
|
|
425
|
+
coderifts adopt
|
|
426
|
+
coderifts adopt --days 30
|
|
427
|
+
coderifts adopt --commits 20 --json
|
|
428
|
+
```
|
|
429
|
+
|
|
248
430
|
## CI/CD Integration
|
|
249
431
|
|
|
250
432
|
### GitHub Actions
|
|
@@ -303,14 +485,18 @@ Two honest modes:
|
|
|
303
485
|
|----------|-------------|
|
|
304
486
|
| `CODERIFTS_API_KEY` | API key (alternative to `coderifts login`) |
|
|
305
487
|
| `CODERIFTS_OASDIFF_BIN` | Explicit path to the `oasdiff` binary (overrides auto-detect) |
|
|
488
|
+
| `CODERIFTS_STRICT` | `claude-hook` only: `1` or `true` (case-insensitive) turns enforcement-relevant soft sites into exit **2** (BLOCK). Unset/empty → default soft allow. Not a package-level guarantee. |
|
|
489
|
+
| `CODERIFTS_DEPLOY_ENFORCE` | `deploy-gate`: `true` marks the step enforcing (same as `--enforce`); `unknown` is explicitly unobservable (never assume ENFORCING) |
|
|
306
490
|
| `NO_COLOR` | Disable colored output |
|
|
307
491
|
|
|
308
492
|
## Exit Codes
|
|
309
493
|
|
|
310
494
|
| Code | Meaning |
|
|
311
495
|
|------|---------|
|
|
312
|
-
| `0` |
|
|
313
|
-
| `1` | Breaking changes
|
|
496
|
+
| `0` | Success: no breaking changes (or below threshold); advisory `deploy-gate`; `lock --check` unchanged; `adopt` / `status` / `outcome` success |
|
|
497
|
+
| `1` | Breaking changes (CI mode), analysis/usage/API failure, or `deploy-gate` deny **when enforcing** |
|
|
498
|
+
| `2` | `claude-hook` BLOCK (Claude Code cancel); `lock --check` unreachable / missing locked or live |
|
|
499
|
+
| `3` | `lock --check` drift detected (monitor only — does not block the package) |
|
|
314
500
|
|
|
315
501
|
## Links
|
|
316
502
|
|
package/bin/coderifts.js
CHANGED
|
@@ -183,14 +183,21 @@ program
|
|
|
183
183
|
runCopilotSetup(options, { exit: true });
|
|
184
184
|
});
|
|
185
185
|
|
|
186
|
-
// ── lock — agent contract lockfile v1 (observed usage; ID847) ──
|
|
187
|
-
// GET /api/v1/lock?repo= →
|
|
186
|
+
// ── lock — agent contract lockfile v1 (observed usage; ID847) + MCP drift --check (896) ──
|
|
187
|
+
// Write: GET /api/v1/lock?repo= → coderifts.lock. Check: locked MCP vs live via scoreMcpRisk.
|
|
188
188
|
program
|
|
189
189
|
.command('lock [repo]')
|
|
190
|
-
.description(
|
|
190
|
+
.description(
|
|
191
|
+
'Fetch observed agent-contract lockfile (coderifts.lock v1), or --check MCP drift vs live manifest',
|
|
192
|
+
)
|
|
191
193
|
.option('--repo <owner/repo>', 'Repository (owner/repo); also accepted as a positional argument')
|
|
192
194
|
.option('--out <path>', 'Output path (default: coderifts.lock in cwd)')
|
|
193
|
-
.option('--json', 'Print
|
|
195
|
+
.option('--json', 'Print JSON to stdout only (write: lock doc; check: drift report)')
|
|
196
|
+
.option('--check', 'MCP supply-chain monitor: compare locked vs live manifest (scoreMcpRisk)')
|
|
197
|
+
.option('--locked-manifest <path>', 'Baseline MCP manifest JSON (tools[]) for --check')
|
|
198
|
+
.option('--live-manifest <path>', 'Live MCP manifest JSON for --check')
|
|
199
|
+
.option('--live-url <url>', 'Fetch live MCP manifest JSON from URL for --check')
|
|
200
|
+
.option('--lockfile <path>', 'Read coderifts.lock for additive mcp_manifests (optional)')
|
|
194
201
|
.action(async (repoPositional, options) => {
|
|
195
202
|
const { runLock } = require('../src/commands/lock');
|
|
196
203
|
const result = await runLock({
|
|
@@ -202,6 +209,29 @@ program
|
|
|
202
209
|
}
|
|
203
210
|
});
|
|
204
211
|
|
|
212
|
+
// ── adopt — counterfactual "what would CodeRifts have done" from local git (roadmap 893 Step A) ──
|
|
213
|
+
// Stateless core in app src/core/counterfactual-adopt.js; CLI extracts change sets via git
|
|
214
|
+
// (mirrors publish-gate gitImpl). Not named "shadow" (shadowApis is taken).
|
|
215
|
+
program
|
|
216
|
+
.command('adopt')
|
|
217
|
+
.description(
|
|
218
|
+
'Counterfactual report: what CodeRifts would have done on contract-artifact changes in local git history',
|
|
219
|
+
)
|
|
220
|
+
.option('--days <n>', 'Look back N days of git history', (v) => parseInt(v, 10))
|
|
221
|
+
.option('--commits <n>', 'Look at the last N commits', (v) => parseInt(v, 10))
|
|
222
|
+
.option('--json', 'Machine-readable JSON report')
|
|
223
|
+
.action(async (options) => {
|
|
224
|
+
const { runAdopt } = require('../src/commands/adopt');
|
|
225
|
+
const result = await runAdopt({
|
|
226
|
+
days: options.days,
|
|
227
|
+
commits: options.commits,
|
|
228
|
+
json: !!options.json,
|
|
229
|
+
});
|
|
230
|
+
if (result && typeof result.exitCode === 'number') {
|
|
231
|
+
process.exitCode = result.exitCode;
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
205
235
|
// ── outcome — POST /api/v1/outcomes (caller assertion; does not verify the deploy) ──
|
|
206
236
|
program
|
|
207
237
|
.command('outcome <kind>')
|