coderifts 7.0.0 → 8.0.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/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: "7.0.0",
3031
+ version: "8.0.1",
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",
@@ -3068,13 +3068,13 @@ var require_package = __commonJS({
3068
3068
  },
3069
3069
  scripts: {
3070
3070
  build: "node scripts/copy-corpus.js && node scripts/build.js",
3071
- prepublishOnly: "node scripts/assert-guard-major.js && node scripts/assert-changelog-version.js && bash ../../scripts/freeze-gate.sh && npm run build",
3071
+ prepublishOnly: "node scripts/assert-guard-major.js && node scripts/assert-changelog-version.js && bash ../../scripts/freeze-gate.sh && npm run build && bash ../../scripts/release-check.sh .",
3072
3072
  "assert-guard-major": "node scripts/assert-guard-major.js",
3073
3073
  postinstall: "node scripts/postinstall.js",
3074
3074
  test: "node --test test/*.test.js"
3075
3075
  },
3076
3076
  dependencies: {
3077
- "@coderifts/agent-guard": "^14.0.0",
3077
+ "@coderifts/agent-guard": "^15.1.0",
3078
3078
  chalk: "^4.1.2",
3079
3079
  "cli-table3": "^0.6.4",
3080
3080
  commander: "^12.0.0",
@@ -68128,7 +68128,7 @@ var require_client = __commonJS({
68128
68128
  this.timeout = options.timeout || DEFAULT_TIMEOUT;
68129
68129
  }
68130
68130
  // ─── Internal HTTP helper ──────────────────────────────────────────────
68131
- async request(method, path, body) {
68131
+ async request(method, path, body, extraHeaders) {
68132
68132
  const url = `${this.baseUrl}${path}`;
68133
68133
  const controller = new AbortController();
68134
68134
  const timer = setTimeout(() => controller.abort(), this.timeout);
@@ -68137,7 +68137,8 @@ var require_client = __commonJS({
68137
68137
  method,
68138
68138
  headers: {
68139
68139
  "Content-Type": "application/json",
68140
- Authorization: `Bearer ${this.apiKey}`
68140
+ Authorization: `Bearer ${this.apiKey}`,
68141
+ ...extraHeaders || {}
68141
68142
  },
68142
68143
  body: body ? JSON.stringify(body) : void 0,
68143
68144
  signal: controller.signal
@@ -68340,8 +68341,12 @@ var require_client = __commonJS({
68340
68341
  * `decision` / `safe_for_agent` (authorize) or `analysis_outcome` (analyze). Call
68341
68342
  * `analyzeChangeSet` / `authorizeChangeSet` instead to get an already-narrowed type.
68342
68343
  */
68343
- async preflightChangeSet(req) {
68344
- return this.request("POST", "/api/v1/preflight", req);
68344
+ async preflightChangeSet(req, opts) {
68345
+ const extra = {};
68346
+ const token = opts && typeof opts.scmToken === "string" ? opts.scmToken.trim() : "";
68347
+ if (token)
68348
+ extra["X-Coderifts-Scm-Token"] = token;
68349
+ return this.request("POST", "/api/v1/preflight", req, extra);
68345
68350
  }
68346
68351
  /**
68347
68352
  * Risk-only preflight (`preflight_mode: 'analyze'`). Informational — not permission;
@@ -68350,11 +68355,11 @@ var require_client = __commonJS({
68350
68355
  * The mode is fixed by this method, so the analyze branch is returned directly — there is no
68351
68356
  * `decision` / `execution_action` / `safe_for_agent` on it, by protocol.
68352
68357
  */
68353
- async analyzeChangeSet(req) {
68358
+ async analyzeChangeSet(req, opts) {
68354
68359
  return this.preflightChangeSet({
68355
68360
  ...req,
68356
68361
  preflight_mode: "analyze"
68357
- });
68362
+ }, opts);
68358
68363
  }
68359
68364
  /**
68360
68365
  * Operation-bound authorize preflight (`preflight_mode: 'authorize'`).
@@ -68364,11 +68369,11 @@ var require_client = __commonJS({
68364
68369
  * The mode is fixed by this method, so the authorize branch is returned directly:
68365
68370
  * `decision`, `execution_action` and `safe_for_agent` are present without narrowing.
68366
68371
  */
68367
- async authorizeChangeSet(req) {
68372
+ async authorizeChangeSet(req, opts) {
68368
68373
  return this.preflightChangeSet({
68369
68374
  ...req,
68370
68375
  preflight_mode: "authorize"
68371
- });
68376
+ }, opts);
68372
68377
  }
68373
68378
  // ─── 9. verifyReceipt ──────────────────────────────────────────────────
68374
68379
  /**
@@ -68581,7 +68586,7 @@ var require_execution_grant = __commonJS({
68581
68586
  "node_modules/@coderifts/sdk/dist/cjs/execution-grant.js"(exports2) {
68582
68587
  "use strict";
68583
68588
  Object.defineProperty(exports2, "__esModule", { value: true });
68584
- exports2.CLOCK_SKEW_LEEWAY_MS = exports2.GRANT_SIGNING_PREFIX = exports2.GRANT_VERSION = void 0;
68589
+ exports2.CLOCK_SKEW_LEEWAY_MS = exports2.GRANT_SIGNING_PREFIX = exports2.GRANT_VERSION_V2 = exports2.GRANT_VERSION = void 0;
68585
68590
  exports2.afterPayloadCanonical = afterPayloadCanonical;
68586
68591
  exports2.computeScopeHash = computeScopeHash;
68587
68592
  exports2.receiptDigest = receiptDigest;
@@ -68592,6 +68597,7 @@ var require_execution_grant = __commonJS({
68592
68597
  return leeway_js_1.CLOCK_SKEW_LEEWAY_MS;
68593
68598
  } });
68594
68599
  exports2.GRANT_VERSION = "cr.exec.v1";
68600
+ exports2.GRANT_VERSION_V2 = "cr.exec.v2";
68595
68601
  exports2.GRANT_SIGNING_PREFIX = "crexec.v1";
68596
68602
  var NUL = "";
68597
68603
  var SIGNED_FIELDS = [
@@ -69226,7 +69232,7 @@ var require_cjs3 = __commonJS({
69226
69232
  "node_modules/@coderifts/sdk/dist/cjs/index.js"(exports2) {
69227
69233
  "use strict";
69228
69234
  Object.defineProperty(exports2, "__esModule", { value: true });
69229
- exports2.MONITOR_ATTEST_ENVELOPE_TAG = exports2.MONITOR_ATTEST_SIGNING_PREFIX = exports2.MONITOR_ATTEST_VERSION = exports2.monitorAttestSigningInput = exports2.verifyMonitoringAttestation = exports2.ATTEST_ENVELOPE_TAG = exports2.ATTEST_SIGNING_PREFIX = exports2.ATTEST_VERSION = exports2.attestSigningInput = exports2.verifyExecutionAttestation = exports2.GRANT_SIGNING_PREFIX = exports2.GRANT_VERSION = exports2.receiptDigest = exports2.afterPayloadCanonical = exports2.computeScopeHash = exports2.verifyExecutionGrant = exports2.isIssuedInFuture = exports2.isReceiptExpired = exports2.declaresDestructiveProduction = exports2.expiryLeewayMs = exports2.CLOCK_SKEW_LEEWAY_MS = exports2.readDecision = exports2.AuthError = exports2.RateLimitError = exports2.TimeoutError = exports2.ApiError = exports2.CodeRiftsError = exports2.resetPolicyWarnForTests = exports2.warnPolicyAbsentOnce = exports2.observePolicyPresence = exports2.detectPolicyPresence = exports2.policyPresenceOf = exports2.withPolicy = exports2.POLICY_ABSENT_WARN = exports2.POLICY_MARKER = exports2.CODERIFTS_POLICY = exports2.CodeRifts = void 0;
69235
+ exports2.MONITOR_ATTEST_ENVELOPE_TAG = exports2.MONITOR_ATTEST_SIGNING_PREFIX = exports2.MONITOR_ATTEST_VERSION = exports2.monitorAttestSigningInput = exports2.verifyMonitoringAttestation = exports2.ATTEST_ENVELOPE_TAG = exports2.ATTEST_SIGNING_PREFIX = exports2.ATTEST_VERSION = exports2.attestSigningInput = exports2.verifyExecutionAttestation = exports2.GRANT_SIGNING_PREFIX = exports2.GRANT_VERSION_V2 = exports2.GRANT_VERSION = exports2.receiptDigest = exports2.afterPayloadCanonical = exports2.computeScopeHash = exports2.verifyExecutionGrant = exports2.isIssuedInFuture = exports2.isReceiptExpired = exports2.declaresDestructiveProduction = exports2.expiryLeewayMs = exports2.CLOCK_SKEW_LEEWAY_MS = exports2.readDecision = exports2.AuthError = exports2.RateLimitError = exports2.TimeoutError = exports2.ApiError = exports2.CodeRiftsError = exports2.resetPolicyWarnForTests = exports2.warnPolicyAbsentOnce = exports2.observePolicyPresence = exports2.detectPolicyPresence = exports2.policyPresenceOf = exports2.withPolicy = exports2.POLICY_ABSENT_WARN = exports2.POLICY_MARKER = exports2.CODERIFTS_POLICY = exports2.CodeRifts = void 0;
69230
69236
  var client_js_1 = require_client();
69231
69237
  Object.defineProperty(exports2, "CodeRifts", { enumerable: true, get: function() {
69232
69238
  return client_js_1.CodeRifts;
@@ -69311,6 +69317,9 @@ var require_cjs3 = __commonJS({
69311
69317
  Object.defineProperty(exports2, "GRANT_VERSION", { enumerable: true, get: function() {
69312
69318
  return execution_grant_js_1.GRANT_VERSION;
69313
69319
  } });
69320
+ Object.defineProperty(exports2, "GRANT_VERSION_V2", { enumerable: true, get: function() {
69321
+ return execution_grant_js_1.GRANT_VERSION_V2;
69322
+ } });
69314
69323
  Object.defineProperty(exports2, "GRANT_SIGNING_PREFIX", { enumerable: true, get: function() {
69315
69324
  return execution_grant_js_1.GRANT_SIGNING_PREFIX;
69316
69325
  } });
@@ -70000,7 +70009,7 @@ var require_policy2 = __commonJS({
70000
70009
  exports2.observePolicyPresence = observePolicyPresence;
70001
70010
  exports2.resetPolicyWarnForTests = resetPolicyWarnForTests;
70002
70011
  exports2.POLICY_MARKER = "A receipt authorizes ONE operation: a merge receipt does not authorize a deploy.";
70003
- exports2.CODERIFTS_POLICY = '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\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\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\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\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\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational (`may_execute` is always false) and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".';
70012
+ exports2.CODERIFTS_POLICY = '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\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\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\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\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\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".';
70004
70013
  exports2.POLICY_ABSENT_WARN = "CodeRifts policy text not detected in the system prompt. The agent will still see the tools, but measured evidence shows operation-scope misuse is markedly more likely without it. See https://github.com/coderifts/agent-guard#policy-delivery.";
70005
70014
  function textHasMarker(text) {
70006
70015
  return text.includes(exports2.POLICY_MARKER);
@@ -70079,16 +70088,196 @@ var require_policy2 = __commonJS({
70079
70088
  }
70080
70089
  });
70081
70090
 
70091
+ // node_modules/@coderifts/agent-guard/dist/cjs/deny-remedy.js
70092
+ var require_deny_remedy = __commonJS({
70093
+ "node_modules/@coderifts/agent-guard/dist/cjs/deny-remedy.js"(exports2) {
70094
+ "use strict";
70095
+ Object.defineProperty(exports2, "__esModule", { value: true });
70096
+ exports2.ARGS_SHAPE = exports2.DOES_NOT_PROMISE = exports2.DENY_ERROR = void 0;
70097
+ exports2.buildDenyRemedy = buildDenyRemedy;
70098
+ exports2.denyErrorForReason = denyErrorForReason;
70099
+ exports2.DENY_ERROR = Object.freeze({
70100
+ GRANT_REQUIRED: "CODERIFTS_GRANT_REQUIRED",
70101
+ GRANT_INVALID: "CODERIFTS_GRANT_INVALID",
70102
+ GRANT_MISMATCH: "CODERIFTS_GRANT_MISMATCH"
70103
+ });
70104
+ exports2.DOES_NOT_PROMISE = "a grant does not guarantee execution (CAS may still fail)";
70105
+ exports2.ARGS_SHAPE = Object.freeze({
70106
+ artifacts: "Array<{ id, type, before, after }> \u2014 the change set being authorized",
70107
+ context: "{ operation, environment?, repository?, branch?, pull_request? } \u2014 operation is required for authorize"
70108
+ });
70109
+ var FINGERPRINT_RE = /^sha256:[0-9a-f]{64}$/;
70110
+ function buildDenyRemedy({ error, target = null, fingerprint = null, observed = null }) {
70111
+ if (!error || !Object.values(exports2.DENY_ERROR).includes(error))
70112
+ return null;
70113
+ const remedy = {
70114
+ error,
70115
+ // Null, never a wildcard: a surface that cannot name what it refused must
70116
+ // not emit a value a reader could take for "everything".
70117
+ target: typeof target === "string" && target.length > 0 ? target : null,
70118
+ // Only a well-formed fingerprint. A malformed one is dropped rather than
70119
+ // passed through, because a caller comparing it would get a false mismatch.
70120
+ fingerprint: typeof fingerprint === "string" && FINGERPRINT_RE.test(fingerprint) ? fingerprint : null,
70121
+ action_required: {
70122
+ tool: "preflight_change_set",
70123
+ mode: "authorize",
70124
+ args_shape: { ...exports2.ARGS_SHAPE }
70125
+ },
70126
+ does_not_promise: exports2.DOES_NOT_PROMISE
70127
+ };
70128
+ if (observed && typeof observed === "object")
70129
+ remedy.observed = observed;
70130
+ return remedy;
70131
+ }
70132
+ function denyErrorForReason(reason) {
70133
+ switch (String(reason || "").toLowerCase()) {
70134
+ // Nothing was presented.
70135
+ case "receipt_missing":
70136
+ case "missing_receipt":
70137
+ case "missing_grant_header":
70138
+ case "decision_missing":
70139
+ case "missing_decision_result":
70140
+ case "no_preflight_response":
70141
+ case "grant_not_supplied":
70142
+ return exports2.DENY_ERROR.GRANT_REQUIRED;
70143
+ // Something was presented and did not hold up.
70144
+ case "receipt_invalid":
70145
+ case "receipt_unverified":
70146
+ case "invalid_signature":
70147
+ case "unknown_key":
70148
+ case "unknown_kid":
70149
+ case "dsse_malformed":
70150
+ case "dsse_unsupported":
70151
+ case "dsse_predicate_mismatch":
70152
+ case "malformed":
70153
+ case "grant_malformed":
70154
+ case "grant_unverified":
70155
+ case "grant_expired":
70156
+ return exports2.DENY_ERROR.GRANT_INVALID;
70157
+ // It held up, but it is not about this request.
70158
+ case "scope_mismatch":
70159
+ case "target_mismatch":
70160
+ case "operation_mismatch":
70161
+ case "grant_scope_mismatch":
70162
+ case "mode_mismatch":
70163
+ case "repo_mismatch":
70164
+ case "base_mismatch":
70165
+ case "head_mismatch":
70166
+ case "grant_does_not_cover_path":
70167
+ case "grant_bound_elsewhere":
70168
+ case "receipt_envelope_mismatch":
70169
+ case "artifact_mismatch":
70170
+ case "grant_unbound":
70171
+ case "grant_wrong_audience":
70172
+ return exports2.DENY_ERROR.GRANT_MISMATCH;
70173
+ default:
70174
+ return null;
70175
+ }
70176
+ }
70177
+ }
70178
+ });
70179
+
70180
+ // node_modules/@coderifts/agent-guard/dist/cjs/next-agent-step.js
70181
+ var require_next_agent_step = __commonJS({
70182
+ "node_modules/@coderifts/agent-guard/dist/cjs/next-agent-step.js"(exports2) {
70183
+ "use strict";
70184
+ Object.defineProperty(exports2, "__esModule", { value: true });
70185
+ exports2.NEXT_STEP_NOTE = exports2.NEXT_AGENT_ACTIONS = void 0;
70186
+ exports2.readNextAgentStep = readNextAgentStep;
70187
+ exports2.NEXT_AGENT_ACTIONS = [
70188
+ "re_preflight",
70189
+ "revert",
70190
+ "migrate",
70191
+ "escalate",
70192
+ "await_approval"
70193
+ ];
70194
+ function readNextAgentStep(envelope) {
70195
+ if (!envelope || typeof envelope !== "object")
70196
+ return null;
70197
+ const raw = envelope.next_agent_step;
70198
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
70199
+ return null;
70200
+ const step = raw;
70201
+ if (typeof step.action !== "string" || step.action.length === 0)
70202
+ return null;
70203
+ return step;
70204
+ }
70205
+ exports2.NEXT_STEP_NOTE = "This is the decision's remediation suggestion, not permission; branch on execution_action.";
70206
+ }
70207
+ });
70208
+
70082
70209
  // node_modules/@coderifts/agent-guard/dist/cjs/execution-grant.js
70083
70210
  var require_execution_grant2 = __commonJS({
70084
70211
  "node_modules/@coderifts/agent-guard/dist/cjs/execution-grant.js"(exports2) {
70085
70212
  "use strict";
70086
70213
  Object.defineProperty(exports2, "__esModule", { value: true });
70214
+ exports2.V2_WIRE_FIELDS = exports2.V2_FIELD_KEYS = void 0;
70215
+ exports2.resolveV2Fields = resolveV2Fields;
70216
+ exports2.v2WireFields = v2WireFields;
70087
70217
  exports2.isExecutionGrantEnabled = isExecutionGrantEnabled;
70088
70218
  exports2.readExecutionGrantToken = readExecutionGrantToken;
70089
70219
  exports2.firstArtifactId = firstArtifactId;
70090
70220
  exports2.isSignerUnavailableError = isSignerUnavailableError;
70091
70221
  exports2.resolveStateNonceForCall = resolveStateNonceForCall;
70222
+ exports2.V2_FIELD_KEYS = Object.freeze([
70223
+ "executorId",
70224
+ "adapterId",
70225
+ "targetUri",
70226
+ "tenantId",
70227
+ "policyHash",
70228
+ "audienceHash"
70229
+ ]);
70230
+ function resolveV2Fields(input) {
70231
+ const top = input || {};
70232
+ const nested = input && input.executionGrant || {};
70233
+ const out = {};
70234
+ const conflicts = [];
70235
+ for (const key of exports2.V2_FIELD_KEYS) {
70236
+ const t = typeof top[key] === "string" && top[key].length > 0 ? top[key] : void 0;
70237
+ const n = typeof nested[key] === "string" && nested[key].length > 0 ? nested[key] : void 0;
70238
+ if (t !== void 0 && n !== void 0 && t !== n) {
70239
+ conflicts.push(` ${key}: top-level ${JSON.stringify(t)} vs executionGrant.${key} ${JSON.stringify(n)}`);
70240
+ continue;
70241
+ }
70242
+ const v = t !== void 0 ? t : n;
70243
+ if (v !== void 0)
70244
+ out[key] = v;
70245
+ }
70246
+ if (conflicts.length > 0) {
70247
+ const err = new Error(`withCodeRifts: the V2 identity fields are configured in two places and they disagree.
70248
+ ${conflicts.join("\n")}
70249
+
70250
+ These feed DIFFERENT halves of the system \u2014 the top level binds the ATOMIC construction check and the posture receipt, the executionGrant copy goes on the authorize request \u2014 so a disagreement builds a grant against one identity and verifies against another. Set each field ONCE, at the top level; the executionGrant spelling is a deprecated alias.`);
70251
+ err.code = "V2_FIELDS_CONFLICT";
70252
+ throw err;
70253
+ }
70254
+ return out;
70255
+ }
70256
+ exports2.V2_WIRE_FIELDS = Object.freeze([
70257
+ ["executor_id", "executorId"],
70258
+ ["adapter_id", "adapterId"],
70259
+ ["target_uri", "targetUri"],
70260
+ ["tenant_id", "tenantId"],
70261
+ ["policy_hash", "policyHash"],
70262
+ ["audience_hash", "audienceHash"]
70263
+ ]);
70264
+ function v2WireFields(config) {
70265
+ const g = config && config.executionGrant;
70266
+ const fields = {};
70267
+ const absent = [];
70268
+ if (!g || g.grantVersion !== "v2") {
70269
+ return { fields, absent: exports2.V2_WIRE_FIELDS.map(([wire]) => wire) };
70270
+ }
70271
+ const resolved = resolveV2Fields(config);
70272
+ for (const [wire, key] of exports2.V2_WIRE_FIELDS) {
70273
+ const v = resolved[key];
70274
+ if (typeof v === "string" && v.length > 0)
70275
+ fields[wire] = v;
70276
+ else
70277
+ absent.push(wire);
70278
+ }
70279
+ return { fields, absent };
70280
+ }
70092
70281
  function isExecutionGrantEnabled(config) {
70093
70282
  return !!(config && config.executionGrant && config.executionGrant.enabled === true);
70094
70283
  }
@@ -70163,6 +70352,8 @@ var require_guard = __commonJS({
70163
70352
  var monitoring_delivery_js_1 = require_monitoring_delivery();
70164
70353
  var monitoring_attestation_js_1 = require_monitoring_attestation2();
70165
70354
  var policy_js_1 = require_policy2();
70355
+ var deny_remedy_js_1 = require_deny_remedy();
70356
+ var next_agent_step_js_1 = require_next_agent_step();
70166
70357
  var execution_grant_js_1 = require_execution_grant2();
70167
70358
  var breakers = /* @__PURE__ */ new WeakMap();
70168
70359
  var nowMs = () => Date.now();
@@ -70333,7 +70524,7 @@ var require_guard = __commonJS({
70333
70524
  function coverageOutcomeFieldsFrom(s) {
70334
70525
  return s.coverageObserved ? { coverage_observed: s.coverageObserved } : {};
70335
70526
  }
70336
- function blocked(config, verdict, preflighted, freshness, conditional_write, monitoring_delivery, monitoring_attestation, grantObs) {
70527
+ function blocked(config, verdict, preflighted, freshness, conditional_write, monitoring_delivery, monitoring_attestation, grantObs, call) {
70337
70528
  const commit_observation = {
70338
70529
  status: "not_observed",
70339
70530
  observed_at: iso(),
@@ -70341,6 +70532,15 @@ var require_guard = __commonJS({
70341
70532
  };
70342
70533
  const base = { executionAttempted: false, executed: false, enforced: false, verdict, preflighted };
70343
70534
  const cov = coverageSnap(config);
70535
+ const cause = "cause" in verdict ? verdict.cause : null;
70536
+ const nextStep = "envelope" in verdict && "receiptVerified" in verdict && verdict.receiptVerified === true ? (0, next_agent_step_js_1.readNextAgentStep)(verdict.envelope) : null;
70537
+ const remedy = call ? (0, deny_remedy_js_1.buildDenyRemedy)({
70538
+ error: (0, deny_remedy_js_1.denyErrorForReason)(cause),
70539
+ target: call.toolName || null,
70540
+ // The guard's own input fingerprint, already sha256:<hex>.
70541
+ fingerprint: fingerprint(call),
70542
+ observed: { cause, resolution: "resolution" in verdict ? verdict.resolution : null }
70543
+ }) : null;
70344
70544
  const out = {
70345
70545
  ...base,
70346
70546
  proof: (0, execution_proof_js_1.buildExecutionProof)({
@@ -70357,7 +70557,9 @@ var require_guard = __commonJS({
70357
70557
  ...monitoring_delivery ? { monitoring_delivery } : {},
70358
70558
  ...monitoring_attestation ? { monitoring_attestation } : {},
70359
70559
  ...coverageOutcomeFieldsFrom(cov),
70360
- ...grantObs ? { execution_grant: grantObs } : {}
70560
+ ...grantObs ? { execution_grant: grantObs } : {},
70561
+ ...remedy ? { remedy } : {},
70562
+ ...nextStep ? { next_step: nextStep } : {}
70361
70563
  };
70362
70564
  return attachPolicyPresence(out, config);
70363
70565
  }
@@ -70565,7 +70767,7 @@ var require_guard = __commonJS({
70565
70767
  const v = unavailableVerdict({ cause: "MISSING_ARTIFACT_CONTENT", failPolicy, resolution: "CLOSED", action: "STOP" }, count);
70566
70768
  const { basis } = freshnessFor(config, redacted, fctx, detection.artifacts);
70567
70769
  const { basis: cw } = conditionalWriteFor(config, redacted, cwctx, detection.artifacts);
70568
- return blocked(config, v, false, basis, cw);
70770
+ return blocked(config, v, false, basis, cw, void 0, void 0, void 0, redacted);
70569
70771
  }
70570
70772
  if (failPolicy === "lkg" && !config.lkg) {
70571
70773
  breakerRecord(config);
@@ -70589,6 +70791,20 @@ var require_guard = __commonJS({
70589
70791
  request.include_execution_grant = true;
70590
70792
  if (nonceRes.nonce)
70591
70793
  request.state_nonce = nonceRes.nonce;
70794
+ const wire = (0, execution_grant_js_1.v2WireFields)(config);
70795
+ if (config.executionGrant?.grantVersion === "v2") {
70796
+ request.grant_version = "v2";
70797
+ for (const [k, v] of Object.entries(wire.fields))
70798
+ request[k] = v;
70799
+ }
70800
+ if (config.executionGrant?.grantVersion === "v2") {
70801
+ grantObs = {
70802
+ ...grantObs,
70803
+ grant_version: "v2",
70804
+ v2_fields_sent: Object.keys(wire.fields),
70805
+ v2_fields_absent: wire.absent
70806
+ };
70807
+ }
70592
70808
  }
70593
70809
  const cap = config.maxPayloadBytes ?? 1e6;
70594
70810
  if (Buffer.byteLength(JSON.stringify(request), "utf8") > cap) {
@@ -70605,14 +70821,14 @@ var require_guard = __commonJS({
70605
70821
  if (pf.integrity) {
70606
70822
  emit(config, { type: "breaker_tripped", at: iso(), cause: pf.cause });
70607
70823
  const v2 = unavailableVerdict({ cause: pf.cause, failPolicy, resolution: "CLOSED", action: "STOP" }, count);
70608
- return blocked(config, v2, false, basis, cw, void 0, void 0, grantObs);
70824
+ return blocked(config, v2, false, basis, cw, void 0, void 0, grantObs, redacted);
70609
70825
  }
70610
70826
  const availCause = pf.cause;
70611
70827
  if (grantObs && grantObs.requested) {
70612
70828
  if (breakerTripped(config))
70613
70829
  emit(config, { type: "breaker_tripped", at: iso(), cause: availCause });
70614
70830
  const v2 = unavailableVerdict({ cause: availCause, failPolicy, resolution: "CLOSED", action: "STOP" }, count);
70615
- return blocked(config, v2, false, basis, cw, void 0, void 0, grantObs);
70831
+ return blocked(config, v2, false, basis, cw, void 0, void 0, grantObs, redacted);
70616
70832
  }
70617
70833
  if (failPolicy === "open" && !breakerTripped(config)) {
70618
70834
  emit(config, { type: "preflight_unavailable", at: iso(), cause: availCause, action: "CONTINUE" });
@@ -70630,7 +70846,7 @@ var require_guard = __commonJS({
70630
70846
  if (breakerTripped(config))
70631
70847
  emit(config, { type: "breaker_tripped", at: iso(), cause: availCause });
70632
70848
  const v = unavailableVerdict({ cause: availCause, failPolicy, resolution: "CLOSED", action: "STOP" }, count);
70633
- return blocked(config, v, false, basis, cw, void 0, void 0, grantObs);
70849
+ return blocked(config, v, false, basis, cw, void 0, void 0, grantObs, redacted);
70634
70850
  }
70635
70851
  const rd = (0, read_decision_js_1.readDecision)(pf.response);
70636
70852
  if (rd.reason === "EXECUTION_ACTION_UNRECOGNISED") {
@@ -70670,7 +70886,7 @@ var require_guard = __commonJS({
70670
70886
  if (gate.verdict === "block-strict") {
70671
70887
  const { basis } = freshnessFor(config, redacted, fctx, detection.artifacts);
70672
70888
  const { basis: cw } = conditionalWriteFor(config, redacted, cwctx, detection.artifacts);
70673
- return gate.decision === "BLOCK" ? blocked(config, { kind: "BLOCK", action: "STOP", envelope, receiptVerified }, true, basis, cw, void 0, void 0, grantObs) : blocked(config, { kind: "APPROVAL", action: "REQUEST_APPROVAL", envelope, receiptVerified }, true, basis, cw, void 0, void 0, grantObs);
70889
+ return gate.decision === "BLOCK" ? blocked(config, { kind: "BLOCK", action: "STOP", envelope, receiptVerified }, true, basis, cw, void 0, void 0, grantObs, redacted) : blocked(config, { kind: "APPROVAL", action: "REQUEST_APPROVAL", envelope, receiptVerified }, true, basis, cw, void 0, void 0, grantObs, redacted);
70674
70890
  }
70675
70891
  const kind = gate.kind;
70676
70892
  if (grantObs && grantObs.requested) {
@@ -70816,7 +71032,7 @@ var require_guard = __commonJS({
70816
71032
  const v = unavailableVerdict({ cause, failPolicy, resolution: "CLOSED", action: "STOP" }, count);
70817
71033
  const { basis } = freshnessFor(config, redacted, fctx, arts);
70818
71034
  const { basis: cw } = conditionalWriteFor(config, redacted, cwctx, arts);
70819
- return blocked(config, v, false, basis, cw, monitoring_delivery, monitoring_attestation, grantObs);
71035
+ return blocked(config, v, false, basis, cw, monitoring_delivery, monitoring_attestation, grantObs, redacted);
70820
71036
  }
70821
71037
  function isExpired(envelope) {
70822
71038
  const exp = envelope.expires_at;
@@ -73407,6 +73623,7 @@ var require_deploy_receipt_token = __commonJS({
73407
73623
  Object.defineProperty(exports2, "__esModule", { value: true });
73408
73624
  exports2.CHAIN_SIGNING_PREFIX = void 0;
73409
73625
  exports2.verifyDeployReceiptToken = verifyDeployReceiptToken;
73626
+ var next_agent_step_js_1 = require_next_agent_step();
73410
73627
  var node_crypto_1 = require("node:crypto");
73411
73628
  var sdk_1 = require_cjs3();
73412
73629
  var receipt_binding_js_1 = require_receipt_binding();
@@ -73427,6 +73644,31 @@ var require_deploy_receipt_token = __commonJS({
73427
73644
  }
73428
73645
  return v1;
73429
73646
  }
73647
+ function deriveKeyWithdrawalStatus(ts, keyMeta) {
73648
+ const KNOWN_STATUSES = ["active", "retired", "revoked", null];
73649
+ if (!KNOWN_STATUSES.includes(keyMeta.status))
73650
+ return "UNKNOWN_KEY_STATUS";
73651
+ if (typeof keyMeta.revoked_at === "string" && keyMeta.revoked_at.length > 0)
73652
+ return "KEY_REVOKED";
73653
+ if (typeof keyMeta.retired_at === "string" && keyMeta.retired_at.length > 0 && ts) {
73654
+ const issued = Date.parse(ts);
73655
+ const retired = Date.parse(keyMeta.retired_at);
73656
+ if (Number.isFinite(issued) && Number.isFinite(retired) && issued >= retired) {
73657
+ return "KEY_RETIRED_AFTER_SIGNING";
73658
+ }
73659
+ }
73660
+ if (keyMeta.status === "revoked") {
73661
+ const at = keyMeta.compromised_at;
73662
+ if (typeof at !== "string" || at.length === 0)
73663
+ return "REVOKED_KEY_UNDECIDABLE";
73664
+ const boundary = Date.parse(at);
73665
+ const issued = typeof ts === "string" ? Date.parse(ts) : NaN;
73666
+ if (!Number.isFinite(boundary) || !Number.isFinite(issued))
73667
+ return "REVOKED_KEY_UNDECIDABLE";
73668
+ return issued >= boundary ? "REVOKED_KEY" : "REVOKED_KEY_UNDECIDABLE";
73669
+ }
73670
+ return null;
73671
+ }
73430
73672
  function isIssueTimeWithinKeyWindow(ts, keyMeta) {
73431
73673
  if (!keyMeta || keyMeta.status === "active")
73432
73674
  return true;
@@ -73451,6 +73693,12 @@ var require_deploy_receipt_token = __commonJS({
73451
73693
  return false;
73452
73694
  return true;
73453
73695
  }
73696
+ function optionalString(source, field) {
73697
+ if (!source || typeof source !== "object")
73698
+ return null;
73699
+ const v = source[field];
73700
+ return typeof v === "string" && v.length > 0 ? v : null;
73701
+ }
73454
73702
  function resolveKey(kid, registry, pinnedKeyPem) {
73455
73703
  if (typeof pinnedKeyPem === "string" && pinnedKeyPem.trim().length > 0) {
73456
73704
  try {
@@ -73458,7 +73706,9 @@ var require_deploy_receipt_token = __commonJS({
73458
73706
  publicKey: (0, node_crypto_1.createPublicKey)(pinnedKeyPem),
73459
73707
  status: "active",
73460
73708
  valid_from: null,
73461
- retired_at: null
73709
+ retired_at: null,
73710
+ revoked_at: null,
73711
+ compromised_at: null
73462
73712
  };
73463
73713
  } catch {
73464
73714
  return null;
@@ -73473,9 +73723,11 @@ var require_deploy_receipt_token = __commonJS({
73473
73723
  try {
73474
73724
  return {
73475
73725
  publicKey: (0, node_crypto_1.createPublicKey)(entry.public_key_pem),
73476
- status: entry.status === "retired" ? "retired" : "active",
73726
+ status: typeof entry.status === "string" ? entry.status : null,
73477
73727
  valid_from: entry.valid_from || null,
73478
- retired_at: entry.retired_at || null
73728
+ retired_at: entry.retired_at || null,
73729
+ revoked_at: optionalString(entry, "revoked_at"),
73730
+ compromised_at: optionalString(entry, "compromised_at")
73479
73731
  };
73480
73732
  } catch {
73481
73733
  return null;
@@ -73504,7 +73756,12 @@ var require_deploy_receipt_token = __commonJS({
73504
73756
  bound_artifact_id: artifact == null ? null : String(artifact),
73505
73757
  verdict_fingerprint: typeof envelope.fingerprint === "string" ? envelope.fingerprint : typeof payload.fp === "string" ? payload.fp : void 0,
73506
73758
  body_hash: typeof payload.bh === "string" ? payload.bh : void 0,
73507
- target_id: envelope.target_id == null ? void 0 : String(envelope.target_id)
73759
+ target_id: envelope.target_id == null ? void 0 : String(envelope.target_id),
73760
+ // Read from the envelope the caller supplied. On the currently_authorized path the
73761
+ // body hash has already bound it; on the expired / retired-key paths the signature
73762
+ // was authentic too. Every path that did NOT authenticate returns through fail(),
73763
+ // which sets view: null — so this field cannot carry an unsigned step.
73764
+ next_agent_step: (0, next_agent_step_js_1.readNextAgentStep)(envelope)
73508
73765
  };
73509
73766
  }
73510
73767
  function verifyDeployReceiptToken(input, _intended = {}, nowMs) {
@@ -73549,6 +73806,14 @@ var require_deploy_receipt_token = __commonJS({
73549
73806
  return fail("INVALID_SIGNATURE", "invalid_signature", { payload, authz_reason: "delimiter_in_field" });
73550
73807
  }
73551
73808
  }
73809
+ const withdrawn = deriveKeyWithdrawalStatus(typeof payload.ts === "string" ? payload.ts : void 0, resolved);
73810
+ if (withdrawn) {
73811
+ return fail(withdrawn, withdrawn === "UNKNOWN_KEY_STATUS" ? "unknown_key_status" : "revoked_key", {
73812
+ payload,
73813
+ authz_reason: withdrawn.toLowerCase(),
73814
+ key_status: withdrawn === "UNKNOWN_KEY_STATUS" ? "unknown" : "revoked"
73815
+ });
73816
+ }
73552
73817
  if (resolved.status === "retired") {
73553
73818
  if (!isIssueTimeWithinKeyWindow(typeof payload.ts === "string" ? payload.ts : void 0, resolved)) {
73554
73819
  return fail("INVALID_SIGNATURE", "invalid_signature", { payload, authz_reason: "retired_key_outside_window" });
@@ -73629,6 +73894,7 @@ var require_deploy_gate = __commonJS({
73629
73894
  exports2.isVerifiedDeployReceiptView = isVerifiedDeployReceiptView;
73630
73895
  exports2.deployGate = deployGate;
73631
73896
  var deploy_receipt_token_js_1 = require_deploy_receipt_token();
73897
+ var next_agent_step_js_1 = require_next_agent_step();
73632
73898
  exports2.DEPLOY_RECEIPT_VIEW_SPEC = "deploy-receipt-view.v1";
73633
73899
  function asVerifiedDeployReceiptView(view, verify_status = "VERIFIED_CURRENT") {
73634
73900
  return {
@@ -73690,16 +73956,21 @@ var require_deploy_gate = __commonJS({
73690
73956
  bound_artifact_id: r && r.bound_artifact_id != null ? norm(r.bound_artifact_id) : null,
73691
73957
  operation: r && r.operation != null ? String(r.operation) : null
73692
73958
  });
73693
- const deny = (state, reason) => ({
73694
- deploy_allowed: false,
73695
- state,
73696
- reason,
73697
- enforcement_state,
73698
- inescapable_deploy: false,
73699
- residuals: [],
73700
- detail: detailOf(receipt),
73701
- verification
73702
- });
73959
+ const nextStepOf = (r) => verification.mode === "token" ? (0, next_agent_step_js_1.readNextAgentStep)(r) : null;
73960
+ const deny = (state, reason) => {
73961
+ const step = nextStepOf(receipt);
73962
+ return {
73963
+ deploy_allowed: false,
73964
+ state,
73965
+ reason,
73966
+ enforcement_state,
73967
+ inescapable_deploy: false,
73968
+ residuals: [],
73969
+ detail: detailOf(receipt),
73970
+ verification,
73971
+ ...step ? { next_step: step } : {}
73972
+ };
73973
+ };
73703
73974
  if (!target.environment || String(target.environment).trim() === "" || !target.artifact_id || String(target.artifact_id).trim() === "") {
73704
73975
  return deny(allowPending ? "pending" : "failure", "inputs_incomplete");
73705
73976
  }
@@ -74040,18 +74311,168 @@ var require_coverage_report = __commonJS({
74040
74311
  }
74041
74312
  });
74042
74313
 
74314
+ // node_modules/@coderifts/agent-guard/dist/cjs/posture-receipt.js
74315
+ var require_posture_receipt = __commonJS({
74316
+ "node_modules/@coderifts/agent-guard/dist/cjs/posture-receipt.js"(exports2) {
74317
+ "use strict";
74318
+ Object.defineProperty(exports2, "__esModule", { value: true });
74319
+ exports2.POSTURE_CLOCK_SKEW_TOLERANCE_MS = exports2.POSTURE_RECEIPT_V = void 0;
74320
+ exports2.verifyPostureReceipt = verifyPostureReceipt;
74321
+ var node_crypto_1 = require("node:crypto");
74322
+ exports2.POSTURE_RECEIPT_V = "cr.posture.receipt.v1";
74323
+ exports2.POSTURE_CLOCK_SKEW_TOLERANCE_MS = 5e3;
74324
+ function resolvePostureKey(kid, registry, pinnedKeyPem) {
74325
+ if (typeof pinnedKeyPem === "string" && pinnedKeyPem.trim().length > 0) {
74326
+ try {
74327
+ return { ok: true, key: (0, node_crypto_1.createPublicKey)(pinnedKeyPem) };
74328
+ } catch {
74329
+ return { ok: false, status: "POSTURE_UNKNOWN_KEY" };
74330
+ }
74331
+ }
74332
+ if (!registry || !Array.isArray(registry.keys) || !kid) {
74333
+ return { ok: false, status: "POSTURE_UNKNOWN_KEY" };
74334
+ }
74335
+ const matches = registry.keys.filter((k) => k && k.kid === kid && typeof k.public_key_pem === "string");
74336
+ if (matches.length === 0)
74337
+ return { ok: false, status: "POSTURE_UNKNOWN_KEY" };
74338
+ const entry = matches.find((k) => k.status === "active");
74339
+ if (!entry)
74340
+ return { ok: false, status: "POSTURE_REVOKED_KEY" };
74341
+ try {
74342
+ return { ok: true, key: (0, node_crypto_1.createPublicKey)(entry.public_key_pem) };
74343
+ } catch {
74344
+ return { ok: false, status: "POSTURE_UNKNOWN_KEY" };
74345
+ }
74346
+ }
74347
+ var fail = (status, reason, extra = {}) => ({ valid: false, status, reason, ...extra });
74348
+ function verifyPostureReceipt(token, input = {}) {
74349
+ if (typeof token !== "string" || token.length === 0) {
74350
+ return fail("POSTURE_MALFORMED", "malformed_structure");
74351
+ }
74352
+ const seg = token.split("|");
74353
+ if (seg.length !== 4 || seg[0] !== exports2.POSTURE_RECEIPT_V || seg.some((x) => !x)) {
74354
+ return fail("POSTURE_MALFORMED", "malformed_structure");
74355
+ }
74356
+ let preimageBytes;
74357
+ try {
74358
+ preimageBytes = Buffer.from(seg[2], "base64url");
74359
+ if (preimageBytes.length === 0)
74360
+ throw new Error("empty");
74361
+ } catch {
74362
+ return fail("POSTURE_MALFORMED", "bad_preimage");
74363
+ }
74364
+ const resolved = resolvePostureKey(seg[1], input.registry, input.pinnedKeyPem);
74365
+ if (!resolved.ok) {
74366
+ return fail(resolved.status, resolved.status === "POSTURE_REVOKED_KEY" ? "kid_revoked" : "unknown_kid");
74367
+ }
74368
+ const key = resolved.key;
74369
+ let sigOk = false;
74370
+ try {
74371
+ sigOk = (0, node_crypto_1.verify)(null, preimageBytes, key, Buffer.from(seg[3], "base64url"));
74372
+ } catch {
74373
+ return fail("POSTURE_INVALID_SIGNATURE", "signature_error");
74374
+ }
74375
+ if (!sigOk)
74376
+ return fail("POSTURE_INVALID_SIGNATURE", "signature_mismatch");
74377
+ let payload;
74378
+ try {
74379
+ payload = JSON.parse(preimageBytes.toString("utf8"));
74380
+ } catch {
74381
+ return fail("POSTURE_MALFORMED", "bad_json");
74382
+ }
74383
+ if (!payload || typeof payload !== "object") {
74384
+ return fail("POSTURE_MALFORMED", "bad_json");
74385
+ }
74386
+ if (payload.verdict !== "PASS") {
74387
+ return fail("POSTURE_FAIL", "posture_verdict_not_pass", { payload });
74388
+ }
74389
+ if (typeof payload.executor_kid === "string" && payload.executor_kid.length > 0 && payload.executor_kid !== seg[1]) {
74390
+ return fail("POSTURE_UNBOUND", "kid_mismatch", { payload });
74391
+ }
74392
+ if (Object.prototype.hasOwnProperty.call(payload, "v") && payload.v != null && payload.v !== exports2.POSTURE_RECEIPT_V) {
74393
+ return fail("POSTURE_MALFORMED", "body_version_mismatch", { payload });
74394
+ }
74395
+ if (typeof input.expectedDeploymentId === "string" && input.expectedDeploymentId.length > 0) {
74396
+ if (payload.deployment_id !== input.expectedDeploymentId) {
74397
+ return fail("POSTURE_UNBOUND", "deployment_id_mismatch", { payload });
74398
+ }
74399
+ }
74400
+ const bound = [];
74401
+ const notBound = [];
74402
+ const tuple = [
74403
+ ["executor_id", input.expectedExecutorId, "executor_id"],
74404
+ ["adapter_id", input.expectedAdapterId, "adapter_id"],
74405
+ ["target_uri", input.expectedTargetUri, "target_uri"],
74406
+ ["policy_hash", input.expectedPolicyHash, "policy_hash"]
74407
+ ];
74408
+ for (const [field, expected, label] of tuple) {
74409
+ if (typeof expected !== "string" || expected.length === 0) {
74410
+ notBound.push({
74411
+ field: label,
74412
+ reason: "the caller did not state an expected value, so this verification did not check it"
74413
+ });
74414
+ continue;
74415
+ }
74416
+ const actual = payload[field];
74417
+ if (typeof actual !== "string" || actual.length === 0) {
74418
+ return fail("POSTURE_UNBOUND", `${label}_absent`, { payload, bound, not_bound: notBound });
74419
+ }
74420
+ if (actual !== expected) {
74421
+ return fail("POSTURE_UNBOUND", `${label}_mismatch`, { payload, bound, not_bound: notBound });
74422
+ }
74423
+ bound.push(label);
74424
+ }
74425
+ let ageMs;
74426
+ if (typeof input.maxAgeMs === "number" && Number.isFinite(input.maxAgeMs)) {
74427
+ const measured = Date.parse(String(payload.measured_at));
74428
+ if (Number.isNaN(measured)) {
74429
+ return fail("POSTURE_STALE", "measured_at_unparseable", { payload });
74430
+ }
74431
+ const now = (input.now || (() => Date.now()))();
74432
+ if (!Number.isFinite(now)) {
74433
+ return fail("POSTURE_STALE", "now_unparseable", { payload });
74434
+ }
74435
+ ageMs = now - measured;
74436
+ if (!Number.isFinite(ageMs)) {
74437
+ return fail("POSTURE_STALE", "measured_at_unparseable", { payload });
74438
+ }
74439
+ if (ageMs < -exports2.POSTURE_CLOCK_SKEW_TOLERANCE_MS) {
74440
+ return fail("POSTURE_STALE", "measured_at_in_future", { payload, age_ms: ageMs });
74441
+ }
74442
+ if (ageMs > input.maxAgeMs) {
74443
+ return fail("POSTURE_STALE", "outside_freshness_window", { payload, age_ms: ageMs });
74444
+ }
74445
+ }
74446
+ return {
74447
+ valid: true,
74448
+ status: "POSTURE_PASS",
74449
+ reason: null,
74450
+ payload,
74451
+ ...ageMs === void 0 ? {} : { age_ms: ageMs },
74452
+ // What this PASS actually proved about the credential boundary — and what
74453
+ // it did not. A caller must not have to infer the difference.
74454
+ bound,
74455
+ not_bound: notBound
74456
+ };
74457
+ }
74458
+ }
74459
+ });
74460
+
74043
74461
  // node_modules/@coderifts/agent-guard/dist/cjs/atomic-profile.js
74044
74462
  var require_atomic_profile = __commonJS({
74045
74463
  "node_modules/@coderifts/agent-guard/dist/cjs/atomic-profile.js"(exports2) {
74046
74464
  "use strict";
74047
74465
  Object.defineProperty(exports2, "__esModule", { value: true });
74048
- exports2.ATOMIC_INVARIANTS = exports2.ATOMIC_PROFILE_UNSATISFIED = exports2.GUARD_ATOMIC_WIRE_VALUE = exports2.PROFILE_ENFORCING_ATOMIC_V1 = void 0;
74466
+ exports2.CREDENTIAL_BOUNDARY_BARE_REJECTED = exports2.ATOMIC_V2_MAX_AGE_MS_CAP = exports2.ATOMIC_INVARIANTS = exports2.ATOMIC_PROFILE_UNSATISFIED = exports2.GUARD_ATOMIC_WIRE_VALUE = exports2.PROFILE_ENFORCING_ATOMIC_V2 = exports2.PROFILE_ENFORCING_ATOMIC_V1 = void 0;
74049
74467
  exports2.createMutatorRegister = createMutatorRegister;
74050
74468
  exports2.isEnforcingAtomic = isEnforcingAtomic;
74469
+ exports2.isEnforcingAtomicV2 = isEnforcingAtomicV2;
74051
74470
  exports2.atomicConstructionProblems = atomicConstructionProblems;
74052
74471
  exports2.throwAtomicUnsatisfied = throwAtomicUnsatisfied;
74053
74472
  exports2.atomicOutcome = atomicOutcome;
74473
+ var posture_receipt_js_1 = require_posture_receipt();
74054
74474
  exports2.PROFILE_ENFORCING_ATOMIC_V1 = "ENFORCING_ATOMIC_V1";
74475
+ exports2.PROFILE_ENFORCING_ATOMIC_V2 = "ENFORCING_ATOMIC_V2";
74055
74476
  exports2.GUARD_ATOMIC_WIRE_VALUE = "ENFORCING_ATOMIC";
74056
74477
  exports2.ATOMIC_PROFILE_UNSATISFIED = "ATOMIC_PROFILE_UNSATISFIED";
74057
74478
  exports2.ATOMIC_INVARIANTS = Object.freeze([
@@ -74087,8 +74508,13 @@ var require_atomic_profile = __commonJS({
74087
74508
  return api;
74088
74509
  }
74089
74510
  function isEnforcingAtomic(profile) {
74090
- return profile === "ENFORCING_ATOMIC" || profile === exports2.PROFILE_ENFORCING_ATOMIC_V1;
74511
+ return profile === "ENFORCING_ATOMIC" || profile === exports2.PROFILE_ENFORCING_ATOMIC_V1 || profile === exports2.PROFILE_ENFORCING_ATOMIC_V2;
74091
74512
  }
74513
+ function isEnforcingAtomicV2(profile) {
74514
+ return profile === exports2.PROFILE_ENFORCING_ATOMIC_V2;
74515
+ }
74516
+ exports2.ATOMIC_V2_MAX_AGE_MS_CAP = 864e5;
74517
+ exports2.CREDENTIAL_BOUNDARY_BARE_REJECTED = "credential_boundary: a verified cr.posture.receipt.v1 is required; a bare assertion is no longer accepted. ENFORCING_ATOMIC_V1 still accepts the bare form and is frozen \u2014 move to _V2 to get this check.";
74092
74518
  function atomicConstructionProblems(input) {
74093
74519
  const problems = [];
74094
74520
  const grant = input.executionGrant;
@@ -74125,6 +74551,42 @@ var require_atomic_profile = __commonJS({
74125
74551
  if (input.credentialBoundary !== true && typeof input.credentialBoundary !== "object") {
74126
74552
  problems.push("credential_boundary: credentialBoundary assertion required");
74127
74553
  }
74554
+ if (isEnforcingAtomicV2(input.profile)) {
74555
+ const cb = input.credentialBoundary;
74556
+ if (cb === true || !cb || typeof cb !== "object" || typeof cb.postureReceipt !== "string") {
74557
+ problems.push(exports2.CREDENTIAL_BOUNDARY_BARE_REJECTED);
74558
+ } else if (!cb.registry && !cb.pinnedKeyPem) {
74559
+ problems.push("credential_boundary: credentialBoundary.registry or .pinnedKeyPem required \u2014 the posture receipt is verified against a caller-supplied key; this package never fetches one.");
74560
+ } else {
74561
+ const deploymentId = typeof cb.deploymentId === "string" ? cb.deploymentId : "";
74562
+ if (deploymentId.length === 0) {
74563
+ problems.push("credential_boundary: credentialBoundary.deploymentId required under ENFORCING_ATOMIC_V2 \u2014 the posture receipt must be bound to this deployment.");
74564
+ }
74565
+ const maxAgeMs = cb.maxAgeMs;
74566
+ const maxAgeOk = typeof maxAgeMs === "number" && Number.isFinite(maxAgeMs) && maxAgeMs > 0 && maxAgeMs <= exports2.ATOMIC_V2_MAX_AGE_MS_CAP;
74567
+ if (typeof maxAgeMs !== "number" || !Number.isFinite(maxAgeMs) || maxAgeMs <= 0) {
74568
+ problems.push("credential_boundary: credentialBoundary.maxAgeMs required under ENFORCING_ATOMIC_V2 \u2014 a finite positive freshness window; the receipt signs measured_at and no expires_at.");
74569
+ } else if (maxAgeMs > exports2.ATOMIC_V2_MAX_AGE_MS_CAP) {
74570
+ problems.push(`credential_boundary: credentialBoundary.maxAgeMs exceeds the ${exports2.ATOMIC_V2_MAX_AGE_MS_CAP}ms cap (24h). A larger window is not a freshness check.`);
74571
+ }
74572
+ if (deploymentId.length > 0 && maxAgeOk) {
74573
+ const r = (0, posture_receipt_js_1.verifyPostureReceipt)(cb.postureReceipt, {
74574
+ registry: cb.registry,
74575
+ pinnedKeyPem: cb.pinnedKeyPem,
74576
+ expectedDeploymentId: deploymentId,
74577
+ expectedExecutorId: input.executorId,
74578
+ expectedAdapterId: input.adapterId,
74579
+ expectedTargetUri: input.targetUri,
74580
+ expectedPolicyHash: input.policyHash,
74581
+ maxAgeMs,
74582
+ now: cb.now
74583
+ });
74584
+ if (!r.valid) {
74585
+ problems.push(`credential_boundary: posture receipt not verified \u2014 ${r.status} (${r.reason}). ` + (r.status === "POSTURE_STALE" ? "This is the caller-supplied freshness window (maxAgeMs), not a receipt-carried expiry: cr.posture.receipt.v1 signs measured_at and no expires_at." : r.status === "POSTURE_FAIL" ? "The signature verified; the posture did not. A signed FAIL is a drift artifact \u2014 the boundary regressed, the receipt is intact." : "Supply a posture receipt signed by a key in the registry, bound to this deployment_id, with verdict PASS."));
74586
+ }
74587
+ }
74588
+ }
74589
+ }
74128
74590
  return problems;
74129
74591
  }
74130
74592
  function throwAtomicUnsatisfied(problems) {
@@ -74153,11 +74615,13 @@ var require_with_coderifts = __commonJS({
74153
74615
  "node_modules/@coderifts/agent-guard/dist/cjs/with-coderifts.js"(exports2) {
74154
74616
  "use strict";
74155
74617
  Object.defineProperty(exports2, "__esModule", { value: true });
74156
- exports2.PROFILE_ENFORCING_ATOMIC_V1 = exports2.PROFILE_ENFORCING_STRICT_V1 = void 0;
74618
+ exports2.UNVERSIONED_PROFILE_NOTICE = exports2.PROFILE_ENFORCING_ATOMIC_V2 = exports2.PROFILE_ENFORCING_ATOMIC_V1 = exports2.PROFILE_ENFORCING_STRICT_V1 = void 0;
74157
74619
  exports2.foldTableSettledCalls = foldTableSettledCalls;
74158
74620
  exports2.guardedFractionAmongRoutes = guardedFractionAmongRoutes;
74621
+ exports2._resetUnversionedProfileNoticeForTest = _resetUnversionedProfileNoticeForTest;
74159
74622
  exports2.withCodeRifts = withCodeRifts;
74160
74623
  var tool_registry_js_1 = require_tool_registry();
74624
+ var execution_grant_js_1 = require_execution_grant2();
74161
74625
  var coverage_observed_js_1 = require_coverage_observed();
74162
74626
  var atomic_profile_js_1 = require_atomic_profile();
74163
74627
  function foldTableSettledCalls(events) {
@@ -74185,9 +74649,13 @@ var require_with_coderifts = __commonJS({
74185
74649
  Object.defineProperty(exports2, "PROFILE_ENFORCING_ATOMIC_V1", { enumerable: true, get: function() {
74186
74650
  return atomic_profile_js_2.PROFILE_ENFORCING_ATOMIC_V1;
74187
74651
  } });
74652
+ Object.defineProperty(exports2, "PROFILE_ENFORCING_ATOMIC_V2", { enumerable: true, get: function() {
74653
+ return atomic_profile_js_2.PROFILE_ENFORCING_ATOMIC_V2;
74654
+ } });
74188
74655
  var ACCEPTED_PROFILES = Object.freeze([
74189
74656
  "ENFORCING_STRICT_V1",
74190
74657
  "ENFORCING_STRICT",
74658
+ "ENFORCING_ATOMIC_V2",
74191
74659
  "ENFORCING_ATOMIC_V1",
74192
74660
  "ENFORCING_ATOMIC"
74193
74661
  ]);
@@ -74211,6 +74679,19 @@ var require_with_coderifts = __commonJS({
74211
74679
  function isEnforcingStrict(input) {
74212
74680
  return input.profile === "ENFORCING_STRICT" || input.profile === exports2.PROFILE_ENFORCING_STRICT_V1;
74213
74681
  }
74682
+ exports2.UNVERSIONED_PROFILE_NOTICE = "ENFORCING_STRICT is the unversioned spelling of ENFORCING_STRICT_V1; prefer the versioned name.";
74683
+ var noticedUnversionedProfile = false;
74684
+ function _resetUnversionedProfileNoticeForTest() {
74685
+ noticedUnversionedProfile = false;
74686
+ }
74687
+ function noticeUnversionedProfileOnce(profile) {
74688
+ if (profile !== "ENFORCING_STRICT")
74689
+ return;
74690
+ if (noticedUnversionedProfile)
74691
+ return;
74692
+ noticedUnversionedProfile = true;
74693
+ console.warn(exports2.UNVERSIONED_PROFILE_NOTICE);
74694
+ }
74214
74695
  function enforcingStrictExecutionChainProblems(input) {
74215
74696
  const grant = input.executionGrant;
74216
74697
  const enabled = !!(grant && grant.enabled === true);
@@ -74441,6 +74922,7 @@ var require_with_coderifts = __commonJS({
74441
74922
  if (!input || typeof input !== "object") {
74442
74923
  throw new Error("withCodeRifts: input object is required");
74443
74924
  }
74925
+ noticeUnversionedProfileOnce(input.profile);
74444
74926
  const problems = [];
74445
74927
  if (typeof input.operation !== "string" || input.operation.trim() === "") {
74446
74928
  problems.push("`operation` is required and must be a non-empty string (receipts bind to an operation; merge != deploy, so there is no safe default)");
@@ -74465,16 +74947,21 @@ var require_with_coderifts = __commonJS({
74465
74947
  problems.push(...enforcingStrictExecutionChainProblems(input));
74466
74948
  }
74467
74949
  if ((0, atomic_profile_js_1.isEnforcingAtomic)(input.profile)) {
74950
+ const v2 = (0, execution_grant_js_1.resolveV2Fields)(input);
74468
74951
  const atomicProblems = (0, atomic_profile_js_1.atomicConstructionProblems)({
74469
74952
  executionGrant: input.executionGrant,
74470
- executorId: input.executorId,
74471
- adapterId: input.adapterId,
74472
- targetUri: input.targetUri,
74953
+ executorId: v2.executorId,
74954
+ adapterId: v2.adapterId,
74955
+ targetUri: v2.targetUri,
74956
+ // Previously never forwarded, so the posture verifier's policy_hash
74957
+ // binding could not fire no matter what the caller configured.
74958
+ policyHash: v2.policyHash,
74473
74959
  executorAttestation: input.executorAttestation,
74474
74960
  mutatorRegister: input.mutatorRegister,
74475
74961
  casAdapter: input.casAdapter,
74476
74962
  readBack: input.readBack,
74477
- credentialBoundary: input.credentialBoundary
74963
+ credentialBoundary: input.credentialBoundary,
74964
+ profile: input.profile
74478
74965
  });
74479
74966
  if (atomicProblems.length > 0)
74480
74967
  (0, atomic_profile_js_1.throwAtomicUnsatisfied)(atomicProblems);
@@ -74553,6 +75040,7 @@ var require_with_coderifts = __commonJS({
74553
75040
  }
74554
75041
  if (input.executionGrant !== void 0) {
74555
75042
  guard.executionGrant = input.executionGrant;
75043
+ Object.assign(guard, (0, execution_grant_js_1.resolveV2Fields)(input));
74556
75044
  }
74557
75045
  const strict = isEnforcingStrict(input);
74558
75046
  if (strict) {
@@ -75105,49 +75593,140 @@ var require_gemini = __commonJS({
75105
75593
  }
75106
75594
  });
75107
75595
 
75108
- // node_modules/@coderifts/agent-guard/dist/cjs/execute-tool-call.js
75109
- var require_execute_tool_call = __commonJS({
75110
- "node_modules/@coderifts/agent-guard/dist/cjs/execute-tool-call.js"(exports2) {
75596
+ // node_modules/@coderifts/agent-guard/dist/cjs/adapters/langchain.js
75597
+ var require_langchain = __commonJS({
75598
+ "node_modules/@coderifts/agent-guard/dist/cjs/adapters/langchain.js"(exports2) {
75111
75599
  "use strict";
75112
75600
  Object.defineProperty(exports2, "__esModule", { value: true });
75113
- exports2.isGuardOutcome = isGuardOutcome;
75114
- exports2.executeProtectedTool = executeProtectedTool;
75115
- exports2.surfaceEnvelopeFields = surfaceEnvelopeFields;
75116
- exports2.executeOpenAIToolCall = executeOpenAIToolCall;
75117
- exports2.executeAnthropicToolCall = executeAnthropicToolCall;
75118
- exports2.executeGeminiToolCall = executeGeminiToolCall;
75119
- exports2.executeLangGraphToolCall = executeLangGraphToolCall;
75120
- var execution_proof_js_1 = require_execution_proof();
75121
- var openai_js_1 = require_openai();
75122
- var anthropic_js_1 = require_anthropic();
75123
- var gemini_js_1 = require_gemini();
75124
- var langgraph_js_1 = require_langgraph();
75125
- function resolveProtectedTools(table) {
75126
- if (Array.isArray(table))
75127
- return table;
75128
- if (table && typeof table === "object") {
75129
- const bag = table;
75130
- if (Array.isArray(bag.protected_tools) && bag.protected_tools.length > 0) {
75131
- return bag.protected_tools;
75132
- }
75133
- if (Array.isArray(bag.tools)) {
75134
- const withExecute = bag.tools.filter((t) => t && typeof t === "object" && typeof t.execute === "function");
75135
- if (withExecute.length > 0)
75136
- return withExecute;
75137
- }
75601
+ exports2.LANGCHAIN_ARTIFACT_SPEC = void 0;
75602
+ exports2.defaultSerializeLangChainToolResult = defaultSerializeLangChainToolResult;
75603
+ exports2.bindLangChainToolOutcome = bindLangChainToolOutcome;
75604
+ var final_answer_proof_js_1 = require_final_answer_proof();
75605
+ var gate_refusal_js_1 = require_gate_refusal();
75606
+ function defaultSerializeLangChainToolResult(result) {
75607
+ if (typeof result === "string")
75608
+ return result;
75609
+ if (typeof result === "number" || typeof result === "boolean" || typeof result === "bigint" || result === null || result === void 0) {
75610
+ return String(result);
75611
+ }
75612
+ try {
75613
+ return JSON.stringify(result);
75614
+ } catch {
75615
+ return String(result);
75138
75616
  }
75139
- return [];
75140
75617
  }
75141
- function findTool(table, name) {
75142
- const tools = resolveProtectedTools(table);
75143
- return tools.find((t) => t && t.name === name);
75618
+ exports2.LANGCHAIN_ARTIFACT_SPEC = "coderifts-guard-artifact.v1";
75619
+ function bindLangChainToolOutcome(outcome, args) {
75620
+ const serialize = args.serialize ?? defaultSerializeLangChainToolResult;
75621
+ let body;
75622
+ if (outcome.executed === true) {
75623
+ body = serialize(outcome.result);
75624
+ } else if (outcome.executionAttempted === false) {
75625
+ body = (0, gate_refusal_js_1.formatGateRefusalBody)(outcome);
75626
+ } else {
75627
+ const err = "error" in outcome ? outcome.error : void 0;
75628
+ const kind = (0, gate_refusal_js_1.verdictKind)(outcome);
75629
+ body = `Tool execution failed after gate decision (verdict: ${kind}): ${(0, gate_refusal_js_1.formatGuardError)(err)}`;
75630
+ }
75631
+ const content = args.attachProof === false ? body : (0, final_answer_proof_js_1.attachProofToAgentResponse)(body, outcome.proof);
75632
+ const out = {
75633
+ content,
75634
+ artifact: {
75635
+ artifact_spec: exports2.LANGCHAIN_ARTIFACT_SPEC,
75636
+ final_answer_proof: outcome.proof,
75637
+ executed: outcome.executed === true,
75638
+ enforced: outcome.enforced === true,
75639
+ verdict: (0, gate_refusal_js_1.verdictKind)(outcome)
75640
+ },
75641
+ tool_call_id: args.tool_call_id
75642
+ };
75643
+ if (args.name != null && args.name !== "") {
75644
+ out.name = args.name;
75645
+ }
75646
+ return out;
75144
75647
  }
75145
- function isGuardOutcome(x) {
75648
+ }
75649
+ });
75650
+
75651
+ // node_modules/@coderifts/agent-guard/dist/cjs/adapters/crewai.js
75652
+ var require_crewai = __commonJS({
75653
+ "node_modules/@coderifts/agent-guard/dist/cjs/adapters/crewai.js"(exports2) {
75654
+ "use strict";
75655
+ Object.defineProperty(exports2, "__esModule", { value: true });
75656
+ exports2.defaultSerializeCrewAIToolResult = defaultSerializeCrewAIToolResult;
75657
+ exports2.bindCrewAIToolOutcome = bindCrewAIToolOutcome;
75658
+ var final_answer_proof_js_1 = require_final_answer_proof();
75659
+ var gate_refusal_js_1 = require_gate_refusal();
75660
+ function defaultSerializeCrewAIToolResult(result) {
75661
+ if (typeof result === "string")
75662
+ return result;
75663
+ if (typeof result === "number" || typeof result === "boolean" || typeof result === "bigint" || result === null || result === void 0) {
75664
+ return String(result);
75665
+ }
75666
+ try {
75667
+ return JSON.stringify(result);
75668
+ } catch {
75669
+ return String(result);
75670
+ }
75671
+ }
75672
+ function bindCrewAIToolOutcome(outcome, args) {
75673
+ const serialize = args.serialize ?? defaultSerializeCrewAIToolResult;
75674
+ let body;
75675
+ let resultAsAnswer;
75676
+ if (outcome.executed === true) {
75677
+ body = serialize(outcome.result);
75678
+ resultAsAnswer = false;
75679
+ } else if (outcome.executionAttempted === false) {
75680
+ body = (0, gate_refusal_js_1.formatGateRefusalBody)(outcome);
75681
+ resultAsAnswer = true;
75682
+ } else {
75683
+ const err = "error" in outcome ? outcome.error : void 0;
75684
+ const kind = (0, gate_refusal_js_1.verdictKind)(outcome);
75685
+ body = `Tool execution failed after gate decision (verdict: ${kind}): ${(0, gate_refusal_js_1.formatGuardError)(err)}`;
75686
+ resultAsAnswer = true;
75687
+ }
75688
+ const result = args.attachProof === false ? body : (0, final_answer_proof_js_1.attachProofToAgentResponse)(body, outcome.proof);
75689
+ const out = {
75690
+ result,
75691
+ result_as_answer: resultAsAnswer,
75692
+ tool_name: args.tool_name,
75693
+ final_answer_proof: outcome.proof
75694
+ };
75695
+ return out;
75696
+ }
75697
+ }
75698
+ });
75699
+
75700
+ // node_modules/@coderifts/agent-guard/dist/cjs/adapters/vercel.js
75701
+ var require_vercel = __commonJS({
75702
+ "node_modules/@coderifts/agent-guard/dist/cjs/adapters/vercel.js"(exports2) {
75703
+ "use strict";
75704
+ Object.defineProperty(exports2, "__esModule", { value: true });
75705
+ exports2.protectedToolToVercel = protectedToolToVercel;
75706
+ exports2.toVercelTools = toVercelTools;
75707
+ exports2.withCodeRiftsVercel = withCodeRiftsVercel;
75708
+ exports2.vercelToolAdapter = vercelToolAdapter;
75709
+ exports2.defaultSerializeVercelToolResult = defaultSerializeVercelToolResult;
75710
+ exports2.bindVercelGuardOutcome = bindVercelGuardOutcome;
75711
+ var with_coderifts_js_1 = require_with_coderifts();
75712
+ var execution_proof_js_1 = require_execution_proof();
75713
+ var final_answer_proof_js_1 = require_final_answer_proof();
75714
+ var gate_refusal_js_1 = require_gate_refusal();
75715
+ var EMPTY_PARAMETERS = Object.freeze({
75716
+ type: "object",
75717
+ properties: {}
75718
+ });
75719
+ function looksLikeGuardOutcome(x) {
75146
75720
  if (!x || typeof x !== "object")
75147
75721
  return false;
75148
75722
  const o = x;
75149
75723
  return typeof o.executed === "boolean" && typeof o.executionAttempted === "boolean" && o.proof != null && typeof o.proof === "object" && o.verdict != null && typeof o.verdict === "object";
75150
75724
  }
75725
+ function toolCallIdFromOptions(options) {
75726
+ if (options && typeof options.toolCallId === "string")
75727
+ return options.toolCallId;
75728
+ return "";
75729
+ }
75151
75730
  var FRESHNESS_NOT_CONFIGURED = Object.freeze({
75152
75731
  wiring: "NOT_CONFIGURED",
75153
75732
  write_style: false,
@@ -75159,14 +75738,7 @@ var require_execute_tool_call = __commonJS({
75159
75738
  write_style: false,
75160
75739
  mutating: false
75161
75740
  });
75162
- function notObserved() {
75163
- return {
75164
- status: "not_observed",
75165
- observed_at: (/* @__PURE__ */ new Date()).toISOString(),
75166
- host_attestation: "absent"
75167
- };
75168
- }
75169
- function unknownToolOutcome(toolName) {
75741
+ function guardedNonOutcomeRefusal(toolName) {
75170
75742
  const verdict = {
75171
75743
  kind: "UNAVAILABLE",
75172
75744
  cause: "CONFIG_ERROR",
@@ -75176,7 +75748,197 @@ var require_execute_tool_call = __commonJS({
75176
75748
  decisionMissing: true,
75177
75749
  unavailableCount: 1
75178
75750
  };
75179
- const commit_observation = notObserved();
75751
+ const commit_observation = {
75752
+ status: "not_observed",
75753
+ observed_at: (/* @__PURE__ */ new Date()).toISOString(),
75754
+ host_attestation: "absent"
75755
+ };
75756
+ const proof = (0, execution_proof_js_1.buildExecutionProof)({
75757
+ preflighted: false,
75758
+ executionAttempted: false,
75759
+ executed: false,
75760
+ enforced: false,
75761
+ verdict,
75762
+ commitObservation: commit_observation
75763
+ });
75764
+ void toolName;
75765
+ return {
75766
+ executionAttempted: false,
75767
+ executed: false,
75768
+ enforced: false,
75769
+ verdict,
75770
+ preflighted: false,
75771
+ proof,
75772
+ freshness: FRESHNESS_NOT_CONFIGURED,
75773
+ conditional_write: CW_NOT_REPORTED,
75774
+ commit_observation
75775
+ };
75776
+ }
75777
+ function protectedToolToVercel(tool) {
75778
+ const parameters = tool.inputSchema != null && typeof tool.inputSchema === "object" && !Array.isArray(tool.inputSchema) ? tool.inputSchema : { ...EMPTY_PARAMETERS };
75779
+ const execute = async (args, options) => {
75780
+ const raw = await Promise.resolve().then(() => tool.execute(args));
75781
+ const bindArgs = {
75782
+ toolCallId: toolCallIdFromOptions(options),
75783
+ toolName: tool.name
75784
+ };
75785
+ if (looksLikeGuardOutcome(raw)) {
75786
+ return bindVercelGuardOutcome(raw, bindArgs).result;
75787
+ }
75788
+ if (tool._coderifts && tool._coderifts.guarded) {
75789
+ return bindVercelGuardOutcome(guardedNonOutcomeRefusal(tool.name), bindArgs).result;
75790
+ }
75791
+ return raw;
75792
+ };
75793
+ const out = {
75794
+ parameters,
75795
+ execute
75796
+ };
75797
+ if (tool.description != null && tool.description !== "") {
75798
+ out.description = tool.description;
75799
+ }
75800
+ return out;
75801
+ }
75802
+ function toVercelTools(protectedTools) {
75803
+ const out = {};
75804
+ for (const t of protectedTools) {
75805
+ out[t.name] = protectedToolToVercel(t);
75806
+ }
75807
+ return out;
75808
+ }
75809
+ function withCodeRiftsVercel(input) {
75810
+ const core = (0, with_coderifts_js_1.withCodeRifts)(input);
75811
+ return vercelToolAdapter(core);
75812
+ }
75813
+ function vercelToolAdapter(result) {
75814
+ const protected_tools = result.tools;
75815
+ const tools = toVercelTools(protected_tools);
75816
+ const out = {
75817
+ tools,
75818
+ protected_tools,
75819
+ registry_report: result.registry_report,
75820
+ composition_assurance: result.composition_assurance,
75821
+ receipt_thread: result.receipt_thread,
75822
+ coverage_observed: result.coverage_observed
75823
+ };
75824
+ if (result.repository !== void 0) {
75825
+ out.repository = result.repository;
75826
+ }
75827
+ return out;
75828
+ }
75829
+ function defaultSerializeVercelToolResult(result) {
75830
+ if (typeof result === "string")
75831
+ return result;
75832
+ if (typeof result === "number" || typeof result === "boolean" || typeof result === "bigint" || result === null || result === void 0) {
75833
+ return String(result);
75834
+ }
75835
+ try {
75836
+ return JSON.stringify(result);
75837
+ } catch {
75838
+ return String(result);
75839
+ }
75840
+ }
75841
+ function bindVercelGuardOutcome(outcome, args) {
75842
+ const toolCallId = args.toolCallId;
75843
+ const serialize = args.serialize ?? defaultSerializeVercelToolResult;
75844
+ let body;
75845
+ if (outcome.executed === true) {
75846
+ body = serialize(outcome.result);
75847
+ } else if (outcome.executionAttempted === false) {
75848
+ body = (0, gate_refusal_js_1.formatGateRefusalBody)(outcome);
75849
+ } else {
75850
+ const err = "error" in outcome ? outcome.error : void 0;
75851
+ const kind = (0, gate_refusal_js_1.verdictKind)(outcome);
75852
+ body = `Tool execution failed after gate decision (verdict: ${kind}): ${(0, gate_refusal_js_1.formatGuardError)(err)}`;
75853
+ }
75854
+ const result = args.attachProof === false ? body : (0, final_answer_proof_js_1.attachProofToAgentResponse)(body, outcome.proof);
75855
+ const part = {
75856
+ type: "tool-result",
75857
+ toolCallId,
75858
+ result
75859
+ };
75860
+ if (args.toolName != null && args.toolName !== "") {
75861
+ part.toolName = args.toolName;
75862
+ }
75863
+ return part;
75864
+ }
75865
+ }
75866
+ });
75867
+
75868
+ // node_modules/@coderifts/agent-guard/dist/cjs/execute-tool-call.js
75869
+ var require_execute_tool_call = __commonJS({
75870
+ "node_modules/@coderifts/agent-guard/dist/cjs/execute-tool-call.js"(exports2) {
75871
+ "use strict";
75872
+ Object.defineProperty(exports2, "__esModule", { value: true });
75873
+ exports2.isGuardOutcome = isGuardOutcome;
75874
+ exports2.executeProtectedTool = executeProtectedTool;
75875
+ exports2.surfaceEnvelopeFields = surfaceEnvelopeFields;
75876
+ exports2.executeOpenAIToolCall = executeOpenAIToolCall;
75877
+ exports2.executeAnthropicToolCall = executeAnthropicToolCall;
75878
+ exports2.executeGeminiToolCall = executeGeminiToolCall;
75879
+ exports2.executeLangGraphToolCall = executeLangGraphToolCall;
75880
+ exports2.executeVercelToolCall = executeVercelToolCall;
75881
+ var execution_proof_js_1 = require_execution_proof();
75882
+ var openai_js_1 = require_openai();
75883
+ var anthropic_js_1 = require_anthropic();
75884
+ var gemini_js_1 = require_gemini();
75885
+ var langgraph_js_1 = require_langgraph();
75886
+ var vercel_js_1 = require_vercel();
75887
+ function resolveProtectedTools(table) {
75888
+ if (Array.isArray(table))
75889
+ return table;
75890
+ if (table && typeof table === "object") {
75891
+ const bag = table;
75892
+ if (Array.isArray(bag.protected_tools) && bag.protected_tools.length > 0) {
75893
+ return bag.protected_tools;
75894
+ }
75895
+ if (Array.isArray(bag.tools)) {
75896
+ const withExecute = bag.tools.filter((t) => t && typeof t === "object" && typeof t.execute === "function");
75897
+ if (withExecute.length > 0)
75898
+ return withExecute;
75899
+ }
75900
+ }
75901
+ return [];
75902
+ }
75903
+ function findTool(table, name) {
75904
+ const tools = resolveProtectedTools(table);
75905
+ return tools.find((t) => t && t.name === name);
75906
+ }
75907
+ function isGuardOutcome(x) {
75908
+ if (!x || typeof x !== "object")
75909
+ return false;
75910
+ const o = x;
75911
+ return typeof o.executed === "boolean" && typeof o.executionAttempted === "boolean" && o.proof != null && typeof o.proof === "object" && o.verdict != null && typeof o.verdict === "object";
75912
+ }
75913
+ var FRESHNESS_NOT_CONFIGURED = Object.freeze({
75914
+ wiring: "NOT_CONFIGURED",
75915
+ write_style: false,
75916
+ require_freshness: false
75917
+ });
75918
+ var CW_NOT_REPORTED = Object.freeze({
75919
+ conditional_write: "not_reported",
75920
+ require_conditional_write: false,
75921
+ write_style: false,
75922
+ mutating: false
75923
+ });
75924
+ function notObserved() {
75925
+ return {
75926
+ status: "not_observed",
75927
+ observed_at: (/* @__PURE__ */ new Date()).toISOString(),
75928
+ host_attestation: "absent"
75929
+ };
75930
+ }
75931
+ function unknownToolOutcome(toolName) {
75932
+ const verdict = {
75933
+ kind: "UNAVAILABLE",
75934
+ cause: "CONFIG_ERROR",
75935
+ failPolicy: "closed",
75936
+ resolution: "CLOSED",
75937
+ action: "STOP",
75938
+ decisionMissing: true,
75939
+ unavailableCount: 1
75940
+ };
75941
+ const commit_observation = notObserved();
75180
75942
  const proof = (0, execution_proof_js_1.buildExecutionProof)({
75181
75943
  preflighted: false,
75182
75944
  executionAttempted: false,
@@ -75382,6 +76144,26 @@ var require_execute_tool_call = __commonJS({
75382
76144
  }
75383
76145
  return bound;
75384
76146
  }
76147
+ async function executeVercelToolCall(args) {
76148
+ const callArgs = parseMaybeJsonArgs(args.arguments);
76149
+ const outcome = await executeProtectedTool(args.tools, args.name, callArgs);
76150
+ const bound = (0, vercel_js_1.bindVercelGuardOutcome)(outcome, {
76151
+ toolCallId: args.toolCallId,
76152
+ toolName: args.name,
76153
+ serialize: args.serialize
76154
+ });
76155
+ if (outcome.executionAttempted === false) {
76156
+ const result = appendEnvelopeSurface(bound.result, outcome);
76157
+ const part = {
76158
+ type: "tool-result",
76159
+ toolCallId: args.toolCallId,
76160
+ toolName: args.name,
76161
+ result
76162
+ };
76163
+ return part;
76164
+ }
76165
+ return bound;
76166
+ }
75385
76167
  function parseMaybeJsonArgs(args) {
75386
76168
  if (typeof args === "string") {
75387
76169
  const s = args.trim();
@@ -75611,9 +76393,9 @@ var require_cjs4 = __commonJS({
75611
76393
  Object.defineProperty(exports2, "__esModule", { value: true });
75612
76394
  exports2.monitorAttestSigningInput = exports2.kidFromMonitoringAttestation = exports2.tryIssueMonitoringAttestation = exports2.DEFAULT_MONITORING_SINK_TIMEOUT_MS = exports2.ackBytes = exports2.verifyAckHmac = exports2.monitoringDeliveryFailClosed = exports2.formatMonitoringDeliveryLine = exports2.deliverMonitoring = exports2.hashObservedContent = exports2.observeCommit = exports2.deriveKeySignal = exports2.pathClass = exports2.classifyCommand = exports2.projectState = exports2.emptySessionState = exports2.computeTainted = exports2.evaluate = exports2.updateSession = exports2.SESSION_TAINT_VERSION = exports2.SessionTaintTracker = exports2.readDecision = exports2.EXECUTION_TIME_FP_REASONS = exports2.EXECUTION_STATE_UNMEASURABLE_NOTE = exports2.isUnmeasurableExecutionStateReason = exports2.computeCanonicalBundleFingerprint = exports2.authorizedFingerprintFromEnvelope = exports2.checkExecutionTimeFingerprint = exports2.computeBundleFingerprint = exports2.computeArtifactDigest = exports2.evaluateEnvelope = exports2.RECEIPT_PREV_NULL = exports2.decodeReceiptBodyPrev = exports2.previousReceiptCommitment = exports2.verifyReceiptChainLinkage = exports2.canonicalJson = exports2.computeBodyHash = exports2.bindReceiptToEnvelope = exports2.DETECTOR_VERSION = exports2.builtinDetector = exports2.resetPolicyWarnForTests = exports2.warnPolicyAbsentOnce = exports2.observePolicyPresence = exports2.detectPolicyPresence = exports2.policyPresenceOf = exports2.withPolicy = exports2.POLICY_ABSENT_WARN = exports2.POLICY_MARKER = exports2.CODERIFTS_POLICY = exports2.guardToolCall = void 0;
75613
76395
  exports2.createDbVersionToken = exports2.API_ABSENT_TOKEN = exports2.API_VERSION_TOKEN_PREFIX = exports2.apiTokenRaw = exports2.writeApiIfUnchanged = exports2.createApiVersionToken = exports2.identitiesEqual = exports2.fsObjectIdentity = exports2.UnsafeCasPathError = exports2.assertSafeCasPath = exports2.FS_ABSENT_TOKEN = exports2.FS_VERSION_TOKEN_PREFIX = exports2.fsTokenContentHash = exports2.createFsPriorContentResolver = exports2.writeFileIfUnchanged = exports2.readVersionedFile = exports2.createFsVersionToken = exports2.StaleVersionTokenAbort = exports2.executeIfUnchanged = exports2.RESIDUAL_UNCONDITIONAL_WRITE = exports2.conditionalWriteResidual = exports2.tokensEqual = exports2.buildConditionalWriteBasis = exports2.buildFreshnessBasis = exports2.collectFreshnessCallContext = exports2.artifactIdsForResolve = exports2.isMutatingCall = exports2.isWriteStyleCall = exports2.freshnessAllowsEnforce = exports2.computePathSetTreeHash = exports2.contentByteIdentical = exports2.assessWriteStylePrior = exports2.assessFreshness = exports2.deriveProofBanner = exports2.attachProofToAgentResponse = exports2.renderFinalAnswerProof = exports2.EXECUTION_PROOF_SPEC = exports2.assertEnforcedReceiptInvariant = exports2.hashExecutionResult = exports2.buildExecutionProof = exports2.COVERAGE_ATTEST_ENVELOPE_TAG = exports2.COVERAGE_ATTEST_SIGNING_PREFIX = exports2.COVERAGE_ATTEST_VERSION = exports2.coverageAttestSigningInput = exports2.kidFromCoverageAttestation = exports2.tryIssueCoverageAttestation = exports2.MONITOR_ATTEST_ENVELOPE_TAG = exports2.MONITOR_ATTEST_SIGNING_PREFIX = exports2.MONITOR_ATTEST_VERSION = exports2.receiptDigestOfToken = void 0;
75614
- exports2.guardedFractionAmongRoutes = exports2.foldTableSettledCalls = exports2.withCodeRifts = exports2.AUTO_DERIVE_READ_TIMEOUT_MS = exports2.AUTO_DERIVE_SOURCE = exports2.defaultFsReader = exports2.normalizeAutoDerive = exports2.runAutoDerive = exports2.AUTO_RECHECK_MAX_CAP = exports2.clampMaxAttempts = exports2.normalizeAutoRecheck = exports2.runAutoRecheckLoop = exports2.coverageReport = exports2.DEPLOY_REPAIRABLE_REASONS = exports2.bindDeploy = exports2.verifyDeployReceiptToken = exports2.DEPLOY_RECEIPT_VIEW_SPEC = exports2.isVerifiedDeployReceiptView = exports2.asVerifiedDeployReceiptView = exports2.deployGate = exports2.gateDecision = exports2.RegistryConstructionError = exports2.guardToolRegistry = exports2.globToRegExp = exports2.matchGlob = exports2.blobMapKey = exports2.classifyByName = exports2.resolveArtifacts = exports2.REMEDIATION_LOOP_ATTESTATION_SPEC = exports2.isCasAttestation = exports2.readPriorBlockRemediation = exports2.readRemediationTransaction = exports2.buildRemediationLoopAttestation = exports2.COMMIT_EVIDENCE_MISSING = exports2.CAS_ATTESTATION_SPEC = exports2.strictCommitObservation = exports2.extractExecutorAttestationToken = exports2.evaluateCasEvidence = exports2.isExecuteIfUnchangedOutcome = exports2.isGuardExecutionProof = exports2.buildCasAttestation = exports2.REGISTRY_ABSENT_TOKEN = exports2.REGISTRY_VERSION_TOKEN_PREFIX = exports2.registryTokenRaw = exports2.writeRegistryIfUnchanged = exports2.createRegistryVersionToken = exports2.DB_ABSENT_TOKEN = exports2.DB_VERSION_TOKEN_PREFIX = exports2.dbTokenRaw = exports2.writeDbIfUnchanged = void 0;
75615
- exports2.executeAnthropicToolCall = exports2.executeOpenAIToolCall = exports2.executeProtectedTool = exports2.defaultSerializeGeminiToolResult = exports2.bindGeminiGuardOutcome = exports2.protectedToolToFunctionDeclaration = exports2.toGeminiTools = exports2.geminiToolAdapter = exports2.withCodeRiftsGemini = exports2.measureFsAuthorizationToken = exports2.measureFsAuthorization = exports2.wrapWriteWithFsCas = exports2.inferFullFileWriteContent = exports2.inferFsPathFromArgs = exports2.FRESHNESS_RESOLVER_FIX = exports2.freshnessRefusalTeaching = exports2.formatGateRefusalBody = exports2.defaultSerializeLangGraphToolResult = exports2.bindLangGraphGuardOutcome = exports2.LangGraphToolsNotStructuredError = exports2.isLangGraphReactAgentTool = exports2.bindLangGraphTools = exports2.protectedToolToLangGraph = exports2.toLangGraphTools = exports2.langGraphToolAdapter = exports2.withCodeRiftsLangGraph = exports2.defaultSerializeAnthropicToolResult = exports2.bindAnthropicGuardOutcome = exports2.protectedToolToAnthropic = exports2.toAnthropicTools = exports2.anthropicToolAdapter = exports2.withCodeRiftsAnthropic = exports2.defaultSerializeOpenAIToolResult = exports2.bindOpenAIGuardOutcome = exports2.protectedToolToOpenAI = exports2.toOpenAITools = exports2.openAIToolAdapter = exports2.withCodeRiftsOpenAI = exports2.formatCoverageObservedLine = exports2.freezeCoverageObserved = exports2.createCoverageObserver = exports2.readExecutionGrantToken = exports2.isExecutionGrantEnabled = exports2.isEnforcingAtomic = exports2.atomicOutcome = exports2.ATOMIC_PROFILE_UNSATISFIED = exports2.ATOMIC_INVARIANTS = exports2.createMutatorRegister = exports2.PROFILE_ENFORCING_ATOMIC_V1 = exports2.PROFILE_ENFORCING_STRICT_V1 = void 0;
75616
- exports2.kidFromToolsetAttestation = exports2.tryIssueToolsetAttestation = exports2.toolsetAttestSigningInput = exports2.declarationEntriesFromTools = exports2.computeToolsetDigest = exports2.TOOLSET_ATTEST_STATEMENT = exports2.TOOLSET_ATTEST_ENVELOPE_TAG = exports2.TOOLSET_ATTEST_SIGNING_PREFIX = exports2.TOOLSET_ATTEST_VERSION = exports2.surfaceEnvelopeFields = exports2.isGuardOutcome = exports2.executeLangGraphToolCall = exports2.executeGeminiToolCall = void 0;
76396
+ exports2.AUTO_DERIVE_READ_TIMEOUT_MS = exports2.AUTO_DERIVE_SOURCE = exports2.defaultFsReader = exports2.normalizeAutoDerive = exports2.runAutoDerive = exports2.AUTO_RECHECK_MAX_CAP = exports2.clampMaxAttempts = exports2.normalizeAutoRecheck = exports2.runAutoRecheckLoop = exports2.coverageReport = exports2.DEPLOY_REPAIRABLE_REASONS = exports2.bindDeploy = exports2.NEXT_STEP_NOTE = exports2.NEXT_AGENT_ACTIONS = exports2.readNextAgentStep = exports2.verifyDeployReceiptToken = exports2.DEPLOY_RECEIPT_VIEW_SPEC = exports2.isVerifiedDeployReceiptView = exports2.asVerifiedDeployReceiptView = exports2.deployGate = exports2.gateDecision = exports2.RegistryConstructionError = exports2.guardToolRegistry = exports2.globToRegExp = exports2.matchGlob = exports2.blobMapKey = exports2.classifyByName = exports2.resolveArtifacts = exports2.REMEDIATION_LOOP_ATTESTATION_SPEC = exports2.isCasAttestation = exports2.readPriorBlockRemediation = exports2.readRemediationTransaction = exports2.buildRemediationLoopAttestation = exports2.COMMIT_EVIDENCE_MISSING = exports2.CAS_ATTESTATION_SPEC = exports2.strictCommitObservation = exports2.extractExecutorAttestationToken = exports2.evaluateCasEvidence = exports2.isExecuteIfUnchangedOutcome = exports2.isGuardExecutionProof = exports2.buildCasAttestation = exports2.REGISTRY_ABSENT_TOKEN = exports2.REGISTRY_VERSION_TOKEN_PREFIX = exports2.registryTokenRaw = exports2.writeRegistryIfUnchanged = exports2.createRegistryVersionToken = exports2.DB_ABSENT_TOKEN = exports2.DB_VERSION_TOKEN_PREFIX = exports2.dbTokenRaw = exports2.writeDbIfUnchanged = void 0;
76397
+ exports2.inferFsPathFromArgs = exports2.FRESHNESS_RESOLVER_FIX = exports2.freshnessRefusalTeaching = exports2.formatGateRefusalBody = exports2.defaultSerializeLangGraphToolResult = exports2.bindLangGraphGuardOutcome = exports2.LangGraphToolsNotStructuredError = exports2.isLangGraphReactAgentTool = exports2.bindLangGraphTools = exports2.protectedToolToLangGraph = exports2.toLangGraphTools = exports2.langGraphToolAdapter = exports2.withCodeRiftsLangGraph = exports2.defaultSerializeAnthropicToolResult = exports2.bindAnthropicGuardOutcome = exports2.protectedToolToAnthropic = exports2.toAnthropicTools = exports2.anthropicToolAdapter = exports2.withCodeRiftsAnthropic = exports2.defaultSerializeOpenAIToolResult = exports2.bindOpenAIGuardOutcome = exports2.protectedToolToOpenAI = exports2.toOpenAITools = exports2.openAIToolAdapter = exports2.withCodeRiftsOpenAI = exports2.formatCoverageObservedLine = exports2.freezeCoverageObserved = exports2.createCoverageObserver = exports2.readExecutionGrantToken = exports2.isExecutionGrantEnabled = exports2.POSTURE_CLOCK_SKEW_TOLERANCE_MS = exports2.POSTURE_RECEIPT_V = exports2.verifyPostureReceipt = exports2.ATOMIC_V2_MAX_AGE_MS_CAP = exports2.CREDENTIAL_BOUNDARY_BARE_REJECTED = exports2.atomicConstructionProblems = exports2.isEnforcingAtomicV2 = exports2.PROFILE_ENFORCING_ATOMIC_V2 = exports2.isEnforcingAtomic = exports2.atomicOutcome = exports2.ATOMIC_PROFILE_UNSATISFIED = exports2.ATOMIC_INVARIANTS = exports2.createMutatorRegister = exports2._resetUnversionedProfileNoticeForTest = exports2.UNVERSIONED_PROFILE_NOTICE = exports2.PROFILE_ENFORCING_ATOMIC_V1 = exports2.PROFILE_ENFORCING_STRICT_V1 = exports2.guardedFractionAmongRoutes = exports2.foldTableSettledCalls = exports2.withCodeRifts = void 0;
76398
+ exports2.kidFromToolsetAttestation = exports2.tryIssueToolsetAttestation = exports2.toolsetAttestSigningInput = exports2.declarationEntriesFromTools = exports2.computeToolsetDigest = exports2.TOOLSET_ATTEST_STATEMENT = exports2.TOOLSET_ATTEST_ENVELOPE_TAG = exports2.TOOLSET_ATTEST_SIGNING_PREFIX = exports2.TOOLSET_ATTEST_VERSION = exports2.surfaceEnvelopeFields = exports2.isGuardOutcome = exports2.executeVercelToolCall = exports2.executeLangGraphToolCall = exports2.executeGeminiToolCall = exports2.executeAnthropicToolCall = exports2.executeOpenAIToolCall = exports2.executeProtectedTool = exports2.defaultSerializeVercelToolResult = exports2.bindVercelGuardOutcome = exports2.protectedToolToVercel = exports2.toVercelTools = exports2.vercelToolAdapter = exports2.withCodeRiftsVercel = exports2.defaultSerializeCrewAIToolResult = exports2.bindCrewAIToolOutcome = exports2.LANGCHAIN_ARTIFACT_SPEC = exports2.defaultSerializeLangChainToolResult = exports2.bindLangChainToolOutcome = exports2.defaultSerializeGeminiToolResult = exports2.bindGeminiGuardOutcome = exports2.protectedToolToFunctionDeclaration = exports2.toGeminiTools = exports2.geminiToolAdapter = exports2.withCodeRiftsGemini = exports2.measureFsAuthorizationToken = exports2.measureFsAuthorization = exports2.wrapWriteWithFsCas = exports2.inferFullFileWriteContent = void 0;
75617
76399
  var guard_js_1 = require_guard();
75618
76400
  Object.defineProperty(exports2, "guardToolCall", { enumerable: true, get: function() {
75619
76401
  return guard_js_1.guardToolCall;
@@ -76048,6 +76830,16 @@ var require_cjs4 = __commonJS({
76048
76830
  Object.defineProperty(exports2, "verifyDeployReceiptToken", { enumerable: true, get: function() {
76049
76831
  return deploy_receipt_token_js_1.verifyDeployReceiptToken;
76050
76832
  } });
76833
+ var next_agent_step_js_1 = require_next_agent_step();
76834
+ Object.defineProperty(exports2, "readNextAgentStep", { enumerable: true, get: function() {
76835
+ return next_agent_step_js_1.readNextAgentStep;
76836
+ } });
76837
+ Object.defineProperty(exports2, "NEXT_AGENT_ACTIONS", { enumerable: true, get: function() {
76838
+ return next_agent_step_js_1.NEXT_AGENT_ACTIONS;
76839
+ } });
76840
+ Object.defineProperty(exports2, "NEXT_STEP_NOTE", { enumerable: true, get: function() {
76841
+ return next_agent_step_js_1.NEXT_STEP_NOTE;
76842
+ } });
76051
76843
  var deploy_bind_js_1 = require_deploy_bind();
76052
76844
  Object.defineProperty(exports2, "bindDeploy", { enumerable: true, get: function() {
76053
76845
  return deploy_bind_js_1.bindDeploy;
@@ -76104,6 +76896,12 @@ var require_cjs4 = __commonJS({
76104
76896
  Object.defineProperty(exports2, "PROFILE_ENFORCING_ATOMIC_V1", { enumerable: true, get: function() {
76105
76897
  return with_coderifts_js_1.PROFILE_ENFORCING_ATOMIC_V1;
76106
76898
  } });
76899
+ Object.defineProperty(exports2, "UNVERSIONED_PROFILE_NOTICE", { enumerable: true, get: function() {
76900
+ return with_coderifts_js_1.UNVERSIONED_PROFILE_NOTICE;
76901
+ } });
76902
+ Object.defineProperty(exports2, "_resetUnversionedProfileNoticeForTest", { enumerable: true, get: function() {
76903
+ return with_coderifts_js_1._resetUnversionedProfileNoticeForTest;
76904
+ } });
76107
76905
  var atomic_profile_js_1 = require_atomic_profile();
76108
76906
  Object.defineProperty(exports2, "createMutatorRegister", { enumerable: true, get: function() {
76109
76907
  return atomic_profile_js_1.createMutatorRegister;
@@ -76120,6 +76918,31 @@ var require_cjs4 = __commonJS({
76120
76918
  Object.defineProperty(exports2, "isEnforcingAtomic", { enumerable: true, get: function() {
76121
76919
  return atomic_profile_js_1.isEnforcingAtomic;
76122
76920
  } });
76921
+ Object.defineProperty(exports2, "PROFILE_ENFORCING_ATOMIC_V2", { enumerable: true, get: function() {
76922
+ return atomic_profile_js_1.PROFILE_ENFORCING_ATOMIC_V2;
76923
+ } });
76924
+ Object.defineProperty(exports2, "isEnforcingAtomicV2", { enumerable: true, get: function() {
76925
+ return atomic_profile_js_1.isEnforcingAtomicV2;
76926
+ } });
76927
+ Object.defineProperty(exports2, "atomicConstructionProblems", { enumerable: true, get: function() {
76928
+ return atomic_profile_js_1.atomicConstructionProblems;
76929
+ } });
76930
+ Object.defineProperty(exports2, "CREDENTIAL_BOUNDARY_BARE_REJECTED", { enumerable: true, get: function() {
76931
+ return atomic_profile_js_1.CREDENTIAL_BOUNDARY_BARE_REJECTED;
76932
+ } });
76933
+ Object.defineProperty(exports2, "ATOMIC_V2_MAX_AGE_MS_CAP", { enumerable: true, get: function() {
76934
+ return atomic_profile_js_1.ATOMIC_V2_MAX_AGE_MS_CAP;
76935
+ } });
76936
+ var posture_receipt_js_1 = require_posture_receipt();
76937
+ Object.defineProperty(exports2, "verifyPostureReceipt", { enumerable: true, get: function() {
76938
+ return posture_receipt_js_1.verifyPostureReceipt;
76939
+ } });
76940
+ Object.defineProperty(exports2, "POSTURE_RECEIPT_V", { enumerable: true, get: function() {
76941
+ return posture_receipt_js_1.POSTURE_RECEIPT_V;
76942
+ } });
76943
+ Object.defineProperty(exports2, "POSTURE_CLOCK_SKEW_TOLERANCE_MS", { enumerable: true, get: function() {
76944
+ return posture_receipt_js_1.POSTURE_CLOCK_SKEW_TOLERANCE_MS;
76945
+ } });
76123
76946
  var execution_grant_js_1 = require_execution_grant2();
76124
76947
  Object.defineProperty(exports2, "isExecutionGrantEnabled", { enumerable: true, get: function() {
76125
76948
  return execution_grant_js_1.isExecutionGrantEnabled;
@@ -76248,6 +77071,42 @@ var require_cjs4 = __commonJS({
76248
77071
  Object.defineProperty(exports2, "defaultSerializeGeminiToolResult", { enumerable: true, get: function() {
76249
77072
  return gemini_js_1.defaultSerializeGeminiToolResult;
76250
77073
  } });
77074
+ var langchain_js_1 = require_langchain();
77075
+ Object.defineProperty(exports2, "bindLangChainToolOutcome", { enumerable: true, get: function() {
77076
+ return langchain_js_1.bindLangChainToolOutcome;
77077
+ } });
77078
+ Object.defineProperty(exports2, "defaultSerializeLangChainToolResult", { enumerable: true, get: function() {
77079
+ return langchain_js_1.defaultSerializeLangChainToolResult;
77080
+ } });
77081
+ Object.defineProperty(exports2, "LANGCHAIN_ARTIFACT_SPEC", { enumerable: true, get: function() {
77082
+ return langchain_js_1.LANGCHAIN_ARTIFACT_SPEC;
77083
+ } });
77084
+ var crewai_js_1 = require_crewai();
77085
+ Object.defineProperty(exports2, "bindCrewAIToolOutcome", { enumerable: true, get: function() {
77086
+ return crewai_js_1.bindCrewAIToolOutcome;
77087
+ } });
77088
+ Object.defineProperty(exports2, "defaultSerializeCrewAIToolResult", { enumerable: true, get: function() {
77089
+ return crewai_js_1.defaultSerializeCrewAIToolResult;
77090
+ } });
77091
+ var vercel_js_1 = require_vercel();
77092
+ Object.defineProperty(exports2, "withCodeRiftsVercel", { enumerable: true, get: function() {
77093
+ return vercel_js_1.withCodeRiftsVercel;
77094
+ } });
77095
+ Object.defineProperty(exports2, "vercelToolAdapter", { enumerable: true, get: function() {
77096
+ return vercel_js_1.vercelToolAdapter;
77097
+ } });
77098
+ Object.defineProperty(exports2, "toVercelTools", { enumerable: true, get: function() {
77099
+ return vercel_js_1.toVercelTools;
77100
+ } });
77101
+ Object.defineProperty(exports2, "protectedToolToVercel", { enumerable: true, get: function() {
77102
+ return vercel_js_1.protectedToolToVercel;
77103
+ } });
77104
+ Object.defineProperty(exports2, "bindVercelGuardOutcome", { enumerable: true, get: function() {
77105
+ return vercel_js_1.bindVercelGuardOutcome;
77106
+ } });
77107
+ Object.defineProperty(exports2, "defaultSerializeVercelToolResult", { enumerable: true, get: function() {
77108
+ return vercel_js_1.defaultSerializeVercelToolResult;
77109
+ } });
76251
77110
  var execute_tool_call_js_1 = require_execute_tool_call();
76252
77111
  Object.defineProperty(exports2, "executeProtectedTool", { enumerable: true, get: function() {
76253
77112
  return execute_tool_call_js_1.executeProtectedTool;
@@ -76264,6 +77123,9 @@ var require_cjs4 = __commonJS({
76264
77123
  Object.defineProperty(exports2, "executeLangGraphToolCall", { enumerable: true, get: function() {
76265
77124
  return execute_tool_call_js_1.executeLangGraphToolCall;
76266
77125
  } });
77126
+ Object.defineProperty(exports2, "executeVercelToolCall", { enumerable: true, get: function() {
77127
+ return execute_tool_call_js_1.executeVercelToolCall;
77128
+ } });
76267
77129
  Object.defineProperty(exports2, "isGuardOutcome", { enumerable: true, get: function() {
76268
77130
  return execute_tool_call_js_1.isGuardOutcome;
76269
77131
  } });
@@ -76311,6 +77173,24 @@ var require_claude_hook = __commonJS({
76311
77173
  var { getApiKey } = require_config();
76312
77174
  var { cloudAuthorizePreflight } = require_cloud();
76313
77175
  var DEFAULT_SPEC_PATH = "api/openapi.yaml";
77176
+ var DEFAULT_SPEC_GLOBS = Object.freeze([
77177
+ "**/*openapi*.yaml",
77178
+ "**/*openapi*.yml",
77179
+ "**/*openapi*.json",
77180
+ "**/*swagger*.yaml",
77181
+ "**/*swagger*.yml",
77182
+ "**/*swagger*.json",
77183
+ "**/*asyncapi*.yaml",
77184
+ "**/*asyncapi*.yml",
77185
+ "**/*asyncapi*.json",
77186
+ "**/*.graphql",
77187
+ "**/*.gql",
77188
+ "**/*.proto",
77189
+ "**/*mcp*.json",
77190
+ "**/*mcp*.yaml",
77191
+ "**/*mcp*.yml",
77192
+ "**/*tool-schema*.json"
77193
+ ]);
76314
77194
  var CLOSED_ACTIONS = /* @__PURE__ */ new Set([
76315
77195
  "CONTINUE",
76316
77196
  "CONTINUE_WITH_MONITORING",
@@ -76320,8 +77200,9 @@ var require_claude_hook = __commonJS({
76320
77200
  var USAGE = [
76321
77201
  "Usage: coderifts claude-hook",
76322
77202
  "",
76323
- "Claude Code PreToolUse hook: gates Write|Edit|MultiEdit when they touch the",
76324
- "configured contract spec path. Reads JSON context from STDIN.",
77203
+ "Claude Code PreToolUse hook: gates Write|Edit|MultiEdit when they touch a",
77204
+ "governed contract path (default family + git config coderifts.specPath).",
77205
+ "Reads JSON context from STDIN.",
76325
77206
  "",
76326
77207
  "Exit map (Claude Code semantics \u2014 get this exactly right):",
76327
77208
  " 2 BLOCK \u2014 tool call cancelled (BLOCK/STOP, REQUEST_APPROVAL, unrecognised action,",
@@ -76336,7 +77217,7 @@ var require_claude_hook = __commonJS({
76336
77217
  "Parse-gap DEFAULT (exit 2): unparseable stdin / missing file_path \u2014 refusing (fail-closed);",
76337
77218
  " set CODERIFTS_ADVISORY=1 to soften. JSONL hook_blocked cause stdin_unparseable|missing_file_path.",
76338
77219
  "",
76339
- "Still exit 0 (nothing to govern): non-spec path, identical content, non-governed tool.",
77220
+ "Still exit 0 (nothing to govern): not-governed path (one stderr line), identical content, non-governed tool.",
76340
77221
  "",
76341
77222
  "CONTINUE_WITH_MONITORING: allow only if the host asserts a sink",
76342
77223
  " (CODERIFTS_MONITORING_SINK_WIRED=1|true or git config coderifts.monitoringSinkWired).",
@@ -76344,8 +77225,11 @@ var require_claude_hook = __commonJS({
76344
77225
  "",
76345
77226
  "CODERIFTS_STRICT=1|true: same fail-closed as default; cannot be weakened by ADVISORY.",
76346
77227
  "",
76347
- "Spec path (same source as git pre-push hook):",
76348
- " git config coderifts.specPath (default: api/openapi.yaml)",
77228
+ "Governed paths (additive; configuring one path never drops the defaults):",
77229
+ " default family: OpenAPI/Swagger, GraphQL, *.proto, AsyncAPI, MCP manifest, tool-schema.json",
77230
+ " git config --add coderifts.specPath <path-or-glob> # extra includes",
77231
+ " git config --add coderifts.specPathExclude <path-or-glob> # opt out one path",
77232
+ " Not-governed path: exit 0 and one stderr line `coderifts claude-hook: not governed: <path>`.",
76349
77233
  "",
76350
77234
  "Baseline at PreToolUse: before = current file on disk (pre-edit state \u2014 the tool has",
76351
77235
  "not written yet). after = proposed content from tool_input (Write: content; Edit/MultiEdit:",
@@ -76473,10 +77357,41 @@ var require_claude_hook = __commonJS({
76473
77357
  return readGitConfig("coderifts.apiKey", deps);
76474
77358
  }
76475
77359
  function resolveSpecPath(deps = {}) {
77360
+ const extras = readGitConfigAll("coderifts.specPath", deps);
77361
+ if (extras.length) return extras[0];
76476
77362
  const fromGit = readGitConfig("coderifts.specPath", deps);
76477
- if (fromGit) return fromGit;
77363
+ if (fromGit) return splitConfigValues(fromGit)[0] || DEFAULT_SPEC_PATH;
76478
77364
  return DEFAULT_SPEC_PATH;
76479
77365
  }
77366
+ function splitConfigValues(raw) {
77367
+ return String(raw || "").split(/[\n,]/).map((s) => s.trim()).filter(Boolean);
77368
+ }
77369
+ function readGitConfigAll(key, deps = {}) {
77370
+ if (typeof deps.readGitConfigAll === "function") {
77371
+ const v = deps.readGitConfigAll(key);
77372
+ if (Array.isArray(v)) return v.flatMap(splitConfigValues);
77373
+ return splitConfigValues(v);
77374
+ }
77375
+ const run = deps.execSync || execSync;
77376
+ const cwd = deps.cwd || process.cwd();
77377
+ try {
77378
+ const v = run(`git config --get-all ${key}`, {
77379
+ encoding: "utf8",
77380
+ cwd,
77381
+ stdio: ["ignore", "pipe", "pipe"]
77382
+ });
77383
+ return splitConfigValues(v);
77384
+ } catch {
77385
+ const one = readGitConfig(key, deps);
77386
+ return one ? splitConfigValues(one) : [];
77387
+ }
77388
+ }
77389
+ function resolveSpecIncludes(deps = {}) {
77390
+ return readGitConfigAll("coderifts.specPath", deps);
77391
+ }
77392
+ function resolveSpecExcludes(deps = {}) {
77393
+ return readGitConfigAll("coderifts.specPathExclude", deps);
77394
+ }
76480
77395
  var GOVERNED_TOOLS = /* @__PURE__ */ new Set(["write", "edit", "multiedit", "multi_edit"]);
76481
77396
  function isGovernedTool(name) {
76482
77397
  return GOVERNED_TOOLS.has(String(name || "").toLowerCase());
@@ -76551,6 +77466,75 @@ var require_claude_hook = __commonJS({
76551
77466
  }
76552
77467
  return false;
76553
77468
  }
77469
+ function globToRegExp(pattern) {
77470
+ const src = String(pattern).replace(/\\/g, "/");
77471
+ let out = "^";
77472
+ for (let i = 0; i < src.length; ) {
77473
+ if (src[i] === "*" && src[i + 1] === "*") {
77474
+ if (src[i + 2] === "/") {
77475
+ out += "(?:.*/)?";
77476
+ i += 3;
77477
+ } else {
77478
+ out += ".*";
77479
+ i += 2;
77480
+ }
77481
+ } else if (src[i] === "*") {
77482
+ out += "[^/]*";
77483
+ i += 1;
77484
+ } else if (src[i] === "?") {
77485
+ out += "[^/]";
77486
+ i += 1;
77487
+ } else {
77488
+ out += src[i].replace(/[.+^${}()|[\]\\]/g, "\\$&");
77489
+ i += 1;
77490
+ }
77491
+ }
77492
+ out += "$";
77493
+ return new RegExp(out, "i");
77494
+ }
77495
+ function matchGlob(pattern, value) {
77496
+ if (!pattern || value == null) return false;
77497
+ return globToRegExp(pattern).test(String(value).replace(/\\/g, "/"));
77498
+ }
77499
+ function normalizeToolPath(filePath, cwd) {
77500
+ let p = String(filePath || "").replace(/\\/g, "/");
77501
+ while (p.startsWith("./")) p = p.slice(2);
77502
+ const root = String(cwd || "").replace(/\\/g, "/").replace(/\/$/, "");
77503
+ if (root && (p === root || p.startsWith(`${root}/`))) {
77504
+ p = p.slice(root.length).replace(/^\//, "");
77505
+ }
77506
+ return p;
77507
+ }
77508
+ function isDetectorsExcludedDir(rel) {
77509
+ const s = `/${String(rel).replace(/\\/g, "/").toLowerCase()}/`;
77510
+ return s.includes("/node_modules/") || s.includes("/vendor/");
77511
+ }
77512
+ function patternLooksLikeGlob(pattern) {
77513
+ return /[*?]/.test(String(pattern || ""));
77514
+ }
77515
+ function matchesPattern(filePath, rel, pattern) {
77516
+ if (!pattern) return false;
77517
+ if (patternLooksLikeGlob(pattern)) {
77518
+ return matchGlob(pattern, rel) || matchGlob(pattern, filePath);
77519
+ }
77520
+ return isSpecPath(filePath, pattern) || isSpecPath(rel, pattern);
77521
+ }
77522
+ function matchesAnyPattern(filePath, rel, patterns) {
77523
+ for (const p of patterns || []) {
77524
+ if (matchesPattern(filePath, rel, p)) return true;
77525
+ }
77526
+ return false;
77527
+ }
77528
+ function isGovernedPath(filePath, deps = {}) {
77529
+ if (!filePath) return false;
77530
+ const rel = normalizeToolPath(filePath, deps.cwd);
77531
+ const extras = resolveSpecIncludes(deps);
77532
+ const excludes = resolveSpecExcludes(deps);
77533
+ if (matchesAnyPattern(filePath, rel, excludes)) return false;
77534
+ if (matchesAnyPattern(filePath, rel, extras)) return true;
77535
+ if (isDetectorsExcludedDir(rel)) return false;
77536
+ return DEFAULT_SPEC_GLOBS.some((g) => matchGlob(g, rel) || matchGlob(g, String(filePath).replace(/\\/g, "/")));
77537
+ }
76554
77538
  function deriveAfterContent(toolName, toolInput, diskBefore) {
76555
77539
  const name = String(toolName || "").toLowerCase();
76556
77540
  if (name === "write") {
@@ -76779,8 +77763,9 @@ var require_claude_hook = __commonJS({
76779
77763
  return emitTerminal({ exitCode: 2, reason: "missing_file_path" });
76780
77764
  }
76781
77765
  filePathKnown = filePath;
76782
- const specPath = resolveSpecPath({ ...deps, cwd });
76783
- if (!isSpecPath(filePath, specPath)) {
77766
+ if (!isGovernedPath(filePath, { ...deps, cwd })) {
77767
+ const rel = normalizeToolPath(filePath, cwd);
77768
+ errLog(`coderifts claude-hook: not governed: ${rel || filePath}`);
76784
77769
  logEv({ type: "detection_skip", signals: ["not_spec_path"], tool, path: filePath });
76785
77770
  return emitTerminal({ exitCode: 0, reason: "not_spec_path" });
76786
77771
  }
@@ -76961,12 +77946,18 @@ var require_claude_hook = __commonJS({
76961
77946
  isGovernedTool,
76962
77947
  coerceToolInput,
76963
77948
  isSpecPath,
77949
+ isGovernedPath,
77950
+ matchGlob,
77951
+ normalizeToolPath,
76964
77952
  deriveAfterContent,
76965
77953
  mapDecisionSeverity,
76966
77954
  renderDecisionWhy,
76967
77955
  resolveApiKey,
76968
77956
  resolveSpecPath,
77957
+ resolveSpecIncludes,
77958
+ resolveSpecExcludes,
76969
77959
  readGitConfig,
77960
+ readGitConfigAll,
76970
77961
  isEnvFlag,
76971
77962
  isStrictMode,
76972
77963
  isAdvisoryMode,
@@ -76974,6 +77965,7 @@ var require_claude_hook = __commonJS({
76974
77965
  failClosedOrAdvisory,
76975
77966
  softOrStrictBlock,
76976
77967
  DEFAULT_SPEC_PATH,
77968
+ DEFAULT_SPEC_GLOBS,
76977
77969
  CLOSED_ACTIONS,
76978
77970
  USAGE,
76979
77971
  appendGuardEventLog,
@@ -158775,7 +159767,7 @@ var require_rateLimit = __commonJS({
158775
159767
  var ipDailyStore = /* @__PURE__ */ new Map();
158776
159768
  var apiKeyMinuteStore = /* @__PURE__ */ new Map();
158777
159769
  var ipAgentMinuteStore = /* @__PURE__ */ new Map();
158778
- var AGENT_PUBLIC_ENDPOINTS = ["/api/v1/demo", "/api/v1/public/preflight", "/api/v1/public/actionguard-check", "/api/v1/public/migraguard-check", "/api/v1/badge/agent-readiness"];
159770
+ var AGENT_PUBLIC_ENDPOINTS = ["/api/v1/demo", "/api/v1/public/preflight", "/api/v1/public/actionguard-check", "/api/v1/public/migraguard-check", "/api/v1/badge/agent-readiness", "/snippets"];
158779
159771
  var AGENT_IP_MINUTE_LIMIT = 60;
158780
159772
  var ANONYMOUS_DAILY_LIMIT = 50;
158781
159773
  var API_KEY_MINUTE_LIMIT = 100;
@@ -179997,6 +180989,32 @@ var require_comment_renderer = __commonJS({
179997
180989
  lines.push("");
179998
180990
  return lines.join("\n");
179999
180991
  }
180992
+ var BREAKING_HIGHLIGHTS_TOP_N = 5;
180993
+ function renderBreakingHighlights(results, topN = BREAKING_HIGHLIGHTS_TOP_N) {
180994
+ if (!Array.isArray(results) || results.length === 0) return "";
180995
+ const rows = [];
180996
+ for (const r of results) {
180997
+ const file = r && typeof r.schemaPath === "string" ? r.schemaPath : "";
180998
+ for (const d of r && Array.isArray(r.breaking) ? r.breaking : []) {
180999
+ const raw = extractRawLocation(d);
181000
+ const pointer = raw && raw !== "N/A" ? raw : "";
181001
+ if (!file && !pointer) continue;
181002
+ rows.push({ file, pointer, code: d && d.code ? String(d.code) : "" });
181003
+ }
181004
+ }
181005
+ if (rows.length === 0) return "";
181006
+ const shown = rows.slice(0, topN);
181007
+ const lines = ["## \u{1F3AF} Breaking elements\n"];
181008
+ for (const row of shown) {
181009
+ const where = row.file && row.pointer ? `\`${escapeMd(row.file)}\` \xB7 \`${escapeMd(row.pointer)}\`` : `\`${escapeMd(row.file || row.pointer)}\``;
181010
+ lines.push(`- ${where}${row.code ? ` \u2014 \`${escapeMd(row.code)}\`` : ""}`);
181011
+ }
181012
+ if (rows.length > shown.length) {
181013
+ lines.push(`- \u2026and ${rows.length - shown.length} more \u2014 see **Raw diff details** below.`);
181014
+ }
181015
+ lines.push("");
181016
+ return lines.join("\n");
181017
+ }
180000
181018
  function renderAgentImpactHeadline(options) {
180001
181019
  const n = (options.omegaAgentPatterns || []).length;
180002
181020
  if (n === 0) return "";
@@ -180246,6 +181264,10 @@ var require_comment_renderer = __commonJS({
180246
181264
  const changeList = renderCanonicalChangeList(options.detectedPatterns || []);
180247
181265
  if (changeList) lines.push(changeList);
180248
181266
  }
181267
+ {
181268
+ const highlights = renderBreakingHighlights(results);
181269
+ if (highlights) lines.push(highlights);
181270
+ }
180249
181271
  {
180250
181272
  const agentLine = renderAgentImpactHeadline(options);
180251
181273
  if (agentLine) lines.push(agentLine);
@@ -180728,6 +181750,8 @@ ${body}` : poison;
180728
181750
  renderBlockReason,
180729
181751
  renderUnblockActions,
180730
181752
  renderCanonicalChangeList,
181753
+ renderBreakingHighlights,
181754
+ BREAKING_HIGHLIGHTS_TOP_N,
180731
181755
  renderAgentImpactHeadline,
180732
181756
  renderEconomicHeadline,
180733
181757
  renderPoisonGateSection,
@@ -201561,7 +202585,120 @@ var require_asyncapi_diff = __commonJS({
201561
202585
  channels[channelName] = { operations };
201562
202586
  }
201563
202587
  }
201564
- return { channels };
202588
+ return { channels, root: parsed };
202589
+ }
202590
+ function stillHasRef(node) {
202591
+ return !!(node && typeof node === "object" && typeof node.$ref === "string" && !node.properties);
202592
+ }
202593
+ function comparePayload(basePayload, headPayload, pathPrefix, messageId, baseRoot, headRoot, addBreakingChange, addNonBreakingChange) {
202594
+ const baseResolved = resolveLocalRef(baseRoot, basePayload, []);
202595
+ const headResolved = resolveLocalRef(headRoot, headPayload, []);
202596
+ if (stillHasRef(baseResolved) || stillHasRef(headResolved)) {
202597
+ const ref = stillHasRef(baseResolved) && baseResolved.$ref || stillHasRef(headResolved) && headResolved.$ref || "";
202598
+ addNonBreakingChange(
202599
+ "PAYLOAD_REF_UNCOMPARED",
202600
+ pathPrefix,
202601
+ `Payload at '${pathPrefix}' uses unresolved $ref '${ref}' and was not compared.`
202602
+ );
202603
+ return;
202604
+ }
202605
+ if (!baseResolved || !headResolved || typeof baseResolved !== "object" || typeof headResolved !== "object") {
202606
+ return;
202607
+ }
202608
+ const baseProps = baseResolved.properties || {};
202609
+ const headProps = headResolved.properties || {};
202610
+ const baseReq = new Set(Array.isArray(baseResolved.required) ? baseResolved.required : []);
202611
+ const headReq = new Set(Array.isArray(headResolved.required) ? headResolved.required : []);
202612
+ for (const fieldName of headReq) {
202613
+ if (baseReq.has(fieldName)) continue;
202614
+ if (baseProps[fieldName]) {
202615
+ addBreakingChange(
202616
+ "PAYLOAD_FIELD_NOW_REQUIRED",
202617
+ `${pathPrefix}.${fieldName}`,
202618
+ `Payload field '${fieldName}' in message '${messageId}' changed from optional to required.`
202619
+ );
202620
+ } else {
202621
+ addBreakingChange(
202622
+ "REQUIRED_PAYLOAD_FIELD_ADDED",
202623
+ `${pathPrefix}.${fieldName}`,
202624
+ `Required payload field '${fieldName}' was added to message '${messageId}'.`
202625
+ );
202626
+ }
202627
+ }
202628
+ for (const fieldName of baseReq) {
202629
+ if (!headReq.has(fieldName) && headProps[fieldName]) {
202630
+ addNonBreakingChange(
202631
+ "PAYLOAD_FIELD_NOW_OPTIONAL",
202632
+ `${pathPrefix}.${fieldName}`,
202633
+ `Payload field '${fieldName}' in message '${messageId}' changed from required to optional.`
202634
+ );
202635
+ }
202636
+ }
202637
+ for (const fieldName in baseProps) {
202638
+ const baseField = resolveLocalRef(baseRoot, baseProps[fieldName], []);
202639
+ const headFieldRaw = headProps[fieldName];
202640
+ if (!headFieldRaw) {
202641
+ addBreakingChange(
202642
+ "PAYLOAD_FIELD_REMOVED",
202643
+ `${pathPrefix}.${fieldName}`,
202644
+ `Payload field '${fieldName}' was removed from message '${messageId}'.`
202645
+ );
202646
+ continue;
202647
+ }
202648
+ const headField = resolveLocalRef(headRoot, headFieldRaw, []);
202649
+ if (stillHasRef(baseField) || stillHasRef(headField)) {
202650
+ const ref = stillHasRef(baseField) && baseField.$ref || stillHasRef(headField) && headField.$ref || "";
202651
+ addNonBreakingChange(
202652
+ "PAYLOAD_REF_UNCOMPARED",
202653
+ `${pathPrefix}.${fieldName}`,
202654
+ `Payload field '${fieldName}' in message '${messageId}' uses unresolved $ref '${ref}' and was not compared.`
202655
+ );
202656
+ continue;
202657
+ }
202658
+ if (baseField && headField && baseField.type !== headField.type) {
202659
+ addBreakingChange(
202660
+ "PAYLOAD_FIELD_TYPE_CHANGED",
202661
+ `${pathPrefix}.${fieldName}`,
202662
+ `Payload field '${fieldName}' in message '${messageId}' changed type from '${baseField.type}' to '${headField.type}'.`
202663
+ );
202664
+ continue;
202665
+ }
202666
+ if (baseField && headField && Array.isArray(baseField.enum) && Array.isArray(headField.enum)) {
202667
+ for (const val of baseField.enum) {
202668
+ if (!headField.enum.includes(val)) {
202669
+ addBreakingChange(
202670
+ "ENUM_VALUE_REMOVED",
202671
+ `${pathPrefix}.${fieldName}.${val}`,
202672
+ `Enum value '${val}' was removed from field '${fieldName}' in message '${messageId}'.`
202673
+ );
202674
+ }
202675
+ }
202676
+ for (const val of headField.enum) {
202677
+ if (!baseField.enum.includes(val)) {
202678
+ addNonBreakingChange(
202679
+ "ENUM_VALUE_ADDED",
202680
+ `${pathPrefix}.${fieldName}.${val}`,
202681
+ `New enum value '${val}' was added to field '${fieldName}' in message '${messageId}'.`
202682
+ );
202683
+ }
202684
+ }
202685
+ }
202686
+ if (baseField && headField && (baseField.properties || headField.properties || baseField.type === "object" || headField.type === "object")) {
202687
+ comparePayload(baseField, headField, `${pathPrefix}.${fieldName}`, messageId, baseRoot, headRoot, addBreakingChange, addNonBreakingChange);
202688
+ }
202689
+ }
202690
+ for (const fieldName in headProps) {
202691
+ if (!baseProps[fieldName]) {
202692
+ const addedIsRequired = headReq.has(fieldName);
202693
+ if (!addedIsRequired) {
202694
+ addNonBreakingChange(
202695
+ "PAYLOAD_FIELD_ADDED",
202696
+ `${pathPrefix}.${fieldName}`,
202697
+ `New optional payload field '${fieldName}' was added to message '${messageId}'.`
202698
+ );
202699
+ }
202700
+ }
202701
+ }
201565
202702
  }
201566
202703
  function diffAsyncAPISchemas(base_schema_content, head_schema_content) {
201567
202704
  const base = parseAsyncAPI(base_schema_content);
@@ -201601,42 +202738,17 @@ var require_asyncapi_diff = __commonJS({
201601
202738
  }
201602
202739
  const basePayload = baseMessage.payload;
201603
202740
  const headPayload = headMessage.payload;
201604
- if (basePayload && headPayload && basePayload.properties && headPayload.properties) {
201605
- for (const fieldName in basePayload.properties) {
201606
- const baseField = basePayload.properties[fieldName];
201607
- const headField = headPayload.properties[fieldName];
201608
- if (!headField) {
201609
- addBreakingChange("PAYLOAD_FIELD_REMOVED", `${channelName}.${opType}.${messageId}.${fieldName}`, `Payload field '${fieldName}' was removed from message '${messageId}'.`);
201610
- } else if (baseField.type !== headField.type) {
201611
- addBreakingChange("PAYLOAD_FIELD_TYPE_CHANGED", `${channelName}.${opType}.${messageId}.${fieldName}`, `Payload field '${fieldName}' in message '${messageId}' changed type from '${baseField.type}' to '${headField.type}'.`);
201612
- } else if (Array.isArray(baseField.enum) && Array.isArray(headField.enum)) {
201613
- for (const val of baseField.enum) {
201614
- if (!headField.enum.includes(val)) {
201615
- addBreakingChange("ENUM_VALUE_REMOVED", `${channelName}.${opType}.${messageId}.${fieldName}.${val}`, `Enum value '${val}' was removed from field '${fieldName}' in message '${messageId}'.`);
201616
- }
201617
- }
201618
- for (const val of headField.enum) {
201619
- if (!baseField.enum.includes(val)) {
201620
- addNonBreakingChange("ENUM_VALUE_ADDED", `${channelName}.${opType}.${messageId}.${fieldName}.${val}`, `New enum value '${val}' was added to field '${fieldName}' in message '${messageId}'.`);
201621
- }
201622
- }
201623
- }
201624
- }
201625
- for (const fieldName in headPayload.properties) {
201626
- if (!basePayload.properties[fieldName]) {
201627
- const addedIsRequired = Array.isArray(headPayload.required) && headPayload.required.includes(fieldName);
201628
- if (!addedIsRequired) {
201629
- addNonBreakingChange("PAYLOAD_FIELD_ADDED", `${channelName}.${opType}.${messageId}.${fieldName}`, `New optional payload field '${fieldName}' was added to message '${messageId}'.`);
201630
- }
201631
- }
201632
- }
201633
- if (headPayload.required && Array.isArray(headPayload.required)) {
201634
- for (const requiredField of headPayload.required) {
201635
- if (!basePayload.required || !basePayload.required.includes(requiredField)) {
201636
- addBreakingChange("REQUIRED_PAYLOAD_FIELD_ADDED", `${channelName}.${opType}.${messageId}.${requiredField}`, `Required payload field '${requiredField}' was added to message '${messageId}'.`);
201637
- }
201638
- }
201639
- }
202741
+ if (basePayload && headPayload) {
202742
+ comparePayload(
202743
+ basePayload,
202744
+ headPayload,
202745
+ `${channelName}.${opType}.${messageId}`,
202746
+ messageId,
202747
+ base.root,
202748
+ head.root,
202749
+ addBreakingChange,
202750
+ addNonBreakingChange
202751
+ );
201640
202752
  }
201641
202753
  }
201642
202754
  for (const messageId in headOperation.messages) {
@@ -202399,6 +203511,83 @@ var require_remediation_taxonomy = __commonJS({
202399
203511
  }
202400
203512
  });
202401
203513
 
203514
+ // ../../src/next-agent-step.js
203515
+ var require_next_agent_step2 = __commonJS({
203516
+ "../../src/next-agent-step.js"(exports2, module2) {
203517
+ "use strict";
203518
+ var NEXT_AGENT_ACTIONS = Object.freeze([
203519
+ "re_preflight",
203520
+ "revert",
203521
+ "migrate",
203522
+ "escalate",
203523
+ "await_approval"
203524
+ ]);
203525
+ var NEXT_AGENT_ACTION_SET = new Set(NEXT_AGENT_ACTIONS);
203526
+ function mapChoiceIdToNextAction(id) {
203527
+ const s = String(id == null ? "" : id);
203528
+ if (s === "re_preflight" || s === "re_preflight_deploy") return "re_preflight";
203529
+ if (s === "fix_input") return "re_preflight";
203530
+ if (s === "revert") return "revert";
203531
+ if (s === "migrate") return "migrate";
203532
+ if (s === "escalate") return "escalate";
203533
+ if (s === "obtain_human_approval") return "await_approval";
203534
+ return null;
203535
+ }
203536
+ function projectNextAgentStep(executionAction, requiredAction) {
203537
+ const ea = executionAction != null ? String(executionAction) : "";
203538
+ if (ea === "CONTINUE" || ea === "CONTINUE_WITH_MONITORING") return null;
203539
+ if (ea !== "STOP" && ea !== "REQUEST_APPROVAL") return null;
203540
+ const raObj = requiredAction && typeof requiredAction === "object" ? requiredAction : null;
203541
+ const raStr = typeof requiredAction === "string" ? requiredAction : null;
203542
+ const reason = raObj && raObj.reason_code != null && String(raObj.reason_code) || raObj && raObj.type != null && String(raObj.type) || raStr && raStr.slice(0, 200) || (ea === "REQUEST_APPROVAL" ? "request_approval" : "remediate_or_revert");
203543
+ const resume_condition = raObj && typeof raObj.resume_condition === "string" ? raObj.resume_condition : raStr || "";
203544
+ let action = null;
203545
+ if (ea === "REQUEST_APPROVAL") {
203546
+ action = "await_approval";
203547
+ } else {
203548
+ const choices = raObj && Array.isArray(raObj.choices) ? raObj.choices : [];
203549
+ for (const c of choices) {
203550
+ const id = typeof c === "string" ? c : c && c.id != null ? c.id : null;
203551
+ const mapped = mapChoiceIdToNextAction(id);
203552
+ if (mapped && NEXT_AGENT_ACTION_SET.has(mapped) && mapped !== "await_approval") {
203553
+ action = mapped;
203554
+ break;
203555
+ }
203556
+ }
203557
+ if (!action) {
203558
+ const t = raObj && raObj.type != null ? String(raObj.type) : "";
203559
+ if (t === "re_preflight" || t === "remediate_or_revert" || t === "fix_coverage" || t === "revert") {
203560
+ action = t === "revert" ? "revert" : "re_preflight";
203561
+ } else if (raStr || ea === "STOP") {
203562
+ action = "re_preflight";
203563
+ }
203564
+ }
203565
+ }
203566
+ if (!action || !NEXT_AGENT_ACTION_SET.has(action)) return null;
203567
+ let then_call = null;
203568
+ if (action === "re_preflight" || action === "revert" || action === "migrate") {
203569
+ then_call = "preflight_change_set";
203570
+ } else if (action === "await_approval") {
203571
+ then_call = null;
203572
+ } else if (action === "escalate") {
203573
+ then_call = null;
203574
+ }
203575
+ return {
203576
+ action,
203577
+ reason: String(reason),
203578
+ resume_condition: String(resume_condition),
203579
+ then_call
203580
+ };
203581
+ }
203582
+ module2.exports = {
203583
+ NEXT_AGENT_ACTIONS,
203584
+ NEXT_AGENT_ACTION_SET,
203585
+ mapChoiceIdToNextAction,
203586
+ projectNextAgentStep
203587
+ };
203588
+ }
203589
+ });
203590
+
202402
203591
  // ../../src/response-envelope.js
202403
203592
  var require_response_envelope = __commonJS({
202404
203593
  "../../src/response-envelope.js"(exports2, module2) {
@@ -202642,70 +203831,10 @@ var require_response_envelope = __commonJS({
202642
203831
  function buildEnforcementDescriptor() {
202643
203832
  return { ...ENFORCEMENT_DESCRIPTOR };
202644
203833
  }
202645
- var NEXT_AGENT_ACTIONS = Object.freeze([
202646
- "re_preflight",
202647
- "revert",
202648
- "migrate",
202649
- "escalate",
202650
- "await_approval"
202651
- ]);
202652
- var NEXT_AGENT_ACTION_SET = new Set(NEXT_AGENT_ACTIONS);
202653
- function mapChoiceIdToNextAction(id) {
202654
- const s = String(id == null ? "" : id);
202655
- if (s === "re_preflight" || s === "re_preflight_deploy") return "re_preflight";
202656
- if (s === "fix_input") return "re_preflight";
202657
- if (s === "revert") return "revert";
202658
- if (s === "migrate") return "migrate";
202659
- if (s === "escalate") return "escalate";
202660
- if (s === "obtain_human_approval") return "await_approval";
202661
- return null;
202662
- }
202663
- function projectNextAgentStep(executionAction, requiredAction) {
202664
- const ea = executionAction != null ? String(executionAction) : "";
202665
- if (ea === "CONTINUE" || ea === "CONTINUE_WITH_MONITORING") return null;
202666
- if (ea !== "STOP" && ea !== "REQUEST_APPROVAL") return null;
202667
- const raObj = requiredAction && typeof requiredAction === "object" ? requiredAction : null;
202668
- const raStr = typeof requiredAction === "string" ? requiredAction : null;
202669
- const reason = raObj && raObj.reason_code != null && String(raObj.reason_code) || raObj && raObj.type != null && String(raObj.type) || raStr && raStr.slice(0, 200) || (ea === "REQUEST_APPROVAL" ? "request_approval" : "remediate_or_revert");
202670
- const resume_condition = raObj && typeof raObj.resume_condition === "string" ? raObj.resume_condition : raStr || "";
202671
- let action = null;
202672
- if (ea === "REQUEST_APPROVAL") {
202673
- action = "await_approval";
202674
- } else {
202675
- const choices = raObj && Array.isArray(raObj.choices) ? raObj.choices : [];
202676
- for (const c of choices) {
202677
- const id = typeof c === "string" ? c : c && c.id != null ? c.id : null;
202678
- const mapped = mapChoiceIdToNextAction(id);
202679
- if (mapped && NEXT_AGENT_ACTION_SET.has(mapped) && mapped !== "await_approval") {
202680
- action = mapped;
202681
- break;
202682
- }
202683
- }
202684
- if (!action) {
202685
- const t = raObj && raObj.type != null ? String(raObj.type) : "";
202686
- if (t === "re_preflight" || t === "remediate_or_revert" || t === "fix_coverage" || t === "revert") {
202687
- action = t === "revert" ? "revert" : "re_preflight";
202688
- } else if (raStr || ea === "STOP") {
202689
- action = "re_preflight";
202690
- }
202691
- }
202692
- }
202693
- if (!action || !NEXT_AGENT_ACTION_SET.has(action)) return null;
202694
- let then_call = null;
202695
- if (action === "re_preflight" || action === "revert" || action === "migrate") {
202696
- then_call = "preflight_change_set";
202697
- } else if (action === "await_approval") {
202698
- then_call = null;
202699
- } else if (action === "escalate") {
202700
- then_call = null;
202701
- }
202702
- return {
202703
- action,
202704
- reason: String(reason),
202705
- resume_condition: String(resume_condition),
202706
- then_call
202707
- };
202708
- }
203834
+ var {
203835
+ NEXT_AGENT_ACTIONS,
203836
+ projectNextAgentStep
203837
+ } = require_next_agent_step2();
202709
203838
  function buildControlEnvelope(verdict, authzContext) {
202710
203839
  const receipt_view = projectReceipt(verdict, authzContext);
202711
203840
  let safeForAgent = verdict.safe_for_agent;
@@ -202829,6 +203958,7 @@ var require_response_envelope = __commonJS({
202829
203958
  return response;
202830
203959
  }
202831
203960
  response.control_envelope = buildControlEnvelope(response, authzContext);
203961
+ if (isCoverageFailClosed(response)) response.safe_for_agent = false;
202832
203962
  response.analysis = buildAnalysisTier(response);
202833
203963
  try {
202834
203964
  response.analysis.remediations = buildRemediations(response);
@@ -204396,6 +205526,48 @@ var require_decision_result_v1_producer = __commonJS({
204396
205526
  }
204397
205527
  }
204398
205528
  },
205529
+ next_agent_step: {
205530
+ type: [
205531
+ "object",
205532
+ "null"
205533
+ ],
205534
+ additionalProperties: false,
205535
+ required: [
205536
+ "action",
205537
+ "reason",
205538
+ "resume_condition",
205539
+ "then_call"
205540
+ ],
205541
+ description: "Additive (I-1288). The decision's own remediation SUGGESTION, projected at issuance from execution_action + required_action_core \u2014 the identical pure function that fills control_envelope.next_agent_step (src/next-agent-step.js). One projection, two placements, never two rules. INSIDE the envelope it is covered by decision_body_hash, so the signed receipt covers the suggestion along with the decision that produced it: a consumer handed only the envelope (k8s-admission, gateway-verifier, agent-guard deployGate) can render the next step without a second call to the issuer, and a tampered step no longer verifies. NOT PERMISSION and NOT a control-flow override \u2014 branch on execution_action. null on the allow class (CONTINUE / CONTINUE_WITH_MONITORING) is the correct value, not a missing measurement; null also on legacy non-additive envelopes, which never carry the field.",
205542
+ properties: {
205543
+ action: {
205544
+ type: "string",
205545
+ enum: [
205546
+ "re_preflight",
205547
+ "revert",
205548
+ "migrate",
205549
+ "escalate",
205550
+ "await_approval"
205551
+ ],
205552
+ description: "Closed set \u2014 src/next-agent-step.js NEXT_AGENT_ACTIONS."
205553
+ },
205554
+ reason: {
205555
+ type: "string",
205556
+ description: "required_action reason_code / type, or the display string when that is all the issuance path had."
205557
+ },
205558
+ resume_condition: {
205559
+ type: "string",
205560
+ description: "What must hold before the caller retries. Projected from the FROZEN required_action_core, which carries no receipt-authz overlay, so this is the one subfield that may be thinner than control_envelope.next_agent_step.resume_condition (the live surface projects from deriveRequiredAction, which has the overlay and can name the approval receipt it wants). Signing the overlay text would sign a fact the envelope deliberately excludes. Empty string when the frozen core supplied none \u2014 not an error."
205561
+ },
205562
+ then_call: {
205563
+ type: [
205564
+ "string",
205565
+ "null"
205566
+ ],
205567
+ description: "Tool to call after the step, or null when the next move is a human one."
205568
+ }
205569
+ }
205570
+ },
204399
205571
  remediation_transaction: {
204400
205572
  type: [
204401
205573
  "object",
@@ -205090,6 +206262,174 @@ var require_decision_result_validator = __commonJS({
205090
206262
  }
205091
206263
  });
205092
206264
 
206265
+ // ../../schemas/execution-grant-request.v2.producer.json
206266
+ var require_execution_grant_request_v2_producer = __commonJS({
206267
+ "../../schemas/execution-grant-request.v2.producer.json"(exports2, module2) {
206268
+ module2.exports = {
206269
+ $schema: "https://json-schema.org/draft/2020-12/schema",
206270
+ $id: "https://coderifts.com/schemas/execution-grant-request.v2.producer.json",
206271
+ title: "CodeRifts Execution Grant Request v2 \u2014 PRODUCER schema",
206272
+ description: "Execution-grant REQUEST v2 \u2014 the fields the authorize handler actually reads when minting a cr.exec.v2 grant. Measured from src/change-set.js:1209-1285 (the wantGrant/wantV2 block) plus the operation / audience / environment reads that same handler already performs, and pinned field-by-field by test/fixtures/v2-grant-field-matrix.json. PRODUCER-ONLY, DELIBERATELY. The pairing convention in schemas/ is not universal: decision-result.v1 and preflight-response.v2 have consumer twins because a GENERATOR derives one from the other (scripts/generate-consumer-schema.js), while control-envelope.v1 and verify-receipt.v1 are producer-only. No generator derives a request consumer, and the only thing a consumer twin would say differently is `additionalProperties`, which is stated here directly. A second hand-maintained file whose sole difference is one keyword is a drift risk, not a contract. ROLES ARE INVERTED relative to the response schemas: on a REQUEST the CLIENT is the producer and the SERVER is the consumer. `additionalProperties` is therefore TRUE, and that is a measurement of current behaviour, not an aspiration \u2014 the handler reads named fields off `input` and ignores everything else, so a client sending an extra key is accepted today. Validation is advisory by default (EXECUTION_GRANT_REQUEST_VALIDATOR_MODE=log); nothing in this schema starts rejecting a request that works now. NOT REQUEST FIELDS \u2014 MINTED BY THE ISSUER, and excluded on purpose: `jti`, `expires_at` / `expiry`, `after_payload_digest` (plus `kid`, `grant_id`, `receipt_hash`, `nonce_hash`, `not_before`, `max_attempts`). src/verdict-core/execution-grant-v2.js:110-154 derives every one of them from the signed receipt and the change set. A caller cannot supply them and the handler would not read them; listing them here would describe a request surface that does not exist. BOUND SINCE 1206 VARIANT A \u2014 `policy_hash` and `audience_hash`: both are now carried into the signed grant. `policy_hash` is forwarded by the authorize handler (src/change-set.js:1323) into the issuer, which binds it at src/verdict-core/execution-grant-v2.js:149; a verifier that states `intended.policy_hash` gets a GRANT_UNBOUND/policy_mismatch on a mismatch. `audience_hash` is NOT a request field of its own: it is derived from `audience` (execution-grant-v2.js:150) and was already enforced (:227-234), so sending it separately has no effect and it stays out of this schema. Before this change policy_hash was accepted on the wire and dropped at the handler, which minted every grant under the sha256('') default \u2014 a field that looked bound and was not.",
206273
+ type: "object",
206274
+ additionalProperties: true,
206275
+ required: [
206276
+ "include_execution_grant"
206277
+ ],
206278
+ properties: {
206279
+ include_execution_grant: {
206280
+ type: "boolean",
206281
+ description: 'Gates the whole grant path. src/change-set.js:1209 \u2014 strictly `=== true`, so any other value (including the string "true") mints no grant.'
206282
+ },
206283
+ grant_version: {
206284
+ type: "string",
206285
+ enum: [
206286
+ "v1",
206287
+ "v2"
206288
+ ],
206289
+ description: "src/change-set.js:1268 \u2014 `v2` selects the cr.exec.v2 issuer. Absent or any other value takes the v1 branch. `grantVersion` (camelCase) is accepted as an alias at the same line; both are listed so neither reads as undeclared."
206290
+ },
206291
+ grantVersion: {
206292
+ type: "string",
206293
+ enum: [
206294
+ "v1",
206295
+ "v2"
206296
+ ],
206297
+ description: "camelCase alias of grant_version, read at src/change-set.js:1268. Declared because the handler reads it, not because it is recommended."
206298
+ },
206299
+ tenant_id: {
206300
+ type: "string",
206301
+ minLength: 1,
206302
+ description: "src/change-set.js:1279 \u2014 `input.tenant_id || context.tenant_id || 'default'`. The default is a real value, not an absence: an unset tenant is issued as `default`, it is not left unbound."
206303
+ },
206304
+ executor_id: {
206305
+ type: "string",
206306
+ minLength: 1,
206307
+ description: "src/change-set.js:1277 \u2014 `input.executor_id || context.executor_id || 'local'`."
206308
+ },
206309
+ adapter_id: {
206310
+ type: "string",
206311
+ minLength: 1,
206312
+ description: "src/change-set.js:1278 \u2014 `input.adapter_id || context.adapter_id || 'fs'`."
206313
+ },
206314
+ target_uri: {
206315
+ type: "string",
206316
+ minLength: 1,
206317
+ description: "src/change-set.js:1276 \u2014 `input.target_uri || context.target_uri`, else a derived `git://{context.repository||'local/repo'}@{context.head_sha||'unknown'}`. The derived form is a fallback, not a binding the caller asked for."
206318
+ },
206319
+ state_nonce: {
206320
+ type: "string",
206321
+ minLength: 1,
206322
+ description: "src/change-set.js:1265-1267 \u2014 non-empty string only; anything else becomes null and the grant is issued without a nonce."
206323
+ },
206324
+ expected_state_token: {
206325
+ type: "string",
206326
+ description: "src/change-set.js:1281 \u2014 `nonEmptyStr(input.expected_state_token) || ''`. Empty string is the issued value when absent; there is no unbound state."
206327
+ },
206328
+ audience: {
206329
+ type: "string",
206330
+ pattern: "^v:[0-9a-f]{12}$",
206331
+ description: "src/change-set.js:1120-1124 \u2014 ONLY the measured `v:<12 hex>` form is accepted; any other string is discarded to null rather than trusted as identity. A free-form caller-supplied name is never an audience."
206332
+ },
206333
+ policy_hash: {
206334
+ type: "string",
206335
+ minLength: 1,
206336
+ description: "src/change-set.js:1305 \u2014 the policy identity this request is made under, bound into the signed grant (execution-grant-v2.js:149). A value already prefixed `sha256:` is carried through; anything else is hashed. Absent \u2192 the issuer's sha256('') default, which is what every grant carried before 1206 variant A. Enforced only by a verifier that states intended.policy_hash \u2014 binding is not by itself a check."
206337
+ },
206338
+ context: {
206339
+ type: "object",
206340
+ additionalProperties: true,
206341
+ description: "The request context object (src/change-set.js:806). Only the keys the grant path reads are declared; the handler reads many others for unrelated purposes and tolerates the rest, so additionalProperties stays true here for the same reason it does at the root.",
206342
+ properties: {
206343
+ operation: {
206344
+ type: "string",
206345
+ minLength: 1,
206346
+ description: "src/change-set.js:807-812 \u2014 REQUIRED for preflight_mode=authorize; the handler throws a typed input error without one. Authorization asks permission for a named operation."
206347
+ },
206348
+ environment: {
206349
+ type: "string",
206350
+ description: "src/change-set.js:1159 \u2014 carried onto the envelope. Not a grant field; read by the same handler on the same request."
206351
+ },
206352
+ target_id: {
206353
+ type: "string",
206354
+ description: "src/change-set.js:1264 \u2014 v1 grant target fallback; the v2 branch uses target_uri instead."
206355
+ },
206356
+ target_uri: {
206357
+ type: "string",
206358
+ description: "src/change-set.js:1276 \u2014 fallback when input.target_uri is absent."
206359
+ },
206360
+ executor_id: {
206361
+ type: "string",
206362
+ description: "src/change-set.js:1277 \u2014 fallback when input.executor_id is absent."
206363
+ },
206364
+ adapter_id: {
206365
+ type: "string",
206366
+ description: "src/change-set.js:1278 \u2014 fallback when input.adapter_id is absent."
206367
+ },
206368
+ tenant_id: {
206369
+ type: "string",
206370
+ description: "src/change-set.js:1279 \u2014 fallback when input.tenant_id is absent."
206371
+ },
206372
+ repository: {
206373
+ type: "string",
206374
+ description: "src/change-set.js:1276 \u2014 feeds the DERIVED target_uri when no explicit one was supplied."
206375
+ },
206376
+ head_sha: {
206377
+ type: "string",
206378
+ description: "src/change-set.js:1276 \u2014 feeds the DERIVED target_uri when no explicit one was supplied."
206379
+ }
206380
+ }
206381
+ }
206382
+ },
206383
+ $comment: "Field set pinned by test/fixtures/v2-grant-field-matrix.json (schema column) and test/execution-grant-request-schema.test.js. Adding a property here without adding the matching matrix cell fails the drift gate."
206384
+ };
206385
+ }
206386
+ });
206387
+
206388
+ // ../../src/execution-grant-request-validator.js
206389
+ var require_execution_grant_request_validator = __commonJS({
206390
+ "../../src/execution-grant-request-validator.js"(exports2, module2) {
206391
+ "use strict";
206392
+ var Ajv2020 = require__();
206393
+ var requestSchema = require_execution_grant_request_v2_producer();
206394
+ var ajv = new Ajv2020({ strict: false, allErrors: true });
206395
+ var _validate = ajv.compile(requestSchema);
206396
+ function isV2GrantRequest(input) {
206397
+ if (!input || typeof input !== "object") return false;
206398
+ if (input.include_execution_grant !== true) return false;
206399
+ return input.grant_version === "v2" || input.grantVersion === "v2";
206400
+ }
206401
+ function validateExecutionGrantRequest(input) {
206402
+ const valid = _validate(input);
206403
+ return { valid: !!valid, errors: valid ? [] : _validate.errors || [] };
206404
+ }
206405
+ function validatorMode() {
206406
+ return process.env.EXECUTION_GRANT_REQUEST_VALIDATOR_MODE === "enforce" ? "enforce" : "log";
206407
+ }
206408
+ function guardExecutionGrantRequest(input, { logger } = {}) {
206409
+ if (!isV2GrantRequest(input)) return { ok: true, skipped: true };
206410
+ const { valid, errors } = validateExecutionGrantRequest(input);
206411
+ if (valid) return { ok: true };
206412
+ const error = { code: "GRANT_REQUEST_SCHEMA_VALIDATION_FAILED", errors };
206413
+ if (validatorMode() === "enforce") {
206414
+ return { ok: false, error };
206415
+ }
206416
+ if (logger && typeof logger.warn === "function") {
206417
+ logger.warn(
206418
+ { severity: "MEDIUM", event: "execution_grant_request_schema_violation", errors },
206419
+ "v2 execution-grant request failed producer-schema validation (log mode \u2014 the request proceeds unchanged)"
206420
+ );
206421
+ }
206422
+ return { ok: true };
206423
+ }
206424
+ module2.exports = {
206425
+ validateExecutionGrantRequest,
206426
+ guardExecutionGrantRequest,
206427
+ isV2GrantRequest,
206428
+ validatorMode
206429
+ };
206430
+ }
206431
+ });
206432
+
205093
206433
  // ../../src/source-binding-gate.js
205094
206434
  var require_source_binding_gate = __commonJS({
205095
206435
  "../../src/source-binding-gate.js"(exports2, module2) {
@@ -206092,6 +207432,13 @@ var require_execution_grant_v2 = __commonJS({
206092
207432
  if (intended.audience_hash != null && String(intended.audience_hash).length > 0 && payload.audience_hash !== String(intended.audience_hash)) {
206093
207433
  return { valid: false, status: "GRANT_UNBOUND", reason: "audience_mismatch", payload };
206094
207434
  }
207435
+ if (intended.policy_hash != null && String(intended.policy_hash).length > 0) {
207436
+ const wantPolicy = String(intended.policy_hash);
207437
+ const norm = wantPolicy.startsWith("sha256:") ? wantPolicy : sha256pref(wantPolicy);
207438
+ if (payload.policy_hash !== norm) {
207439
+ return { valid: false, status: "GRANT_UNBOUND", reason: "policy_mismatch", payload };
207440
+ }
207441
+ }
206095
207442
  if (intended.after_payload != null) {
206096
207443
  if (payload.after_payload_hash !== sha256pref(intended.after_payload)) {
206097
207444
  return { valid: false, status: "GRANT_UNBOUND", reason: "after_payload_mismatch", payload };
@@ -206528,6 +207875,7 @@ var require_change_set = __commonJS({
206528
207875
  var { buildDecisionResultV1 } = require_decision_result();
206529
207876
  var { deriveRequiredAction } = require_response_envelope();
206530
207877
  var { guardDecisionResult } = require_decision_result_validator();
207878
+ var { guardExecutionGrantRequest } = require_execution_grant_request_validator();
206531
207879
  var { issueReceipt, isConfigured, sha256hex } = require_chain_attestation();
206532
207880
  var { getPatternConfigHash } = require_omega_scoring();
206533
207881
  var { computeBlastRadiusCounts } = require_blast_radius_counts();
@@ -207399,6 +208747,16 @@ var require_change_set = __commonJS({
207399
208747
  }
207400
208748
  const authorizeAction = preflightMode === "authorize" ? deriveExecutionAction(core.decision) : null;
207401
208749
  const allowClass = authorizeAction === "CONTINUE" || authorizeAction === "CONTINUE_WITH_MONITORING";
208750
+ if (preflightMode === "authorize" && wantGrant) {
208751
+ const reqGuard = guardExecutionGrantRequest(input, { logger });
208752
+ if (!reqGuard.ok) {
208753
+ throw typedError(
208754
+ reqGuard.error.code,
208755
+ "execution-grant request failed producer-schema validation",
208756
+ { errors: reqGuard.error.errors }
208757
+ );
208758
+ }
208759
+ }
207402
208760
  if (preflightMode === "authorize" && wantGrant && allowClass && typeof receipt === "string" && receipt.length > 0) {
207403
208761
  try {
207404
208762
  const {
@@ -207420,7 +208778,25 @@ var require_change_set = __commonJS({
207420
208778
  adapter_id: nonEmptyStr(input.adapter_id) || nonEmptyStr(context.adapter_id) || "fs",
207421
208779
  tenant_id: nonEmptyStr(input.tenant_id) || nonEmptyStr(context.tenant_id) || "default",
207422
208780
  nonce: stateNonce,
207423
- expected_state_token: nonEmptyStr(input.expected_state_token) || ""
208781
+ expected_state_token: nonEmptyStr(input.expected_state_token) || "",
208782
+ // 1206 variant A — the caller's claimed policy identity, BOUND into the signed grant.
208783
+ //
208784
+ // It was the one v2 field a client could send and the server would drop: the issuer
208785
+ // has always read args.policy_hash (verdict-core/execution-grant-v2.js:132) and the
208786
+ // wire has always carried a policy_hash slot, but this handler never forwarded it, so
208787
+ // every grant was minted with the sha256('') default. A field that looks bound and is
208788
+ // not is worse than an absent one — a reader of the token cannot tell the difference.
208789
+ //
208790
+ // AUDIENCE NEEDS NO LINE HERE: `audience` is already passed at the top of this call
208791
+ // and the issuer derives audience_hash from it (:150), which the verifier already
208792
+ // enforces (:227-234). Only policy_hash was missing.
208793
+ //
208794
+ // This binds what the CALLER CLAIMS, which is the whole point: the grant becomes
208795
+ // tamper-evident about the policy it was issued under, and a verifier that knows which
208796
+ // policy it expects can refuse a mismatch (intended.policy_hash, added symmetrically
208797
+ // to the existing intended.audience_hash check). Absent → the issuer's sha256('')
208798
+ // default, exactly as before.
208799
+ policy_hash: nonEmptyStr(input.policy_hash) || void 0
207424
208800
  } : {
207425
208801
  target_id: grantTarget,
207426
208802
  ...stateNonce ? { state_nonce: stateNonce } : {}
@@ -220480,6 +221856,15 @@ var require_persist_decision = __commonJS({
220480
221856
  return null;
220481
221857
  }
220482
221858
  }
221859
+ function persistMeta(decisionId) {
221860
+ if (typeof decisionId === "string" && decisionId.length > 0) {
221861
+ return { stored: true };
221862
+ }
221863
+ return {
221864
+ stored: false,
221865
+ reason: persistenceEnabled() ? "storage_unavailable" : "persistence_disabled"
221866
+ };
221867
+ }
220483
221868
  var AFTER_HEX_RE = /^[0-9a-f]{64}$/;
220484
221869
  function normalizeAfterHex(raw) {
220485
221870
  if (raw == null) return "";
@@ -220862,6 +222247,8 @@ var require_persist_decision = __commonJS({
220862
222247
  }
220863
222248
  module2.exports = {
220864
222249
  persistDecision,
222250
+ persistMeta,
222251
+ persistenceEnabled,
220865
222252
  persistAuthorizedPaths,
220866
222253
  findDecisionsByAfterHash,
220867
222254
  getAuthorizedPathsCollectingSince,
@@ -223317,82 +224704,7 @@ var require_mcp_streamable = __commonJS({
223317
224704
  });
223318
224705
  next();
223319
224706
  });
223320
- var DESC_PREFLIGHT_CHANGE_SET = `Preflight a COMPLETE base\u2192head change set of contract artifacts and return
223321
- risk score and breaking-change analysis \u2014 plus, on the AUTHORIZE path only, a governance decision
223322
- (ALLOW / WARN / REQUIRE_APPROVAL / BLOCK) and a signed chain-receipt when applicable. ANALYZE
223323
- returns informational risk only: analysis_outcome, may_execute:false, no decision, no receipt.
223324
-
223325
- Requires a pending base\u2192head (before/after) contract change you are about to
223326
- act on (merge, deploy, publish, or register tools). No pending change set \u2192
223327
- do not call this tool.
223328
-
223329
- Use this when:
223330
- - You are about to merge, push, deploy, publish, or register/expose agent tools,
223331
- AND the change includes \u22651 contract artifact (OpenAPI/Swagger, GraphQL SDL,
223332
- gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas: type=agent_tools,
223333
- including before re-registering tools with a runtime).
223334
- - You have (or can assemble) FULL base and head for every changed contract
223335
- artifact in this set \u2014 not a single-file subset when other contract files also
223336
- change.
223337
- - You need a NEW decision for the CURRENT change; you do not already hold a
223338
- currently-valid receipt for this exact target/operation.
223339
- - You hold a receipt for a different operation or target than the act you will
223340
- perform (e.g. ALLOW for merge, now deploying). A receipt authorizes ONE
223341
- operation: a merge receipt does not authorize a deploy. Run a NEW preflight
223342
- with context.operation set to that operation (deploy, publish); a
223343
- differently-scoped receipt is not reusable authorization and will fail at
223344
- the gate.
223345
-
223346
- Do not use when:
223347
- - The change is documentation-only (README, guides, comments) with no contract
223348
- artifact content change \u2014 do not call any CodeRifts tool.
223349
- - You already hold a signed receipt and only need to check it is authentic and
223350
- currently valid \u2014 use coderifts.verify_receipt instead.
223351
- - You need details of a PREVIOUS decision by decision_id \u2014 use
223352
- coderifts.get_decision_details instead.
223353
- - You want a static 0\u2013100 "agent readiness" score for one OpenAPI/MCP file and
223354
- there is no pending base\u2192head mutate \u2014 use coderifts.agent_readiness_score
223355
- (advanced / opt-in; not one of the three default tools). If that tool is not
223356
- in your available list, call none of the CodeRifts tools; do not substitute
223357
- preflight_change_set.
223358
- - You cannot supply both before and after (or base and head) for the artifacts
223359
- that change \u2014 fix the change set first; do not invent empty before specs.
223360
-
223361
- Inputs: list of artifacts, each with type, before, after (or equivalent), plus
223362
- optional operation (merge|deploy|tool_call|publish), environment/stakes, and
223363
- context. Opt-in derivation:"server" (proven tenant\u2194repo binding + context.repository
223364
- + base + head): omit artifacts[] \u2014 the server lists the contract-class set via the
223365
- SCM provider for the proven binding (GitHub App Compare, or GitLab/Bitbucket Compare
223366
- with a per-request X-Coderifts-Scm-Token, never stored; completeness_mode
223367
- SERVER_DERIVED). Default (flag absent) is unchanged. Returns decision,
223368
- execution_action, risk fields, and chain_receipt when issued.
223369
-
223370
- CHANGE SOURCE \u2014 EXACTLY ONE, ENFORCED AT THE ROUTE (400), NOT BY THIS SCHEMA.
223371
- Supply either artifacts[] OR derivation:"server". All three of these are rejected
223372
- with HTTP 400 INVALID_INPUT, on analyze and on authorize alike:
223373
- \u2022 neither artifacts[] nor derivation \u2192 "artifacts must be a non-empty array"
223374
- \u2022 authorize with context.operation but no change source \u2192 same 400
223375
- \u2022 artifacts[] together with derivation:"server" \u2192 "derivation:"server" forbids
223376
- caller-supplied artifacts[] \u2014 one source of truth per request"
223377
- This constraint is NOT expressible in the schema you are reading: a top-level
223378
- oneOf/allOf union is rejected by at least one major MCP client (measured), so the
223379
- schema stays permissive and the route is the enforcement point. Do not read schema
223380
- acceptance as request validity \u2014 verified live against these exact three shapes on
223381
- 2026-08-26, over REST and over MCP tools/call (isError:true on all three).
223382
-
223383
- Mode (required): pass preflight_mode. Use "analyze" for informational risk only
223384
- (returns analysis_outcome with may_execute:false, no decision/execution_action/
223385
- safe_for_agent, no receipt). Use "authorize" for the operation-bound path that can
223386
- mint a receipt (requires context.operation: merge|deploy|publish|tool_call). Under
223387
- Decision Spec 2.0 the mode is mandatory; omission is an error unless a legacy
223388
- decision_spec_version "1.0" pin is set.
223389
-
223390
- Branch on execution_action only (CONTINUE | CONTINUE_WITH_MONITORING | REQUEST_APPROVAL | STOP).
223391
- On non-CONTINUE authorize responses, control_envelope.next_agent_step is a structured
223392
- remediation SUGGESTION the agent MAY follow (action, reason, resume_condition, then_call).
223393
- It is NOT permission and NOT a control-flow override \u2014 still branch on execution_action.
223394
- On CONTINUE / CONTINUE_WITH_MONITORING, next_agent_step is null (no remediation step).
223395
- Human tier remains human_report.next_steps_prose (same source; prose, not machine).`;
224707
+ var DESC_PREFLIGHT_CHANGE_SET = "Use this when: a change set of contract artifacts modifies OpenAPI, GraphQL, protobuf, AsyncAPI, MCP manifests, or agent tool schemas before merge, deploy, publish, or tool registration. Do not call for documentation-only changes, static readiness scoring, or receipt verification. Use analyze for risk only; authorize requires context.operation for permission. For receipt verification use coderifts.verify_receipt instead; for details of a past decision use coderifts.get_decision_details instead.";
223396
224708
  var DESC_VERIFY_RECEIPT = `Verify a CodeRifts signed chain-receipt you ALREADY HOLD: cryptographic
223397
224709
  authenticity (signature + key id), body binding, and \u2014 when lifecycle indices
223398
224710
  are available \u2014 whether it is currently valid authorization (not expired,
@@ -223725,7 +225037,11 @@ next_agent_step is a suggestion, not permission.`;
223725
225037
  }
223726
225038
  }
223727
225039
  },
223728
- annotations: { readOnlyHint: true, openWorldHint: false }
225040
+ // Authorize CREATES an authorization (receipt / grant). readOnlyHint:true over-stated
225041
+ // the mixed tool (roadmap 1212). Analyze is still informational (no receipt) — that
225042
+ // is the mode, not this annotation. Split into two tools is deferred: then_call in
225043
+ // response-envelope.js still names preflight_change_set, and the canonical set is 3.
225044
+ annotations: { readOnlyHint: false, openWorldHint: false }
223729
225045
  },
223730
225046
  {
223731
225047
  name: "get_decision_details",
@@ -224255,9 +225571,9 @@ var require_generate_surface_anchor = __commonJS({
224255
225571
  var OUT = path.join(__dirname, "..", "src", "generated", "surface-anchor.json");
224256
225572
  var ENDPOINT = "https://app.coderifts.com/mcp";
224257
225573
  var VOLATILE_KEYS = Object.freeze([]);
224258
- var SOURCE_REF = "https://raw.githubusercontent.com/coderifts/api-governance/surface-db5cea2f/tools.wire.v1.json";
224259
- var SOURCE_REF_COMMIT = "95999b6553c1f91ed9fd140f60440ee3e1f0dcd6";
224260
- var SOURCE_REF_STATUS = `PINNED TO ONE REVISION. source_ref is the wire-format tools[] as served, published in the public coderifts/api-governance repo at tag surface-db5cea2f (commit ${SOURCE_REF_COMMIT}). Verified at fill time: the file's own tools_sha256, its tools[] recomputed under the canonical rule in digest_input, and this anchor's tools_sha256 are the same value. HOW TO USE IT: fetch it, recompute the digest yourself, and compare it to tools_sha256 here. IF THEY DIFFER, TRUST NEITHER -- it means the surface moved and this ref was not re-tagged. A tag can be force-moved; the commit SHA above cannot, so pin the SHA URL if you want the stronger form. OUR OBLIGATION: every surface change requires a NEW tag and a NEW source_ref in this file. Skipping that leaves this field pointing at an old surface while still looking authoritative, which is worse than the null it replaced. HOW THE OBLIGATION IS ENFORCED, on both sides: this repo CI-runs generate-surface-anchor.js --check --verify-source-ref, which fetches the ref above, recomputes its digest under the rule in digest_input, and FAILS if it is stale, self-inconsistent, or its tag is gone. The target repo runs scripts/validate-tools-wire.mjs from its own npm test and a CI workflow -- on push, on PR, and daily, because the wire target can go stale without anything in that repo changing. Both SKIP LOUDLY rather than fail on a transport error, and both treat a 404 as a real verdict rather than a network problem. Neither this ref nor those gates is a root of trust: pin the digest at YOUR approval time -- see honesty.pin_at_approval_time.`;
225574
+ var SOURCE_REF = "https://raw.githubusercontent.com/coderifts/api-governance/surface-c3ec5f69/tools.wire.v1.json";
225575
+ var SOURCE_REF_COMMIT = "2496038c4bca672e0e9730a8de92db34d0556bb5";
225576
+ var SOURCE_REF_STATUS = `PINNED TO ONE REVISION. source_ref is the wire-format tools[] as served, published in the public coderifts/api-governance repo at tag surface-c3ec5f69 (commit ${SOURCE_REF_COMMIT}). Verified at fill time: the file's own tools_sha256, its tools[] recomputed under the canonical rule in digest_input, and this anchor's tools_sha256 are the same value. HOW TO USE IT: fetch it, recompute the digest yourself, and compare it to tools_sha256 here. IF THEY DIFFER, TRUST NEITHER -- it means the surface moved and this ref was not re-tagged. A tag can be force-moved; the commit SHA above cannot, so pin the SHA URL if you want the stronger form. OUR OBLIGATION: every surface change requires a NEW tag and a NEW source_ref in this file. Skipping that leaves this field pointing at an old surface while still looking authoritative, which is worse than the null it replaced. HOW THE OBLIGATION IS ENFORCED, on both sides: this repo CI-runs generate-surface-anchor.js --check --verify-source-ref, which fetches the ref above, recomputes its digest under the rule in digest_input, and FAILS if it is stale, self-inconsistent, or its tag is gone. The target repo runs scripts/validate-tools-wire.mjs from its own npm test and a CI workflow -- on push, on PR, and daily, because the wire target can go stale without anything in that repo changing. Both SKIP LOUDLY rather than fail on a transport error, and both treat a 404 as a real verdict rather than a network problem. Neither this ref nor those gates is a root of trust: pin the digest at YOUR approval time -- see honesty.pin_at_approval_time.`;
224261
225577
  var HONESTY = Object.freeze({
224262
225578
  pins_bytes_not_behaviour: "This anchor pins BYTES, not behaviour. It says the tool text you received is the text that was published. It says nothing about whether the model read it, understood it, or obeyed it.",
224263
225579
  scoped_to_its_profile: "This digest is scoped to the profile named above and to nothing else. The default-profile digest says NOTHING about the surface served with include_advanced_tools, which is a different tool set with a different digest. A hash without its profile does not identify a surface.",
@@ -224845,6 +226161,7 @@ var require_decision_result = __commonJS({
224845
226161
  } = require_policy_pin();
224846
226162
  var { sha256hex } = require_chain_attestation();
224847
226163
  var { canonicalJson } = require_canonical_json();
226164
+ var { projectNextAgentStep } = require_next_agent_step2();
224848
226165
  var {
224849
226166
  buildRemediationTransaction,
224850
226167
  blockRequiredActionCore
@@ -224885,6 +226202,41 @@ var require_decision_result = __commonJS({
224885
226202
  function envelopeSafeForAgent(decision) {
224886
226203
  return decision === "ALLOW" || decision === "WARN";
224887
226204
  }
226205
+ var SAFE_FOR_AGENT_SEMANTICS = Object.freeze({
226206
+ "decision_result.safe_for_agent": Object.freeze({
226207
+ question: "is the verdict ALLOW/WARN?",
226208
+ kind: "verdict",
226209
+ forced_false_by: Object.freeze([])
226210
+ }),
226211
+ safe_for_agent: Object.freeze({
226212
+ question: "is it actually safe to proceed?",
226213
+ kind: "defense_in_depth",
226214
+ note: "1227: the most-read (flat) field is now defense-in-depth, same as control_envelope. A naive agent reading it must not proceed on a coverage-gapped ALLOW. The raw verdict stays on decision_result \u2014 no information lost.",
226215
+ forced_false_by: Object.freeze([
226216
+ "decision BLOCK",
226217
+ "decision REQUIRE_APPROVAL",
226218
+ "degraded",
226219
+ "coverage_gap",
226220
+ "fallback_reason",
226221
+ "coverage_gap rule_id",
226222
+ "webhook_surface_unanalyzed"
226223
+ ])
226224
+ }),
226225
+ "control_envelope.safe_for_agent": Object.freeze({
226226
+ question: "is it actually safe to proceed?",
226227
+ kind: "defense_in_depth",
226228
+ note: "the verdict AND the coverage check; this is the field to gate on",
226229
+ forced_false_by: Object.freeze([
226230
+ "degraded",
226231
+ "coverage_gap",
226232
+ "fallback_reason",
226233
+ "coverage_gap rule_id",
226234
+ "webhook_surface_unanalyzed"
226235
+ ])
226236
+ }),
226237
+ invariant: "safe_for_agent == control_envelope.safe_for_agent <= decision_result.safe_for_agent",
226238
+ invariant_means: "defense-in-depth only tightens: true may become false, false never becomes true. The flat field equals control_envelope (1227)."
226239
+ });
224888
226240
  function mapSeverity(sev) {
224889
226241
  const up = String(sev || "").toUpperCase();
224890
226242
  return EVIDENCE_SEVERITIES.includes(up) ? up : "MEDIUM";
@@ -225026,8 +226378,27 @@ var require_decision_result = __commonJS({
225026
226378
  // RT-P-20 — fingerprint rebind expected bit (SERVER-authored; under body_hash).
225027
226379
  // true = gate must rebind; null/absent on legacy = not_expected (wire compat residual).
225028
226380
  // Caller cannot set/delete this — author only in change-set issuance path.
225029
- fingerprint_binding_expected: null
226381
+ fingerprint_binding_expected: null,
225030
226382
  // true | false | null (legacy)
226383
+ // I-1288 — the decision's own remediation SUGGESTION, INSIDE the signed envelope.
226384
+ //
226385
+ // WHY IT MOVED IN. The identical projection has always been on the response root, at
226386
+ // control_envelope.next_agent_step. But k8s-admission, gateway-verifier and the guard's
226387
+ // deployGate are handed the ENVELOPE and nothing else: they could verify the decision and
226388
+ // still not say what to do about it without a second network call to the issuer. A field
226389
+ // that only exists next to the envelope is not available to the parties the envelope was
226390
+ // built for. Placed here it is covered by decision_body_hash, so the receipt signs the
226391
+ // suggestion along with the decision that produced it — a tampered next step no longer
226392
+ // verifies.
226393
+ //
226394
+ // STILL NOT PERMISSION. Being signed makes it authentic, not authoritative: agents branch
226395
+ // on execution_action, exactly as before. Null on the allow class (CONTINUE /
226396
+ // CONTINUE_WITH_MONITORING) is the correct value, not an absent measurement.
226397
+ //
226398
+ // ADDITIVE, so spec_version stays decision-result.v1.1 (producer ENVELOPE COMPATIBILITY
226399
+ // rule 5: additive optional fields do not bump the major). control_envelope keeps emitting
226400
+ // its copy from the same pure function — one projection, two placements, never two rules.
226401
+ next_agent_step: null
225031
226402
  });
225032
226403
  var SOURCE_SLOTS = Object.freeze([
225033
226404
  "repository",
@@ -225193,6 +226564,10 @@ var require_decision_result = __commonJS({
225193
226564
  if (hasAdditive && decision === "BLOCK" && additive.required_action_core == null) {
225194
226565
  additive.required_action_core = blockRequiredActionCore(reasonCode(context, breakingCount));
225195
226566
  }
226567
+ if (hasAdditive) {
226568
+ const raForStep = additive.required_action_core != null && typeof additive.required_action_core === "object" ? additive.required_action_core : required_action;
226569
+ additive.next_agent_step = projectNextAgentStep(execution_action, raForStep);
226570
+ }
225196
226571
  if (hasAdditive) {
225197
226572
  if (remediation_transaction) {
225198
226573
  additive.remediation_transaction = remediation_transaction;
@@ -225251,6 +226626,7 @@ var require_decision_result = __commonJS({
225251
226626
  module2.exports = {
225252
226627
  buildDecisionResultV1,
225253
226628
  envelopeSafeForAgent,
226629
+ SAFE_FOR_AGENT_SEMANTICS,
225254
226630
  proseToType,
225255
226631
  toUtcSeconds,
225256
226632
  computeBodyHash,
@@ -227107,10 +228483,10 @@ var require_gate_pin = __commonJS({
227107
228483
  "src/generated/gate-pin.json"(exports2, module2) {
227108
228484
  module2.exports = {
227109
228485
  repo: "coderifts/contract-gate",
227110
- sha: "e5b6315e38c66a2274583ddf4d7be11515180326",
227111
- tag: "v0.5.0",
228486
+ sha: "1fae5d2bb2b52e1e1b745e649eab8834eac45645",
228487
+ tag: "v0.8.0",
227112
228488
  resolved_from: "https://github.com/coderifts/contract-gate refs/tags/v0",
227113
- resolved_at: "2026-08-26T08:37:01Z",
228489
+ resolved_at: "2026-09-02T07:25:19Z",
227114
228490
  note: "STRICT template pins this full commit SHA (GitHub: only a full SHA is immutable). v0 is a tag we move on every release, so it is NOT a pin. Re-run scripts/generate-gate-pin.js on each gate release; Dependabot bumps adopters."
227115
228491
  };
227116
228492
  }
@@ -228786,13 +230162,13 @@ var require_agent_host_files_embedded = __commonJS({
228786
230162
  ".cursor/hooks.json"
228787
230163
  ]);
228788
230164
  var AGENT_HOST_FILES = Object.freeze({
228789
- "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\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\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\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\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\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational (`may_execute` is always false) and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
228790
- "CLAUDE.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\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\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\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\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\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\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational (`may_execute` is always false) and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
228791
- ".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\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\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\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\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\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational (`may_execute` is always false) and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
228792
- ".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\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\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\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\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\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational (`may_execute` is always false) and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
228793
- "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\\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\\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\\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\\n\\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\\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\\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational (`may_execute` is always false) and is not permission. Read `execution_action` on the `decision_result` envelope.\\n\\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\\n\\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\\n\\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\\n\\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\\n\\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\\n\\nWith a proven tenant\u2194repo binding you may request `derivation:\\"server\\"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\\n\\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say \\"authorized, commit not proven\\".";\n',
228794
- "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\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\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\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\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\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational (`may_execute` is always false) and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
228795
- "skills/api-governance/SKILL.md": '---\nname: api-governance\ndescription: Before merging or shipping any API or tool-contract change: preflight the change set, then branch on execution_action.\n---\n\n# CodeRifts API Governance\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\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\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\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\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\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\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational (`may_execute` is always false) and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
230165
+ "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\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\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\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\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\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nVersions you may meet elsewhere: `cr.exec.v2` is the issued-token version for atomic execution, and `ENFORCING_STRICT_V1` is the versioned spelling of the strict profile. Neither is the default and neither is required by these rules \u2014 see `docs/grant-versions.md`.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
230166
+ "CLAUDE.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\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\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\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\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\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\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nVersions you may meet elsewhere: `cr.exec.v2` is the issued-token version for atomic execution, and `ENFORCING_STRICT_V1` is the versioned spelling of the strict profile. Neither is the default and neither is required by these rules \u2014 see `docs/grant-versions.md`.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
230167
+ ".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\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\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\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\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\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nVersions you may meet elsewhere: `cr.exec.v2` is the issued-token version for atomic execution, and `ENFORCING_STRICT_V1` is the versioned spelling of the strict profile. Neither is the default and neither is required by these rules \u2014 see `docs/grant-versions.md`.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
230168
+ ".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\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\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\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\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\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nVersions you may meet elsewhere: `cr.exec.v2` is the issued-token version for atomic execution, and `ENFORCING_STRICT_V1` is the versioned spelling of the strict profile. Neither is the default and neither is required by these rules \u2014 see `docs/grant-versions.md`.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
230169
+ "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\\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\\n\\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not \\"proceed with caution\\" without monitoring.\\n\\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\\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\\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\\n\\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\\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\\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\\n\\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\\n\\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\\n\\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\\n\\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\\n\\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\\n\\nVersions you may meet elsewhere: `cr.exec.v2` is the issued-token version for atomic execution, and `ENFORCING_STRICT_V1` is the versioned spelling of the strict profile. Neither is the default and neither is required by these rules \u2014 see `docs/grant-versions.md`.\\n\\nWith a proven tenant\u2194repo binding you may request `derivation:\\"server\\"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\\n\\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say \\"authorized, commit not proven\\".";\n',
230170
+ "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\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\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\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\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\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nVersions you may meet elsewhere: `cr.exec.v2` is the issued-token version for atomic execution, and `ENFORCING_STRICT_V1` is the versioned spelling of the strict profile. Neither is the default and neither is required by these rules \u2014 see `docs/grant-versions.md`.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
230171
+ "skills/api-governance/SKILL.md": '---\nname: api-governance\ndescription: Before merging or shipping any API or tool-contract change: preflight the change set, then branch on execution_action.\n---\n\n# CodeRifts API Governance\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\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\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\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\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\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\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nVersions you may meet elsewhere: `cr.exec.v2` is the issued-token version for atomic execution, and `ENFORCING_STRICT_V1` is the versioned spelling of the strict profile. Neither is the default and neither is required by these rules \u2014 see `docs/grant-versions.md`.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
228796
230172
  ".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',
228797
230173
  ".cursor/hooks.json": '{\n "version": 1,\n "hooks": {\n "preToolUse": [\n {\n "command": "coderifts cursor-hook",\n "matcher": "Write|Delete",\n "timeout": 60,\n "failClosed": true\n }\n ]\n }\n}\n'
228798
230174
  });
@@ -228958,6 +230334,7 @@ ${USAGE}` };
228958
230334
  var AGENT_SETUP_HOOK_WIRE_LINES = Object.freeze([
228959
230335
  chalk.bold(" Claude Code hook (.claude/settings.json): fail-closed PreToolUse"),
228960
230336
  chalk.dim(" matcher Write|Edit|MultiEdit \u2192 coderifts claude-hook (exit 2 = BLOCK)."),
230337
+ chalk.dim(" Path family: OpenAPI/Swagger, GraphQL, *.proto, AsyncAPI, MCP, tool-schema.json (plus git config coderifts.specPath; exclude via coderifts.specPathExclude)."),
228961
230338
  chalk.dim(" Missing key / API down / unreadable spec \u2192 exit 2 (enforce_indeterminate), not ALLOW."),
228962
230339
  chalk.dim(" Opt-out: CODERIFTS_ADVISORY=1|true restores soft-allow when governance could not run."),
228963
230340
  chalk.dim(" CODERIFTS_STRICT=1 cannot be weakened by ADVISORY.")
@@ -229358,6 +230735,7 @@ exit 0
229358
230735
  say(`Claude Code PreToolUse hook written to ${dest}`);
229359
230736
  if (backedUp) say(`Backup: ${backedUp}`);
229360
230737
  say("matcher Write|Edit|MultiEdit \u2192 coderifts claude-hook (exit 2 = BLOCK).");
230738
+ say("governs the contract path family (OpenAPI/Swagger, GraphQL, *.proto, AsyncAPI, MCP, tool-schema) plus git config coderifts.specPath; opt out one path with coderifts.specPathExclude.");
229361
230739
  return { exitCode: 0, code: "OK", path: dest, backedUp, wrote: true };
229362
230740
  }
229363
230741
  var CURSOR_HOOK_BIN = "coderifts cursor-hook";
@@ -256034,10 +257412,12 @@ var require_github_workflow_pin = __commonJS({
256034
257412
  "use strict";
256035
257413
  var { STATUS } = require_github_enforcement();
256036
257414
  var PIN_REASON = Object.freeze({
256037
- /** The pinned sha is the blob sha of the workflow file at the head being merged. */
257415
+ /** The pinned sha is the head commit sha being merged GitHub's field, grants PASS. */
256038
257416
  WORKFLOW_SHA_MATCHES_HEAD: "workflow_sha_matches_head",
256039
257417
  /** A pin exists, but it names bytes that are not what is at the head. */
256040
257418
  WORKFLOW_SHA_STALE: "workflow_sha_stale",
257419
+ /** Pin equals the file blob SHA, not a commit. Named; does NOT grant PASS. */
257420
+ WORKFLOW_SHA_IS_BLOB: "workflow_sha_is_blob",
256041
257421
  /** No sha in the rule — the ruleset names a path, so rewriting the file changes what runs. */
256042
257422
  WORKFLOW_NOT_PINNED: "workflow_not_pinned",
256043
257423
  /** We could not read the workflow file at the head, so no comparison is possible. */
@@ -256053,7 +257433,8 @@ var require_github_workflow_pin = __commonJS({
256053
257433
  workflow_ref: null,
256054
257434
  workflow_sha: null,
256055
257435
  workflow_sha_matches_head: false,
256056
- matched_against: null
257436
+ matched_against: null,
257437
+ grants_pass: false
256057
257438
  };
256058
257439
  if (!pin || !Array.isArray(pin.workflows) || pin.workflows.length === 0) {
256059
257440
  return {
@@ -256091,14 +257472,26 @@ var require_github_workflow_pin = __commonJS({
256091
257472
  }
256092
257473
  const matchedBlob = sameSha(pinned.sha, blobSha);
256093
257474
  const matchedCommit = sameSha(pinned.sha, headCommitSha);
256094
- if (matchedBlob || matchedCommit) {
257475
+ if (matchedCommit) {
256095
257476
  return {
256096
257477
  ...fields,
256097
257478
  status: STATUS.VERIFIED,
256098
257479
  reason_code: PIN_REASON.WORKFLOW_SHA_MATCHES_HEAD,
256099
257480
  workflow_sha_matches_head: true,
256100
- matched_against: matchedBlob ? "blob" : "commit",
256101
- reason: `the ruleset pins ${fields.workflow_path} to ${fields.workflow_sha}, which is the ${matchedBlob ? "blob sha of that file" : "head commit"} being merged. Moving this pin requires editing the ruleset (repository administration), a different permission from workflow write \u2014 so the check is attributable to THIS workflow, not merely to Actions. It still does not establish that the pinned workflow ran, nor that bypass actors cannot skip the ruleset entirely.`
257481
+ matched_against: "commit",
257482
+ grants_pass: true,
257483
+ reason: `the ruleset pins ${fields.workflow_path} to ${fields.workflow_sha}, which is the head commit being merged (GitHub workflows[].sha is a commit SHA, not a file blob). That match grants PASS. Moving this pin requires editing the ruleset (repository administration), a different permission from workflow write \u2014 so the check is attributable to THIS workflow, not merely to Actions. It still does not establish that the pinned workflow ran, nor that bypass actors cannot skip the ruleset entirely, nor that the pin equals the file blob SHA.`
257484
+ };
257485
+ }
257486
+ if (matchedBlob) {
257487
+ return {
257488
+ ...fields,
257489
+ status: STATUS.UNVERIFIABLE,
257490
+ reason_code: PIN_REASON.WORKFLOW_SHA_IS_BLOB,
257491
+ workflow_sha_matches_head: false,
257492
+ matched_against: "blob",
257493
+ grants_pass: false,
257494
+ reason: "pinned sha matches the file blob, not a commit \u2014 GitHub treats workflows[].sha as a commit SHA. Blob equality is named and does not grant PASS."
256102
257495
  };
256103
257496
  }
256104
257497
  return {
@@ -256107,9 +257500,26 @@ var require_github_workflow_pin = __commonJS({
256107
257500
  reason_code: PIN_REASON.WORKFLOW_SHA_STALE,
256108
257501
  workflow_sha_matches_head: false,
256109
257502
  matched_against: null,
257503
+ grants_pass: false,
256110
257504
  reason: `the ruleset pins ${fields.workflow_path} to ${fields.workflow_sha}, but the head carries ${blobSha || headCommitSha || "(nothing readable)"}. A pin to bytes nobody is merging gates nothing.`
256111
257505
  };
256112
257506
  }
257507
+ function evidenceStatement(headComparison) {
257508
+ if (headComparison && headComparison.grants_pass === true) {
257509
+ return "With the required workflow pinned by sha and that sha matching the head commit SHA (GitHub workflows[].sha is a commit SHA, not a file blob), the check is attributable to this workflow rather than to GitHub Actions in general: moving the pin requires repository administration, which is a different permission from workflow write. The common-issuer objection is closed WITHOUT a second GitHub App. This is not a blob-sha content pin.";
257510
+ }
257511
+ if (headComparison && headComparison.matched_against === "blob") {
257512
+ return "The pinned sha equals the workflow file blob, not the head commit. GitHub treats workflows[].sha as a commit SHA, so blob equality does not grant PASS. The common-issuer objection is not closed by a blob match.";
257513
+ }
257514
+ const code = headComparison && headComparison.reason_code;
257515
+ if (code === PIN_REASON.WORKFLOW_SHA_STALE) {
257516
+ return "A sha-pinned required workflow exists, but the pin names bytes that are not on the head. A stale pin gates nothing and does not grant PASS.";
257517
+ }
257518
+ if (code === PIN_REASON.WORKFLOW_FILE_UNREADABLE) {
257519
+ return "A sha-pinned required workflow exists, but the pin could not be compared with the head. That is UNVERIFIABLE, not a match, and does not grant PASS.";
257520
+ }
257521
+ return "Without a sha-pinned required workflow, the issuer proves the check came from GitHub Actions, not that it came from this workflow. Anyone who can write .github/workflows can post a passing check under the same shared issuer id.";
257522
+ }
256113
257523
  function workflowBindingEvidence(pin, headComparison) {
256114
257524
  return {
256115
257525
  pin_status: pin ? pin.status : STATUS.UNVERIFIABLE,
@@ -256119,10 +257529,11 @@ var require_github_workflow_pin = __commonJS({
256119
257529
  workflow_sha: headComparison.workflow_sha,
256120
257530
  workflow_sha_matches_head: headComparison.workflow_sha_matches_head,
256121
257531
  matched_against: headComparison.matched_against,
257532
+ grants_pass: headComparison.grants_pass === true,
256122
257533
  status: headComparison.status,
256123
257534
  reason_code: headComparison.reason_code,
256124
257535
  reason: headComparison.reason,
256125
- statement: headComparison.workflow_sha_matches_head ? "With the required workflow pinned by sha and that sha present on the head, the check is attributable to this workflow file rather than to GitHub Actions in general: moving the pin requires repository administration, which is a different permission from workflow write. The common-issuer objection is closed WITHOUT a second GitHub App." : "Without a sha-pinned required workflow, the issuer proves the check came from GitHub Actions, not that it came from this workflow. Anyone who can write .github/workflows can post a passing check under the same shared issuer id."
257536
+ statement: evidenceStatement(headComparison)
256126
257537
  };
256127
257538
  }
256128
257539
  module2.exports = { PIN_REASON, evaluateWorkflowShaMatchesHead, workflowBindingEvidence };
@@ -256645,12 +258056,27 @@ var require_setup_required_check = __commonJS({
256645
258056
  }
256646
258057
  const commitRead = runApi([`repos/${owner}/${repo}/commits/${encodeURIComponent(branch)}`], { cwd });
256647
258058
  const commitSha = commitRead && commitRead.ok && commitRead.body && (typeof commitRead.body.sha === "string" ? commitRead.body.sha : commitRead.body.commit && commitRead.body.commit.sha) || null;
258059
+ if (!commitSha || !/^[0-9a-f]{40}$/i.test(commitSha)) {
258060
+ if (!options.json) {
258061
+ logErr(chalk.red(`Could not resolve a commit SHA for ${branch}.`));
258062
+ logErr(" GitHub ruleset workflows[].sha is a commit SHA, not a file blob SHA \u2014 refusing to pin.");
258063
+ }
258064
+ return finish(EXIT.ERROR, {
258065
+ ok: false,
258066
+ code: "WORKFLOW_COMMIT_SHA_UNRESOLVED",
258067
+ owner,
258068
+ repo,
258069
+ branch,
258070
+ workflow_path: WORKFLOW_REL,
258071
+ http_status: commitRead ? commitRead.status : null
258072
+ });
258073
+ }
256648
258074
  const rulesetDocs = fetchRulesetDocs(runApi, owner, repo, cwd) || [];
256649
258075
  const existing = findExistingWorkflowRuleset(rulesetDocs, WORKFLOW_REL);
256650
258076
  const created = buildWorkflowRulesetPayload({
256651
258077
  repositoryId,
256652
258078
  branch,
256653
- sha: blobSha,
258079
+ sha: commitSha,
256654
258080
  path: WORKFLOW_REL
256655
258081
  });
256656
258082
  const payload = existing ? mergeWorkflowRule(existing, created) : created;
@@ -256661,7 +258087,8 @@ var require_setup_required_check = __commonJS({
256661
258087
  if (!options.json) {
256662
258088
  log(chalk.yellow(`Dry-run: pin ${WORKFLOW_REL} as a required workflow on ${branch}.`));
256663
258089
  log(` repo: ${owner}/${repo} (id ${repositoryId})`);
256664
- log(` blob: ${blobSha}`);
258090
+ log(` commit: ${commitSha}`);
258091
+ log(` blob (file object): ${blobSha}`);
256665
258092
  log(` ${existing ? `update ruleset ${existing.id}` : "create ruleset"} ${payload.name}`);
256666
258093
  log("");
256667
258094
  log(cmdText);
@@ -257463,9 +258890,22 @@ var require_enforce_check = __commonJS({
257463
258890
  );
257464
258891
  }
257465
258892
  }
258893
+ const requireBinding = options.requireWorkflowBinding === true;
258894
+ const bindingGrantsPass = report.workflow_binding && report.workflow_binding.grants_pass === true;
258895
+ const bindingExit = requireBinding && !bindingGrantsPass ? 1 : 0;
258896
+ if (bindingExit !== 0) {
258897
+ const wb = report.workflow_binding || {};
258898
+ errLog(chalk.red(
258899
+ `--require-workflow-binding: the required workflow is not sha-pinned to this head (status ${wb.status || "UNKNOWN"}${wb.reason_code ? `, ${wb.reason_code}` : ""}).`
258900
+ ));
258901
+ if (wb.reason) errLog(chalk.dim(` ${wb.reason}`));
258902
+ errLog(chalk.dim(
258903
+ " This is the CLI audit verdict on the Action path, not a merge block \u2014 the App-path clamp is a separate control."
258904
+ ));
258905
+ }
257466
258906
  if (options.json) log(JSON.stringify(report, null, 2));
257467
258907
  else log(renderHuman(report));
257468
- return { exitCode: 0, report };
258908
+ return { exitCode: bindingExit, report };
257469
258909
  }
257470
258910
  module2.exports = {
257471
258911
  runEnforceCheck,
@@ -257558,7 +258998,7 @@ var require_enforce = __commonJS({
257558
258998
  return { exitCode: 1, error: "check_apply_conflict", outcomes: [] };
257559
258999
  }
257560
259000
  const { runEnforceCheck } = require_enforce_check();
257561
- return runEnforceCheck(options, deps);
259001
+ return runEnforceCheck({ ...options, requireWorkflowBinding: options.requireWorkflowBinding === true }, deps);
257562
259002
  }
257563
259003
  const apply = options.apply === true;
257564
259004
  const getKey = deps.getApiKey || getApiKey;