coderifts 4.0.0 → 4.1.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 +41 -0
- package/README.md +12 -1
- package/dist/cli.js +221 -40
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.1.1
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **P0-2: `mapDecisionSeverity` never maps missing `execution_action` to ALLOW.**
|
|
8
|
+
Missing EA in any body shape → `INDETERMINATE` (exit 2). Legacy decision→severity
|
|
9
|
+
map is allowed only when `decision_spec_version === "1.0"` on a non-v2 body
|
|
10
|
+
(no `decision_result`, no `preflight_mode`). Top-level-only `{decision:"ALLOW"}`
|
|
11
|
+
without that pin is not permission.
|
|
12
|
+
- **P0-3: parse-gap is fail-closed by default.** Unparseable stdin and missing
|
|
13
|
+
`tool_input.file_path` → **exit 2**, stderr
|
|
14
|
+
`unparseable input — refusing (fail-closed); set CODERIFTS_ADVISORY=1 to soften`,
|
|
15
|
+
JSONL `hook_blocked` with `cause: stdin_unparseable|missing_file_path`.
|
|
16
|
+
`CODERIFTS_ADVISORY=1` restores exit 0. API-key-before-parse order is unchanged
|
|
17
|
+
(garbage stdin + no key → `missing_api_key`). Non-spec Write stays exit 0.
|
|
18
|
+
Unknown-tool-on-spec was already exit 2.
|
|
19
|
+
|
|
20
|
+
## 4.1.0
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- **`coderifts claude-hook` JSONL GuardEvent log.** When `CODERIFTS_GUARD_EVENT_LOG` is
|
|
25
|
+
set to an absolute file path, the hook appends one JSON object per line:
|
|
26
|
+
`preflight_start` / `preflight_result` / `preflight_unavailable` / `detection_skip`
|
|
27
|
+
plus terminal `hook_blocked` (exit 2) / `hook_continue` (exit 0) /
|
|
28
|
+
`hook_advisory_passthrough` (ADVISORY exit 0). Extra fields: `tool`, `path`,
|
|
29
|
+
`trigger_source:"claude_hook"`, `fingerprint` when the authorize envelope
|
|
30
|
+
returns one, `sessionId` (`CODERIFTS_SESSION_ID` or per-process). Unset env
|
|
31
|
+
→ no file. Log write errors are swallowed and printed to stderr; **exit
|
|
32
|
+
codes are unchanged**. The hook does not claim `enforced` (no
|
|
33
|
+
receipt-verified execution path).
|
|
34
|
+
|
|
3
35
|
## 4.0.0
|
|
4
36
|
|
|
5
37
|
**Breaking** — `coderifts claude-hook` is fail-closed by default. The CLI now
|
|
@@ -28,6 +60,15 @@ depends on `@coderifts/agent-guard` ^8.1.1.
|
|
|
28
60
|
(never widen).
|
|
29
61
|
- **`MIN_GUARD_MAJOR`:** 6 → 8 (`scripts/assert-guard-major.js`).
|
|
30
62
|
|
|
63
|
+
### Added
|
|
64
|
+
- **`coderifts agent-setup` writes `.claude/settings.json`.** PreToolUse hook
|
|
65
|
+
(`matcher: Write|Edit|MultiEdit` → `coderifts claude-hook`, timeout 60)
|
|
66
|
+
beside the six rule files. Fail-closed default (P0-3/P0-4). Explicit
|
|
67
|
+
opt-out documented on stdout: `CODERIFTS_ADVISORY=1`. `--check` is
|
|
68
|
+
byte-stable against the embed (same drift-gate as the six rule files).
|
|
69
|
+
Existing `.claude/settings.json` is skipped (no merge); `--force`
|
|
70
|
+
replaces the **entire** file.
|
|
71
|
+
|
|
31
72
|
### Fixed
|
|
32
73
|
- **Installer copy (P0 #9 / e76e846):** `agent-setup` / `init` teach
|
|
33
74
|
guard@8 execution-state **DEFAULT ON**, not the old OFF.
|
package/README.md
CHANGED
|
@@ -301,7 +301,8 @@ coderifts enforce --repo owner/repo --apply
|
|
|
301
301
|
|
|
302
302
|
### Agent host files (`coderifts agent-setup`)
|
|
303
303
|
|
|
304
|
-
Writes the six CodeRifts agent-host rule files
|
|
304
|
+
Writes the six CodeRifts agent-host rule files **plus** the Claude Code
|
|
305
|
+
PreToolUse hook settings into the current repo (or `--out <dir>`):
|
|
305
306
|
|
|
306
307
|
| File | Host |
|
|
307
308
|
|------|------|
|
|
@@ -311,6 +312,16 @@ Writes the six CodeRifts agent-host rule files into the current repo (or `--out
|
|
|
311
312
|
| `.github/copilot-instructions.md` | GitHub Copilot |
|
|
312
313
|
| `coderifts-langgraph-policy.js` | LangGraph |
|
|
313
314
|
| `openai-agent-instructions.md` | OpenAI Agents SDK |
|
|
315
|
+
| `.claude/settings.json` | Claude Code PreToolUse → `coderifts claude-hook` (fail-closed) |
|
|
316
|
+
|
|
317
|
+
The generated `.claude/settings.json` matches the recipe above (`matcher`
|
|
318
|
+
`Write|Edit|MultiEdit`, `command` `coderifts claude-hook`, `timeout` 60).
|
|
319
|
+
Default is **fail-closed** (missing key / API down → exit 2). Explicit
|
|
320
|
+
opt-out: `CODERIFTS_ADVISORY=1|true`. `CODERIFTS_STRICT=1` cannot be
|
|
321
|
+
weakened by ADVISORY. Existing files are skipped unless `--force`.
|
|
322
|
+
`--force` **replaces the entire** `.claude/settings.json` (no merge into
|
|
323
|
+
permissions / other hooks). If the file already exists, add the PreToolUse
|
|
324
|
+
recipe by hand or accept a full replace.
|
|
314
325
|
|
|
315
326
|
```bash
|
|
316
327
|
coderifts agent-setup # write (skip existing files)
|
package/dist/cli.js
CHANGED
|
@@ -3007,7 +3007,7 @@ var require_package = __commonJS({
|
|
|
3007
3007
|
"package.json"(exports2, module2) {
|
|
3008
3008
|
module2.exports = {
|
|
3009
3009
|
name: "coderifts",
|
|
3010
|
-
version: "4.
|
|
3010
|
+
version: "4.1.1",
|
|
3011
3011
|
description: "Detect breaking API changes from the command line. Works locally or with the CodeRifts cloud API.",
|
|
3012
3012
|
author: "CodeRifts <hello@coderifts.com>",
|
|
3013
3013
|
license: "MIT",
|
|
@@ -100059,7 +100059,8 @@ var require_agent_host_files_embedded = __commonJS({
|
|
|
100059
100059
|
".cursor/rules/coderifts.mdc",
|
|
100060
100060
|
".github/copilot-instructions.md",
|
|
100061
100061
|
"coderifts-langgraph-policy.js",
|
|
100062
|
-
"openai-agent-instructions.md"
|
|
100062
|
+
"openai-agent-instructions.md",
|
|
100063
|
+
".claude/settings.json"
|
|
100063
100064
|
]);
|
|
100064
100065
|
var AGENT_HOST_FILES = Object.freeze({
|
|
100065
100066
|
"AGENTS.md": '<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts agent rules\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call CodeRifts tools for a documentation-only change (README, guides, comments) with no contract artifact content change.\n\nIf you already hold a chain receipt and only need authenticity/lifecycle: `verify_receipt`. If you need a past decision by id: `get_decision_details`. Neither replaces preflight for a new change set.\n\nA receipt is operation-scoped: a merge receipt never authorizes a deploy or publish. When the operation changes, you MUST call `preflight_change_set` again with the new `context.operation` \u2014 do not decline, re-preflight.\n\nA stale or superseded receipt on a changed head requires a NEW preflight \u2014 `verify_receipt` cannot re-diff.\n\nFor mutating tools, put only the guarded version in the agent\'s tool table; keep the raw handler host-only and unreachable from that table. How you name tools is yours \u2014 this is a reachability property, not a product rename of host tools. CodeRifts cannot see or stop a raw call the host makes outside the table it returns; adopt this as a host convention, not as a guarantee from the package.\n\nCodeRifts reports a governance decision and `execution_action`; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.\n',
|
|
@@ -100067,7 +100068,8 @@ var require_agent_host_files_embedded = __commonJS({
|
|
|
100067
100068
|
".cursor/rules/coderifts.mdc": '---\ndescription: CodeRifts API governance \u2014 when to preflight and how to branch\nglobs:\nalwaysApply: true\n---\n\n<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call CodeRifts tools for a documentation-only change (README, guides, comments) with no contract artifact content change.\n\nIf you already hold a chain receipt and only need authenticity/lifecycle: `verify_receipt`. If you need a past decision by id: `get_decision_details`. Neither replaces preflight for a new change set.\n\nA receipt is operation-scoped: a merge receipt never authorizes a deploy or publish. When the operation changes, you MUST call `preflight_change_set` again with the new `context.operation` \u2014 do not decline, re-preflight.\n\nA stale or superseded receipt on a changed head requires a NEW preflight \u2014 `verify_receipt` cannot re-diff.\n\nFor mutating tools, put only the guarded version in the agent\'s tool table; keep the raw handler host-only and unreachable from that table. How you name tools is yours \u2014 this is a reachability property, not a product rename of host tools. CodeRifts cannot see or stop a raw call the host makes outside the table it returns; adopt this as a host convention, not as a guarantee from the package.\n\nCodeRifts reports a governance decision and `execution_action`; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.\n',
|
|
100068
100069
|
".github/copilot-instructions.md": '<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts instructions for GitHub Copilot\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call CodeRifts tools for a documentation-only change (README, guides, comments) with no contract artifact content change.\n\nIf you already hold a chain receipt and only need authenticity/lifecycle: `verify_receipt`. If you need a past decision by id: `get_decision_details`. Neither replaces preflight for a new change set.\n\nA receipt is operation-scoped: a merge receipt never authorizes a deploy or publish. When the operation changes, you MUST call `preflight_change_set` again with the new `context.operation` \u2014 do not decline, re-preflight.\n\nA stale or superseded receipt on a changed head requires a NEW preflight \u2014 `verify_receipt` cannot re-diff.\n\nFor mutating tools, put only the guarded version in the agent\'s tool table; keep the raw handler host-only and unreachable from that table. How you name tools is yours \u2014 this is a reachability property, not a product rename of host tools. CodeRifts cannot see or stop a raw call the host makes outside the table it returns; adopt this as a host convention, not as a guarantee from the package.\n\nCodeRifts reports a governance decision and `execution_action`; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.\n',
|
|
100069
100070
|
"coderifts-langgraph-policy.js": '// GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js\n// System policy string for a LangGraph (or similar) agent. Content is generated;\n// identical rule sentences to AGENTS.md / other formats.\n\'use strict\';\n\nmodule.exports = "Call `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\\n\\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\\n\\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\\n\\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\\n\\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not \\"proceed with caution\\" without monitoring.\\n\\nDo not call CodeRifts tools for a documentation-only change (README, guides, comments) with no contract artifact content change.\\n\\nIf you already hold a chain receipt and only need authenticity/lifecycle: `verify_receipt`. If you need a past decision by id: `get_decision_details`. Neither replaces preflight for a new change set.\\n\\nA receipt is operation-scoped: a merge receipt never authorizes a deploy or publish. When the operation changes, you MUST call `preflight_change_set` again with the new `context.operation` \u2014 do not decline, re-preflight.\\n\\nA stale or superseded receipt on a changed head requires a NEW preflight \u2014 `verify_receipt` cannot re-diff.\\n\\nFor mutating tools, put only the guarded version in the agent\'s tool table; keep the raw handler host-only and unreachable from that table. How you name tools is yours \u2014 this is a reachability property, not a product rename of host tools. CodeRifts cannot see or stop a raw call the host makes outside the table it returns; adopt this as a host convention, not as a guarantee from the package.\\n\\nCodeRifts reports a governance decision and `execution_action`; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.";\n',
|
|
100070
|
-
"openai-agent-instructions.md": '<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts agent instructions\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call CodeRifts tools for a documentation-only change (README, guides, comments) with no contract artifact content change.\n\nIf you already hold a chain receipt and only need authenticity/lifecycle: `verify_receipt`. If you need a past decision by id: `get_decision_details`. Neither replaces preflight for a new change set.\n\nA receipt is operation-scoped: a merge receipt never authorizes a deploy or publish. When the operation changes, you MUST call `preflight_change_set` again with the new `context.operation` \u2014 do not decline, re-preflight.\n\nA stale or superseded receipt on a changed head requires a NEW preflight \u2014 `verify_receipt` cannot re-diff.\n\nFor mutating tools, put only the guarded version in the agent\'s tool table; keep the raw handler host-only and unreachable from that table. How you name tools is yours \u2014 this is a reachability property, not a product rename of host tools. CodeRifts cannot see or stop a raw call the host makes outside the table it returns; adopt this as a host convention, not as a guarantee from the package.\n\nCodeRifts reports a governance decision and `execution_action`; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.\n'
|
|
100071
|
+
"openai-agent-instructions.md": '<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts agent instructions\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call CodeRifts tools for a documentation-only change (README, guides, comments) with no contract artifact content change.\n\nIf you already hold a chain receipt and only need authenticity/lifecycle: `verify_receipt`. If you need a past decision by id: `get_decision_details`. Neither replaces preflight for a new change set.\n\nA receipt is operation-scoped: a merge receipt never authorizes a deploy or publish. When the operation changes, you MUST call `preflight_change_set` again with the new `context.operation` \u2014 do not decline, re-preflight.\n\nA stale or superseded receipt on a changed head requires a NEW preflight \u2014 `verify_receipt` cannot re-diff.\n\nFor mutating tools, put only the guarded version in the agent\'s tool table; keep the raw handler host-only and unreachable from that table. How you name tools is yours \u2014 this is a reachability property, not a product rename of host tools. CodeRifts cannot see or stop a raw call the host makes outside the table it returns; adopt this as a host convention, not as a guarantee from the package.\n\nCodeRifts reports a governance decision and `execution_action`; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.\n',
|
|
100072
|
+
".claude/settings.json": '{\n "hooks": {\n "PreToolUse": [\n {\n "matcher": "Write|Edit|MultiEdit",\n "hooks": [\n {\n "type": "command",\n "command": "coderifts claude-hook",\n "timeout": 60\n }\n ]\n }\n ]\n }\n}\n'
|
|
100071
100073
|
});
|
|
100072
100074
|
module2.exports = { AGENT_HOST_FILES, AGENT_HOST_PATHS };
|
|
100073
100075
|
}
|
|
@@ -100207,6 +100209,15 @@ ${USAGE}` };
|
|
|
100207
100209
|
for (const line of AGENT_SETUP_WARN_TELEMETRY_LINES) {
|
|
100208
100210
|
log(line);
|
|
100209
100211
|
}
|
|
100212
|
+
if (summary.skipped.includes(".claude/settings.json")) {
|
|
100213
|
+
for (const line of AGENT_SETUP_HOOK_SKIP_LINES) {
|
|
100214
|
+
log(line);
|
|
100215
|
+
}
|
|
100216
|
+
} else if (summary.written.includes(".claude/settings.json")) {
|
|
100217
|
+
for (const line of AGENT_SETUP_HOOK_WIRE_LINES) {
|
|
100218
|
+
log(line);
|
|
100219
|
+
}
|
|
100220
|
+
}
|
|
100210
100221
|
}
|
|
100211
100222
|
if (doExit) process.exit(0);
|
|
100212
100223
|
return { exitCode: 0, code: "OK", outDir, ...summary };
|
|
@@ -100222,13 +100233,28 @@ ${USAGE}` };
|
|
|
100222
100233
|
chalk.dim(" \xB7 missing artifacts/fingerprint \u2192 execution_state_unmeasurable (quiet)"),
|
|
100223
100234
|
chalk.dim(" Merge gate block is separate: coderifts setup-required-check --apply")
|
|
100224
100235
|
]);
|
|
100236
|
+
var AGENT_SETUP_HOOK_WIRE_LINES = Object.freeze([
|
|
100237
|
+
chalk.bold(" Claude Code hook (.claude/settings.json): fail-closed PreToolUse"),
|
|
100238
|
+
chalk.dim(" matcher Write|Edit|MultiEdit \u2192 coderifts claude-hook (exit 2 = BLOCK)."),
|
|
100239
|
+
chalk.dim(" Missing key / API down / unreadable spec \u2192 exit 2 (enforce_indeterminate), not ALLOW."),
|
|
100240
|
+
chalk.dim(" Opt-out: CODERIFTS_ADVISORY=1|true restores soft-allow when governance could not run."),
|
|
100241
|
+
chalk.dim(" CODERIFTS_STRICT=1 cannot be weakened by ADVISORY.")
|
|
100242
|
+
]);
|
|
100243
|
+
var AGENT_SETUP_HOOK_SKIP_LINES = Object.freeze([
|
|
100244
|
+
chalk.yellow(" .claude/settings.json exists \u2014 left unchanged (installer does not merge)."),
|
|
100245
|
+
chalk.dim(" --force replaces the ENTIRE file (not just the PreToolUse hook)."),
|
|
100246
|
+
chalk.dim(" To wire fail-closed: add PreToolUse \u2192 coderifts claude-hook by hand, or --force."),
|
|
100247
|
+
chalk.dim(" Opt-out if wired: CODERIFTS_ADVISORY=1|true. CODERIFTS_STRICT cannot weaken.")
|
|
100248
|
+
]);
|
|
100225
100249
|
module2.exports = {
|
|
100226
100250
|
runAgentSetup,
|
|
100227
100251
|
parseAgentSetupArgs,
|
|
100228
100252
|
AGENT_HOST_FILES,
|
|
100229
100253
|
AGENT_HOST_PATHS,
|
|
100230
100254
|
USAGE,
|
|
100231
|
-
AGENT_SETUP_WARN_TELEMETRY_LINES
|
|
100255
|
+
AGENT_SETUP_WARN_TELEMETRY_LINES,
|
|
100256
|
+
AGENT_SETUP_HOOK_WIRE_LINES,
|
|
100257
|
+
AGENT_SETUP_HOOK_SKIP_LINES
|
|
100232
100258
|
};
|
|
100233
100259
|
}
|
|
100234
100260
|
});
|
|
@@ -101205,8 +101231,10 @@ var require_claude_hook = __commonJS({
|
|
|
101205
101231
|
" no API key / API unreachable / disk unreadable / edit-apply failure on the spec path",
|
|
101206
101232
|
" Absence of a key is not permission. Explicit opt-out: CODERIFTS_ADVISORY=1|true.",
|
|
101207
101233
|
"",
|
|
101208
|
-
"
|
|
101209
|
-
"
|
|
101234
|
+
"Parse-gap DEFAULT (exit 2): unparseable stdin / missing file_path \u2014 refusing (fail-closed);",
|
|
101235
|
+
" set CODERIFTS_ADVISORY=1 to soften. JSONL hook_blocked cause stdin_unparseable|missing_file_path.",
|
|
101236
|
+
"",
|
|
101237
|
+
"Still exit 0 (nothing to govern): non-spec path, identical content.",
|
|
101210
101238
|
"",
|
|
101211
101239
|
"CONTINUE_WITH_MONITORING: allow only if the host asserts a sink",
|
|
101212
101240
|
" (CODERIFTS_MONITORING_SINK_WIRED=1|true or git config coderifts.monitoringSinkWired).",
|
|
@@ -101248,6 +101276,33 @@ var require_claude_hook = __commonJS({
|
|
|
101248
101276
|
if (dr && typeof dr === "object" && dr.monitoringSinkWired === true) return true;
|
|
101249
101277
|
return false;
|
|
101250
101278
|
}
|
|
101279
|
+
var HOOK_TRIGGER_SOURCE = "claude_hook";
|
|
101280
|
+
function extractFingerprint(result) {
|
|
101281
|
+
const d = result && typeof result === "object" && !Array.isArray(result) ? result : {};
|
|
101282
|
+
const dr = d.decision_result && typeof d.decision_result === "object" ? d.decision_result : {};
|
|
101283
|
+
const fp = dr.fingerprint || d.fingerprint || d.verdict_fingerprint || d.input_fingerprint;
|
|
101284
|
+
return typeof fp === "string" && fp.length > 0 ? fp : void 0;
|
|
101285
|
+
}
|
|
101286
|
+
function hookSessionId(env) {
|
|
101287
|
+
const fromEnv = env && env.CODERIFTS_SESSION_ID && String(env.CODERIFTS_SESSION_ID).trim();
|
|
101288
|
+
if (fromEnv) return fromEnv;
|
|
101289
|
+
if (!hookSessionId._gen) hookSessionId._gen = `hook-${process.pid}-${Date.now()}`;
|
|
101290
|
+
return hookSessionId._gen;
|
|
101291
|
+
}
|
|
101292
|
+
function appendGuardEventLog(env, event, deps = {}) {
|
|
101293
|
+
const p = env && env.CODERIFTS_GUARD_EVENT_LOG;
|
|
101294
|
+
if (p == null || String(p).trim() === "") return;
|
|
101295
|
+
const errLog = deps.errLog || ((m) => console.error(String(m)));
|
|
101296
|
+
const append = deps.appendFileSync || ((file, data) => fs.appendFileSync(file, data));
|
|
101297
|
+
try {
|
|
101298
|
+
append(String(p).trim(), JSON.stringify(event) + "\n");
|
|
101299
|
+
} catch (err) {
|
|
101300
|
+
try {
|
|
101301
|
+
errLog(`CodeRifts claude-hook: CODERIFTS_GUARD_EVENT_LOG write failed (${err && err.message})`);
|
|
101302
|
+
} catch {
|
|
101303
|
+
}
|
|
101304
|
+
}
|
|
101305
|
+
}
|
|
101251
101306
|
function failClosedOrAdvisory({ advisory, strict, site, softMsg, why, errLog }) {
|
|
101252
101307
|
if (advisory && !strict) {
|
|
101253
101308
|
errLog(`${softMsg} (CODERIFTS_ADVISORY)`);
|
|
@@ -101378,13 +101433,22 @@ var require_claude_hook = __commonJS({
|
|
|
101378
101433
|
}
|
|
101379
101434
|
return { ok: false, reason: `unsupported tool_name for content derive: ${name}` };
|
|
101380
101435
|
}
|
|
101436
|
+
function isV2DecisionBody(d, dr) {
|
|
101437
|
+
if (dr && typeof dr === "object") return true;
|
|
101438
|
+
if (d.preflight_mode != null && d.preflight_mode !== "") return true;
|
|
101439
|
+
const ver = d.decision_spec_version;
|
|
101440
|
+
return typeof ver === "string" && ver.startsWith("2.");
|
|
101441
|
+
}
|
|
101442
|
+
function allowLegacyDecisionMap(d, dr) {
|
|
101443
|
+
return d.decision_spec_version === "1.0" && !isV2DecisionBody(d, dr);
|
|
101444
|
+
}
|
|
101381
101445
|
function mapDecisionSeverity(result) {
|
|
101382
101446
|
const d = result && typeof result === "object" && !Array.isArray(result) ? result : {};
|
|
101383
101447
|
let ea = null;
|
|
101384
101448
|
const dr = d.decision_result;
|
|
101385
|
-
if (dr && typeof dr === "object" && typeof dr.execution_action === "string") {
|
|
101449
|
+
if (dr && typeof dr === "object" && typeof dr.execution_action === "string" && dr.execution_action !== "") {
|
|
101386
101450
|
ea = dr.execution_action;
|
|
101387
|
-
} else if (typeof d.execution_action === "string") {
|
|
101451
|
+
} else if (typeof d.execution_action === "string" && d.execution_action !== "") {
|
|
101388
101452
|
ea = d.execution_action;
|
|
101389
101453
|
}
|
|
101390
101454
|
const hasDecision = d.omega_decision != null && d.omega_decision !== "" || d.decision != null && d.decision !== "" || dr && typeof dr === "object" && dr.execution_action;
|
|
@@ -101409,7 +101473,7 @@ var require_claude_hook = __commonJS({
|
|
|
101409
101473
|
} else {
|
|
101410
101474
|
severity = "REQUIRE_APPROVAL";
|
|
101411
101475
|
}
|
|
101412
|
-
} else {
|
|
101476
|
+
} else if (allowLegacyDecisionMap(d, dr)) {
|
|
101413
101477
|
const od = d.omega_decision || d.decision;
|
|
101414
101478
|
if (od == null || od === "") {
|
|
101415
101479
|
severity = "INDETERMINATE";
|
|
@@ -101417,6 +101481,8 @@ var require_claude_hook = __commonJS({
|
|
|
101417
101481
|
else if (od === "REQUIRE_APPROVAL") severity = "REQUIRE_APPROVAL";
|
|
101418
101482
|
else if (od === "WARN") severity = "WARN";
|
|
101419
101483
|
else severity = "ALLOW";
|
|
101484
|
+
} else {
|
|
101485
|
+
severity = "INDETERMINATE";
|
|
101420
101486
|
}
|
|
101421
101487
|
const decision = dr && dr.decision || d.decision || d.omega_decision || null;
|
|
101422
101488
|
const decisionId = dr && dr.decision_id || d.decision_id || null;
|
|
@@ -101427,6 +101493,45 @@ var require_claude_hook = __commonJS({
|
|
|
101427
101493
|
executionAction: ea
|
|
101428
101494
|
};
|
|
101429
101495
|
}
|
|
101496
|
+
function renderDecisionWhy(result, opts = {}) {
|
|
101497
|
+
const maxFixes = Number.isInteger(opts.maxFixes) ? opts.maxFixes : 5;
|
|
101498
|
+
const maxLines = Number.isInteger(opts.maxLines) ? opts.maxLines : 13;
|
|
101499
|
+
const d = result && typeof result === "object" && !Array.isArray(result) ? result : {};
|
|
101500
|
+
const dr = d.decision_result && typeof d.decision_result === "object" ? d.decision_result : {};
|
|
101501
|
+
const pick = (k) => dr[k] !== void 0 ? dr[k] : d[k];
|
|
101502
|
+
const arr = (v) => Array.isArray(v) ? v : [];
|
|
101503
|
+
const str = (v) => typeof v === "string" ? v.trim() : "";
|
|
101504
|
+
const lines = [];
|
|
101505
|
+
const reasonCodes = [];
|
|
101506
|
+
for (const r of arr(pick("blocking_reasons"))) {
|
|
101507
|
+
if (!r || typeof r !== "object") continue;
|
|
101508
|
+
const code = str(r.code);
|
|
101509
|
+
const message = str(r.message);
|
|
101510
|
+
if (code) reasonCodes.push(code);
|
|
101511
|
+
if (!code && !message) continue;
|
|
101512
|
+
lines.push(`- ${code || "REASON"}${message ? `: ${message}` : ""}`);
|
|
101513
|
+
}
|
|
101514
|
+
for (const r of arr(pick("degraded_reasons"))) {
|
|
101515
|
+
if (!r || typeof r !== "object") continue;
|
|
101516
|
+
const code = str(r.code);
|
|
101517
|
+
const message = str(r.message);
|
|
101518
|
+
if (!code && !message) continue;
|
|
101519
|
+
lines.push(`- degraded: ${[code, message].filter(Boolean).join(": ")}`);
|
|
101520
|
+
}
|
|
101521
|
+
const action = str(pick("required_action"));
|
|
101522
|
+
if (action) lines.push(`- action: ${action}`);
|
|
101523
|
+
const rt = pick("remediation_transaction");
|
|
101524
|
+
const changes = arr(rt && typeof rt === "object" ? rt.required_changes : null).filter((c) => c && typeof c === "object");
|
|
101525
|
+
const shown = changes.slice(0, maxFixes);
|
|
101526
|
+
for (const c of shown) {
|
|
101527
|
+
const target = str(c.target);
|
|
101528
|
+
const instruction = str(c.instruction);
|
|
101529
|
+
if (!instruction && !target) continue;
|
|
101530
|
+
lines.push(`- fix${target ? ` (${target})` : ""}: ${instruction || str(c.precise_label)}`);
|
|
101531
|
+
}
|
|
101532
|
+
if (changes.length > shown.length) lines.push(`- fix: +${changes.length - shown.length} more`);
|
|
101533
|
+
return { lines: lines.slice(0, maxLines), reasonCodes };
|
|
101534
|
+
}
|
|
101430
101535
|
async function runClaudeHook(options = {}, deps = {}) {
|
|
101431
101536
|
const errLog = deps.errLog || ((m) => console.error(String(m)));
|
|
101432
101537
|
const readStdin = deps.readStdin || (() => {
|
|
@@ -101443,32 +101548,79 @@ var require_claude_hook = __commonJS({
|
|
|
101443
101548
|
const env = deps.env || process.env;
|
|
101444
101549
|
const strict = isStrictMode(env);
|
|
101445
101550
|
const advisory = isAdvisoryMode(env);
|
|
101551
|
+
const sessionId = hookSessionId(env);
|
|
101552
|
+
const logEv = (partial) => {
|
|
101553
|
+
appendGuardEventLog(env, {
|
|
101554
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
101555
|
+
sessionId,
|
|
101556
|
+
trigger_source: HOOK_TRIGGER_SOURCE,
|
|
101557
|
+
...partial
|
|
101558
|
+
}, { errLog, appendFileSync: deps.appendFileSync });
|
|
101559
|
+
};
|
|
101560
|
+
let tool = null;
|
|
101561
|
+
let filePathKnown = null;
|
|
101562
|
+
const emitTerminal = (r) => {
|
|
101563
|
+
const extra = {
|
|
101564
|
+
tool: tool || void 0,
|
|
101565
|
+
path: filePathKnown || void 0,
|
|
101566
|
+
decision: r.decision != null ? r.decision : void 0,
|
|
101567
|
+
decisionId: r.decisionId != null ? r.decisionId : void 0
|
|
101568
|
+
};
|
|
101569
|
+
if (r.exitCode === 2) {
|
|
101570
|
+
const reasons = Array.isArray(r.reasons) && r.reasons.length ? r.reasons : void 0;
|
|
101571
|
+
logEv({
|
|
101572
|
+
type: "hook_blocked",
|
|
101573
|
+
exit: 2,
|
|
101574
|
+
...extra,
|
|
101575
|
+
reasons,
|
|
101576
|
+
cause: r.reason || r.site
|
|
101577
|
+
});
|
|
101578
|
+
} else if (r.exitCode === 0 && r.site && advisory && !strict) {
|
|
101579
|
+
logEv({ type: "hook_advisory_passthrough", exit: 0, decision: r.decision || null, ...extra, cause: r.site });
|
|
101580
|
+
} else {
|
|
101581
|
+
logEv({ type: "hook_continue", exit: 0, ...extra, cause: r.reason });
|
|
101582
|
+
}
|
|
101583
|
+
return r;
|
|
101584
|
+
};
|
|
101446
101585
|
const apiKey = resolveApiKey({ ...deps, cwd, env });
|
|
101447
101586
|
if (!apiKey) {
|
|
101448
|
-
|
|
101587
|
+
logEv({ type: "preflight_unavailable", cause: "missing_api_key" });
|
|
101588
|
+
return emitTerminal(failClosedOrAdvisory({
|
|
101449
101589
|
advisory,
|
|
101450
101590
|
strict,
|
|
101451
101591
|
site: "missing_api_key",
|
|
101452
101592
|
why: "no API key",
|
|
101453
101593
|
softMsg: "CodeRifts claude-hook: no API key (coderifts login / CODERIFTS_API_KEY / git config coderifts.apiKey) \u2014 allowing",
|
|
101454
101594
|
errLog
|
|
101455
|
-
});
|
|
101595
|
+
}));
|
|
101456
101596
|
}
|
|
101597
|
+
const PARSE_GAP_STDERR = "unparseable input \u2014 refusing (fail-closed); set CODERIFTS_ADVISORY=1 to soften";
|
|
101457
101598
|
const raw = typeof options.stdin === "string" ? options.stdin : readStdin();
|
|
101458
101599
|
const parsed = parseStdinJson(raw);
|
|
101459
101600
|
if (!parsed.ok) {
|
|
101460
|
-
|
|
101461
|
-
|
|
101601
|
+
if (advisory && !strict) {
|
|
101602
|
+
errLog(`CodeRifts claude-hook: ${parsed.reason} \u2014 allowing (CODERIFTS_ADVISORY)`);
|
|
101603
|
+
return emitTerminal({ exitCode: 0, reason: "stdin_unparseable", site: "stdin_unparseable" });
|
|
101604
|
+
}
|
|
101605
|
+
errLog(`CodeRifts claude-hook: ${PARSE_GAP_STDERR}`);
|
|
101606
|
+
return emitTerminal({ exitCode: 2, reason: "stdin_unparseable" });
|
|
101462
101607
|
}
|
|
101463
101608
|
const { toolName, toolInput } = parsed;
|
|
101609
|
+
tool = toolName;
|
|
101464
101610
|
const filePath = toolInput.file_path || toolInput.filePath || toolInput.path;
|
|
101465
101611
|
if (!filePath || typeof filePath !== "string") {
|
|
101466
|
-
|
|
101467
|
-
|
|
101612
|
+
if (advisory && !strict) {
|
|
101613
|
+
errLog("CodeRifts claude-hook: tool_input.file_path missing \u2014 allowing (CODERIFTS_ADVISORY)");
|
|
101614
|
+
return emitTerminal({ exitCode: 0, reason: "missing_file_path", site: "missing_file_path" });
|
|
101615
|
+
}
|
|
101616
|
+
errLog(`CodeRifts claude-hook: ${PARSE_GAP_STDERR}`);
|
|
101617
|
+
return emitTerminal({ exitCode: 2, reason: "missing_file_path" });
|
|
101468
101618
|
}
|
|
101619
|
+
filePathKnown = filePath;
|
|
101469
101620
|
const specPath = resolveSpecPath({ ...deps, cwd });
|
|
101470
101621
|
if (!isSpecPath(filePath, specPath)) {
|
|
101471
|
-
|
|
101622
|
+
logEv({ type: "detection_skip", signals: ["not_spec_path"], tool, path: filePath });
|
|
101623
|
+
return emitTerminal({ exitCode: 0, reason: "not_spec_path" });
|
|
101472
101624
|
}
|
|
101473
101625
|
const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(cwd, filePath);
|
|
101474
101626
|
let diskBefore = "";
|
|
@@ -101476,30 +101628,34 @@ var require_claude_hook = __commonJS({
|
|
|
101476
101628
|
try {
|
|
101477
101629
|
diskBefore = readFile(absPath, "utf8");
|
|
101478
101630
|
} catch (e) {
|
|
101479
|
-
|
|
101631
|
+
logEv({ type: "preflight_unavailable", cause: "disk_unreadable", tool, path: filePath });
|
|
101632
|
+
return emitTerminal(failClosedOrAdvisory({
|
|
101480
101633
|
advisory,
|
|
101481
101634
|
strict,
|
|
101482
101635
|
site: "disk_unreadable",
|
|
101483
101636
|
why: `cannot read contract file ${absPath}`,
|
|
101484
101637
|
softMsg: `CodeRifts claude-hook: cannot read ${absPath} \u2014 allowing (soft)`,
|
|
101485
101638
|
errLog
|
|
101486
|
-
});
|
|
101639
|
+
}));
|
|
101487
101640
|
}
|
|
101488
101641
|
}
|
|
101489
101642
|
const derived = deriveAfterContent(toolName, toolInput, diskBefore);
|
|
101490
101643
|
if (!derived.ok) {
|
|
101491
|
-
|
|
101644
|
+
logEv({ type: "preflight_unavailable", cause: "edit_apply_failed", tool, path: filePath });
|
|
101645
|
+
return emitTerminal(failClosedOrAdvisory({
|
|
101492
101646
|
advisory,
|
|
101493
101647
|
strict,
|
|
101494
101648
|
site: "edit_apply_failed",
|
|
101495
101649
|
why: derived.reason,
|
|
101496
101650
|
softMsg: `CodeRifts claude-hook: ${derived.reason} \u2014 allowing (soft; never guess edit apply)`,
|
|
101497
101651
|
errLog
|
|
101498
|
-
});
|
|
101652
|
+
}));
|
|
101499
101653
|
}
|
|
101500
101654
|
if (diskBefore === derived.after) {
|
|
101501
|
-
|
|
101655
|
+
logEv({ type: "detection_skip", signals: ["identical"], tool, path: filePath });
|
|
101656
|
+
return emitTerminal({ exitCode: 0, reason: "identical" });
|
|
101502
101657
|
}
|
|
101658
|
+
logEv({ type: "preflight_start", tool, path: filePath });
|
|
101503
101659
|
let result;
|
|
101504
101660
|
try {
|
|
101505
101661
|
result = await authorize(diskBefore, derived.after, apiKey, {
|
|
@@ -101508,54 +101664,75 @@ var require_claude_hook = __commonJS({
|
|
|
101508
101664
|
});
|
|
101509
101665
|
} catch (e) {
|
|
101510
101666
|
const msg = e && e.message ? String(e.message) : "request failed";
|
|
101511
|
-
|
|
101667
|
+
logEv({ type: "preflight_unavailable", cause: "api_unreachable", tool, path: filePath });
|
|
101668
|
+
return emitTerminal(failClosedOrAdvisory({
|
|
101512
101669
|
advisory,
|
|
101513
101670
|
strict,
|
|
101514
101671
|
site: "api_unreachable",
|
|
101515
101672
|
why: `API unreachable: ${msg}`,
|
|
101516
101673
|
softMsg: `CodeRifts claude-hook: API unreachable (${msg}) \u2014 allowing (soft; availability must not brick the editor)`,
|
|
101517
101674
|
errLog
|
|
101518
|
-
});
|
|
101675
|
+
}));
|
|
101519
101676
|
}
|
|
101520
101677
|
const mapped = mapDecisionSeverity(result);
|
|
101678
|
+
const fingerprint = extractFingerprint(result);
|
|
101521
101679
|
const idPart = mapped.decisionId ? ` decision_id=${mapped.decisionId}` : "";
|
|
101522
101680
|
const decPart = mapped.decision ? ` decision=${mapped.decision}` : "";
|
|
101523
101681
|
const eaPart = mapped.executionAction ? ` execution_action=${mapped.executionAction}` : "";
|
|
101682
|
+
const actionForLog = mapped.executionAction || (mapped.severity === "BLOCK" || mapped.severity === "UNKNOWN" || mapped.severity === "INDETERMINATE" ? "STOP" : mapped.severity === "REQUIRE_APPROVAL" ? "REQUEST_APPROVAL" : mapped.severity === "MONITOR" || mapped.severity === "WARN" ? "CONTINUE_WITH_MONITORING" : "CONTINUE");
|
|
101683
|
+
logEv({
|
|
101684
|
+
type: "preflight_result",
|
|
101685
|
+
action: actionForLog,
|
|
101686
|
+
decisionId: mapped.decisionId || void 0,
|
|
101687
|
+
fingerprint,
|
|
101688
|
+
tool,
|
|
101689
|
+
path: filePath
|
|
101690
|
+
});
|
|
101524
101691
|
if (mapped.severity === "INDETERMINATE") {
|
|
101525
101692
|
errLog(
|
|
101526
101693
|
"CodeRifts claude-hook: BLOCKED (indeterminate response \u2014 no execution_action and no decision; not permission)"
|
|
101527
101694
|
);
|
|
101528
|
-
return {
|
|
101695
|
+
return emitTerminal({
|
|
101529
101696
|
exitCode: 2,
|
|
101530
101697
|
reason: "indeterminate",
|
|
101531
101698
|
severity: "INDETERMINATE",
|
|
101532
101699
|
decision: mapped.decision,
|
|
101533
101700
|
decisionId: mapped.decisionId
|
|
101534
|
-
};
|
|
101701
|
+
});
|
|
101535
101702
|
}
|
|
101536
101703
|
if (mapped.severity === "BLOCK" || mapped.severity === "UNKNOWN") {
|
|
101704
|
+
const why = renderDecisionWhy(result);
|
|
101537
101705
|
errLog(
|
|
101538
|
-
|
|
101706
|
+
[
|
|
101707
|
+
`CodeRifts claude-hook: BLOCKED${decPart}${eaPart}${idPart}` + (mapped.severity === "UNKNOWN" ? " (unrecognised execution_action)" : ""),
|
|
101708
|
+
...why.lines
|
|
101709
|
+
].join("\n")
|
|
101539
101710
|
);
|
|
101540
|
-
return {
|
|
101711
|
+
return emitTerminal({
|
|
101541
101712
|
exitCode: 2,
|
|
101542
101713
|
reason: mapped.severity === "UNKNOWN" ? "unknown_action" : "block",
|
|
101543
101714
|
severity: mapped.severity,
|
|
101544
101715
|
decision: mapped.decision,
|
|
101545
|
-
decisionId: mapped.decisionId
|
|
101546
|
-
|
|
101716
|
+
decisionId: mapped.decisionId,
|
|
101717
|
+
reasons: why.reasonCodes
|
|
101718
|
+
});
|
|
101547
101719
|
}
|
|
101548
101720
|
if (mapped.severity === "REQUIRE_APPROVAL") {
|
|
101721
|
+
const why = renderDecisionWhy(result);
|
|
101549
101722
|
errLog(
|
|
101550
|
-
|
|
101723
|
+
[
|
|
101724
|
+
`CodeRifts claude-hook: BLOCKED approval_required${decPart}${eaPart}${idPart}`,
|
|
101725
|
+
...why.lines
|
|
101726
|
+
].join("\n")
|
|
101551
101727
|
);
|
|
101552
|
-
return {
|
|
101728
|
+
return emitTerminal({
|
|
101553
101729
|
exitCode: 2,
|
|
101554
101730
|
reason: "approval_required",
|
|
101555
101731
|
severity: mapped.severity,
|
|
101556
101732
|
decision: mapped.decision,
|
|
101557
|
-
decisionId: mapped.decisionId
|
|
101558
|
-
|
|
101733
|
+
decisionId: mapped.decisionId,
|
|
101734
|
+
reasons: why.reasonCodes
|
|
101735
|
+
});
|
|
101559
101736
|
}
|
|
101560
101737
|
if (mapped.severity === "MONITOR" || mapped.severity === "WARN") {
|
|
101561
101738
|
const sinkWired = isMonitoringSinkWired({ env, deps, result });
|
|
@@ -101563,29 +101740,29 @@ var require_claude_hook = __commonJS({
|
|
|
101563
101740
|
errLog(
|
|
101564
101741
|
`CodeRifts claude-hook: BLOCKED monitoring_unwired${decPart}${eaPart}${idPart} \u2014 CONTINUE_WITH_MONITORING requires CODERIFTS_MONITORING_SINK_WIRED=1 (host assertion; not delivery proof)`
|
|
101565
101742
|
);
|
|
101566
|
-
return {
|
|
101743
|
+
return emitTerminal({
|
|
101567
101744
|
exitCode: 2,
|
|
101568
101745
|
reason: "monitoring_unwired",
|
|
101569
101746
|
severity: mapped.severity === "WARN" ? "MONITOR" : mapped.severity,
|
|
101570
101747
|
decision: mapped.decision,
|
|
101571
101748
|
decisionId: mapped.decisionId
|
|
101572
|
-
};
|
|
101749
|
+
});
|
|
101573
101750
|
}
|
|
101574
|
-
return {
|
|
101751
|
+
return emitTerminal({
|
|
101575
101752
|
exitCode: 0,
|
|
101576
101753
|
reason: "allow",
|
|
101577
101754
|
severity: mapped.severity === "WARN" ? "MONITOR" : mapped.severity,
|
|
101578
101755
|
decision: mapped.decision,
|
|
101579
101756
|
decisionId: mapped.decisionId
|
|
101580
|
-
};
|
|
101757
|
+
});
|
|
101581
101758
|
}
|
|
101582
|
-
return {
|
|
101759
|
+
return emitTerminal({
|
|
101583
101760
|
exitCode: 0,
|
|
101584
101761
|
reason: "allow",
|
|
101585
101762
|
severity: "ALLOW",
|
|
101586
101763
|
decision: mapped.decision,
|
|
101587
101764
|
decisionId: mapped.decisionId
|
|
101588
|
-
};
|
|
101765
|
+
});
|
|
101589
101766
|
}
|
|
101590
101767
|
module2.exports = {
|
|
101591
101768
|
runClaudeHook,
|
|
@@ -101593,6 +101770,7 @@ var require_claude_hook = __commonJS({
|
|
|
101593
101770
|
isSpecPath,
|
|
101594
101771
|
deriveAfterContent,
|
|
101595
101772
|
mapDecisionSeverity,
|
|
101773
|
+
renderDecisionWhy,
|
|
101596
101774
|
resolveApiKey,
|
|
101597
101775
|
resolveSpecPath,
|
|
101598
101776
|
readGitConfig,
|
|
@@ -101604,7 +101782,10 @@ var require_claude_hook = __commonJS({
|
|
|
101604
101782
|
softOrStrictBlock,
|
|
101605
101783
|
DEFAULT_SPEC_PATH,
|
|
101606
101784
|
CLOSED_ACTIONS,
|
|
101607
|
-
USAGE
|
|
101785
|
+
USAGE,
|
|
101786
|
+
appendGuardEventLog,
|
|
101787
|
+
extractFingerprint,
|
|
101788
|
+
HOOK_TRIGGER_SOURCE
|
|
101608
101789
|
};
|
|
101609
101790
|
}
|
|
101610
101791
|
});
|
package/package.json
CHANGED