coderifts 8.2.0 → 8.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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: "8.2.0",
3031
+ version: "8.4.0",
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",
@@ -3071,10 +3071,11 @@ var require_package = __commonJS({
3071
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
- test: "node --test test/*.test.js"
3074
+ test: "node --test test/*.test.js",
3075
+ "check:packed": "node scripts/check-packed-install.js"
3075
3076
  },
3076
3077
  dependencies: {
3077
- "@coderifts/agent-guard": "^17.0.0",
3078
+ "@coderifts/agent-guard": "^17.1.0",
3078
3079
  chalk: "^4.1.2",
3079
3080
  "cli-table3": "^0.6.4",
3080
3081
  commander: "^12.0.0",
@@ -71328,7 +71329,21 @@ These feed DIFFERENT halves of the system \u2014 the top level binds the ATOMIC
71328
71329
  ["target_uri", "targetUri"],
71329
71330
  ["tenant_id", "tenantId"],
71330
71331
  ["policy_hash", "policyHash"],
71331
- ["audience_hash", "audienceHash"],
71332
+ // 1402 — `audience_hash` IS NOT ON THIS LIST, and its absence is the fix.
71333
+ //
71334
+ // MEASURED 2026-09-06 against the server, read-only:
71335
+ // src/change-set.js:1138 reads TOP-LEVEL `input.audience`, strict /^v:[0-9a-f]{12}$/
71336
+ // execution-grant-v2.js:166 derives `audience_hash: sha256pref(audience)` ITSELF
71337
+ // execution-grant-request.v2.producer.json states it outright: "`audience_hash` is NOT a
71338
+ // request field of its own … sending it separately has no
71339
+ // effect and it stays out of this schema"
71340
+ //
71341
+ // So the Guard was sending a field nobody reads. Worse, it was ALSO sending the audience under
71342
+ // `context.audience`, which the handler does not read either (it reads `input.audience`) — both
71343
+ // channels were severed, and the binding a host configured reached the server through neither.
71344
+ // A field that looks bound and is not is the exact failure the server's own 1206 note describes.
71345
+ //
71346
+ // The fix is to send what the server consumes: top-level `audience`. See guard.ts.
71332
71347
  ["expected_state_token", "expectedStateToken"]
71333
71348
  ]);
71334
71349
  function v2WireFields(config) {
@@ -71872,6 +71887,17 @@ var require_guard = __commonJS({
71872
71887
  previous_receipt: resolvePreviousReceipt(config),
71873
71888
  idempotency_key: void 0
71874
71889
  };
71890
+ if (typeof config.audience === "string" && config.audience.length > 0) {
71891
+ if (/^v:[0-9a-f]{12}$/.test(config.audience)) {
71892
+ request.audience = config.audience;
71893
+ } else {
71894
+ emit(config, {
71895
+ type: "audience_not_bindable",
71896
+ at: iso(),
71897
+ cause: `audience ${JSON.stringify(config.audience)} is not the measured v:<12 hex> form; the server discards any other string to null, so it would NOT be bound. Nothing was sent for it.`
71898
+ });
71899
+ }
71900
+ }
71875
71901
  let grantObs;
71876
71902
  let grantForCall = null;
71877
71903
  if ((0, execution_grant_js_1.isExecutionGrantEnabled)(config)) {
@@ -227190,7 +227216,11 @@ var require_mcp_streamable = __commonJS({
227190
227216
  DECISION_ENUM,
227191
227217
  EXECUTION_ACTION_ENUM
227192
227218
  } = require_mcp_decision_result_shape();
227193
- var { GRANT_DEFAULT_V2_DATE, GRANT_VERSION_V1 } = require_grant_version_default();
227219
+ var {
227220
+ GRANT_DEFAULT_V2_DATE,
227221
+ GRANT_VERSION_V1,
227222
+ resolveGrantVersion
227223
+ } = require_grant_version_default();
227194
227224
  var TOOL_SOURCE = {
227195
227225
  preflight_check: "diff",
227196
227226
  agent_tool_check: "diff",
@@ -227598,8 +227628,10 @@ next_agent_step is a suggestion, not permission.`;
227598
227628
  // 1363: JSON Schema `default` is a SINGLE static value. A date-gated default cannot
227599
227629
  // be that without lying on one side of the cutoff. The 1344 mechanism (resolver +
227600
227630
  // GRANT_DEFAULT_V2_DATE) is unchanged; this is the schema expression of it.
227601
- // `x-coderifts-effective-default` is the value omitting the field yields TODAY
227602
- // (migration window). `x-coderifts-default-changes-at` is when that becomes v2.
227631
+ // 1384: the TEMPLATE here is the frozen surface constant (GRANT_VERSION_V1).
227632
+ // visibleTools() stamps the LIVE omit-value from resolveGrantVersion so the
227633
+ // served header is truthful on both sides of 2026-09-18. tools_sha256 hashes
227634
+ // the frozen constant, not the live value (volatile; see toolsForSurfaceDigest).
227603
227635
  "x-coderifts-effective-default": GRANT_VERSION_V1,
227604
227636
  "x-coderifts-default-changes-at": GRANT_DEFAULT_V2_DATE,
227605
227637
  description: "Grant envelope to mint when include_execution_grant is true. Omitting this yields cr.exec.v1 until " + GRANT_DEFAULT_V2_DATE + ' and cr.exec.v2 on and after it (see x-coderifts-effective-default / x-coderifts-default-changes-at). The response meta.grant_version is the version actually issued. An explicit value always wins \u2014 pin "v1" to keep current behaviour with no code change on the date.'
@@ -227850,9 +227882,29 @@ next_agent_step is a suggestion, not permission.`;
227850
227882
  function toolByName(name) {
227851
227883
  return MCP_MANIFEST.tools.find((t) => t.name === name);
227852
227884
  }
227853
- function visibleTools({ includeAdvanced = false } = {}) {
227885
+ function mapGrantVersionExt(tools, fn) {
227886
+ return (Array.isArray(tools) ? tools : []).map((t) => {
227887
+ const gv = t && t.inputSchema && t.inputSchema.properties && t.inputSchema.properties.grant_version;
227888
+ if (!gv) return t;
227889
+ const copy = JSON.parse(JSON.stringify(t));
227890
+ copy.inputSchema.properties.grant_version = fn(copy.inputSchema.properties.grant_version);
227891
+ return copy;
227892
+ });
227893
+ }
227894
+ function visibleTools({ includeAdvanced = false, now } = {}) {
227854
227895
  const names = includeAdvanced ? [...CANONICAL_TOOL_NAMES, ...ADVANCED_TOOL_NAMES] : [...CANONICAL_TOOL_NAMES];
227855
- return names.map(toolByName).filter(Boolean);
227896
+ const tools = names.map(toolByName).filter(Boolean);
227897
+ const live = resolveGrantVersion({}, { now }).version;
227898
+ return mapGrantVersionExt(tools, (gv) => {
227899
+ gv["x-coderifts-effective-default"] = live;
227900
+ return gv;
227901
+ });
227902
+ }
227903
+ function toolsForSurfaceDigest(tools) {
227904
+ return mapGrantVersionExt(tools, (gv) => {
227905
+ gv["x-coderifts-effective-default"] = GRANT_VERSION_V1;
227906
+ return gv;
227907
+ });
227856
227908
  }
227857
227909
  var SERVER_INFO = { name: "CodeRifts API Governance", version: "1.0.2" };
227858
227910
  var SUPPORTED_PROTOCOL_VERSIONS = ["2025-06-18", "2025-03-26", "2024-11-05"];
@@ -228136,6 +228188,8 @@ next_agent_step is a suggestion, not permission.`;
228136
228188
  module2.exports.MCP_MANIFEST = MCP_MANIFEST;
228137
228189
  module2.exports.SERVER_INFO = SERVER_INFO;
228138
228190
  module2.exports.visibleTools = visibleTools;
228191
+ module2.exports.toolsForSurfaceDigest = toolsForSurfaceDigest;
228192
+ module2.exports.EFFECTIVE_DEFAULT_VOLATILE_KEY = "x-coderifts-effective-default";
228139
228193
  module2.exports.CANONICAL_TOOL_NAMES = CANONICAL_TOOL_NAMES;
228140
228194
  module2.exports.ADVANCED_TOOL_NAMES = ADVANCED_TOOL_NAMES;
228141
228195
  module2.exports.HIDDEN_ALIAS_NAMES = HIDDEN_ALIAS_NAMES;
@@ -228270,14 +228324,15 @@ var require_generate_surface_anchor = __commonJS({
228270
228324
  }
228271
228325
  function buildAnchor(opts = {}) {
228272
228326
  const includeAdvanced = opts.includeAdvanced === true;
228273
- const tools = mcp.visibleTools({ includeAdvanced });
228327
+ const tools = mcp.visibleTools({ includeAdvanced, now: opts.now });
228328
+ const digestTools = typeof mcp.toolsForSurfaceDigest === "function" ? mcp.toolsForSurfaceDigest(tools) : tools;
228274
228329
  const profile = buildRequestProfile({
228275
228330
  endpoint: ENDPOINT,
228276
228331
  method: "tools/list",
228277
228332
  headers: {},
228278
228333
  params: includeAdvanced ? { include_advanced_tools: true } : {}
228279
228334
  });
228280
- const digest = crypto.createHash("sha256").update(canonicalJson(tools), "utf8").digest("hex");
228335
+ const digest = crypto.createHash("sha256").update(canonicalJson(digestTools), "utf8").digest("hex");
228281
228336
  return {
228282
228337
  profile,
228283
228338
  tools_sha256: `sha256:${digest}`,
@@ -230166,6 +230221,272 @@ var require_deploy_gate2 = __commonJS({
230166
230221
  }
230167
230222
  });
230168
230223
 
230224
+ // src/doctor.js
230225
+ var require_doctor = __commonJS({
230226
+ "src/doctor.js"(exports2, module2) {
230227
+ "use strict";
230228
+ var fs = require("fs");
230229
+ var path = require("path");
230230
+ function harness() {
230231
+ return require(path.join(__dirname, "..", "..", "..", "benchmark", "tool-selection-benchmark.js"));
230232
+ }
230233
+ var PREFLIGHT = "preflight_change_set";
230234
+ function bare(name) {
230235
+ return String(name == null ? "" : name).replace(/^coderifts\./, "");
230236
+ }
230237
+ function parseToolsDocument(doc) {
230238
+ if (Array.isArray(doc)) return { ok: true, tools: doc };
230239
+ if (doc && Array.isArray(doc.tools)) return { ok: true, tools: doc.tools };
230240
+ if (doc && doc.result && Array.isArray(doc.result.tools)) return { ok: true, tools: doc.result.tools };
230241
+ return {
230242
+ ok: false,
230243
+ why: "expected a tools/list response \u2014 an array, { tools: [...] }, or { result: { tools: [...] } }"
230244
+ };
230245
+ }
230246
+ function descriptionOf(t) {
230247
+ return typeof t.description === "string" ? t.description : "";
230248
+ }
230249
+ function schemaOf(t) {
230250
+ return t.inputSchema || t.input_schema || t.parameters || void 0;
230251
+ }
230252
+ function signalPreflightPresent(tools) {
230253
+ const hit = tools.find((t) => bare(t.name) === PREFLIGHT);
230254
+ return hit ? { ok: true, detail: `\`${bare(hit.name)}\` is in the table` } : {
230255
+ ok: false,
230256
+ detail: `no \`${PREFLIGHT}\` tool in the table \u2014 nothing to select for a contract change`,
230257
+ fix: "coderifts agent-setup"
230258
+ };
230259
+ }
230260
+ function signalDescriptionMatchesShipped(tools, shipped) {
230261
+ const hit = tools.find((t) => bare(t.name) === PREFLIGHT);
230262
+ if (!hit) return { ok: false, detail: "not applicable \u2014 no preflight tool", fix: "coderifts agent-setup" };
230263
+ const ship = shipped.find((t) => bare(t.name) === PREFLIGHT);
230264
+ if (!ship) return { ok: false, detail: "the shipped manifest carries no preflight tool to compare against" };
230265
+ const mine = descriptionOf(hit).trim();
230266
+ const theirs = descriptionOf(ship).trim();
230267
+ if (mine === theirs) return { ok: true, detail: "description is byte-identical to the shipped text" };
230268
+ const pct = theirs.length ? Math.round(mine.length / theirs.length * 100) : 0;
230269
+ return {
230270
+ ok: false,
230271
+ detail: `description DRIFTED from the shipped text (${mine.length} vs ${theirs.length} chars, ${pct}%) \u2014 the model reads this to decide, so a shortened or stale copy changes selection`,
230272
+ fix: "coderifts agent-setup --force"
230273
+ };
230274
+ }
230275
+ function signalSchemaValid(tools, h) {
230276
+ const checks = [];
230277
+ const attempt = (label, fn, arg) => {
230278
+ try {
230279
+ fn(arg);
230280
+ checks.push({ label, ok: true });
230281
+ } catch (err) {
230282
+ checks.push({ label, ok: false, why: err && err.message || "rejected" });
230283
+ }
230284
+ };
230285
+ const anthropicShape = tools.map((t) => ({ name: bare(t.name), description: descriptionOf(t), input_schema: schemaOf(t) }));
230286
+ if (typeof h.validateAnthropicTools === "function") attempt("anthropic", h.validateAnthropicTools, anthropicShape.map(h.toAnthropicTool || ((x) => x)));
230287
+ if (typeof h.validateOpenAITools === "function") attempt("openai", h.validateOpenAITools, anthropicShape.map(h.toOpenAITool || ((x) => x)));
230288
+ if (typeof h.validateGoogleTools === "function") attempt("google", h.validateGoogleTools, anthropicShape.map(h.toGoogleFunctionDeclaration || ((x) => x)));
230289
+ const bad = checks.filter((c) => !c.ok);
230290
+ return bad.length === 0 ? { ok: true, detail: `accepted by ${checks.map((c) => c.label).join(", ") || "(no validator available)"}` } : {
230291
+ ok: false,
230292
+ detail: `rejected by ${bad.map((c) => `${c.label} (${c.why})`).join("; ")}`,
230293
+ fix: "coderifts agent-setup --force"
230294
+ };
230295
+ }
230296
+ var RIVAL_HINTS = ["breaking", "openapi", "contract", "api diff", "api change", "schema diff"];
230297
+ function signalNoAbsorbingRival(tools, shipped = []) {
230298
+ const own = new Set(shipped.map((t) => bare(t.name)));
230299
+ const rivals = tools.filter((t) => bare(t.name) !== PREFLIGHT && !own.has(bare(t.name))).filter((t) => {
230300
+ const text = `${bare(t.name)} ${descriptionOf(t)}`.toLowerCase();
230301
+ return RIVAL_HINTS.some((h) => text.includes(h));
230302
+ }).map((t) => bare(t.name));
230303
+ return rivals.length === 0 ? { ok: true, detail: "no other tool advertises contract-change checking" } : {
230304
+ ok: false,
230305
+ warning: true,
230306
+ detail: `${rivals.length} other tool(s) advertise contract-change work and may absorb the call: ` + rivals.join(", ") + " \u2014 Tier 1 measures whether they actually do",
230307
+ fix: null
230308
+ };
230309
+ }
230310
+ function tier0(tools) {
230311
+ const h = harness();
230312
+ const shipped = h.getCanonicalTools();
230313
+ const signals = [
230314
+ { id: "preflight_present", ...signalPreflightPresent(tools) },
230315
+ { id: "description_matches_shipped", ...signalDescriptionMatchesShipped(tools, shipped) },
230316
+ { id: "schema_valid", ...signalSchemaValid(tools, h) },
230317
+ { id: "no_absorbing_rival", ...signalNoAbsorbingRival(tools, shipped) }
230318
+ ];
230319
+ const blocking = signals.filter((s) => !s.ok && !s.warning);
230320
+ return {
230321
+ tier: 0,
230322
+ tool_count: tools.length,
230323
+ signals,
230324
+ passed: signals.filter((s) => s.ok).length,
230325
+ total: signals.length,
230326
+ blocking: blocking.length,
230327
+ fixes: [...new Set(signals.filter((s) => !s.ok && s.fix).map((s) => s.fix))]
230328
+ };
230329
+ }
230330
+ var DOES_NOT_PROVE = Object.freeze({
230331
+ 0: [
230332
+ "that your model WOULD select CodeRifts \u2014 Tier 0 is structural only, a necessary condition",
230333
+ "that a change reached a merge/deploy/publish sink, or that any gate fired",
230334
+ "anything about tools this file was not shown"
230335
+ ],
230336
+ 1: [
230337
+ "that a change reached a merge/deploy/publish sink \u2014 selection is not enforcement",
230338
+ "anything about a model other than the one you ran, at the version you ran it",
230339
+ "that your production prompt behaves like the harness prompt"
230340
+ ]
230341
+ });
230342
+ module2.exports = {
230343
+ parseToolsDocument,
230344
+ tier0,
230345
+ harness,
230346
+ bare,
230347
+ DOES_NOT_PROVE,
230348
+ PREFLIGHT,
230349
+ signalPreflightPresent,
230350
+ signalDescriptionMatchesShipped,
230351
+ signalSchemaValid,
230352
+ signalNoAbsorbingRival
230353
+ };
230354
+ }
230355
+ });
230356
+
230357
+ // src/commands/doctor.js
230358
+ var require_doctor2 = __commonJS({
230359
+ "src/commands/doctor.js"(exports2, module2) {
230360
+ "use strict";
230361
+ var fs = require("fs");
230362
+ var path = require("path");
230363
+ var chalk = require_source();
230364
+ var {
230365
+ parseToolsDocument,
230366
+ tier0,
230367
+ harness,
230368
+ DOES_NOT_PROVE
230369
+ } = require_doctor();
230370
+ function readToolsFile(file) {
230371
+ const resolved = path.resolve(file);
230372
+ if (!fs.existsSync(resolved)) return { ok: false, why: `no such file: ${file}` };
230373
+ let doc;
230374
+ try {
230375
+ doc = JSON.parse(fs.readFileSync(resolved, "utf8"));
230376
+ } catch (err) {
230377
+ return { ok: false, why: `not JSON: ${err && err.message || "parse error"}` };
230378
+ }
230379
+ return parseToolsDocument(doc);
230380
+ }
230381
+ function printBoundary(tier, log) {
230382
+ log("");
230383
+ log(chalk.bold(" WHAT THIS DOES NOT PROVE"));
230384
+ for (const line of DOES_NOT_PROVE[tier]) log(chalk.dim(` \xB7 ${line}`));
230385
+ }
230386
+ function renderTier0(r, log) {
230387
+ log("");
230388
+ log(chalk.bold(` coderifts doctor \u2014 structural fitness (${r.tool_count} tools, no model called)`));
230389
+ log("");
230390
+ for (const s of r.signals) {
230391
+ const mark = s.ok ? chalk.green(" ok ") : s.warning ? chalk.yellow(" !! ") : chalk.red(" X ");
230392
+ log(`${mark}${s.id}`);
230393
+ log(chalk.dim(` ${s.detail}`));
230394
+ }
230395
+ log("");
230396
+ const verdict = r.blocking === 0 ? chalk.green(` structurally fit to be selected: ${r.passed}/${r.total} signals`) : chalk.red(` NOT structurally fit: ${r.blocking} blocking signal(s), ${r.passed}/${r.total} passed`);
230397
+ log(verdict);
230398
+ if (r.fixes.length) {
230399
+ log("");
230400
+ log(chalk.bold(" NEXT COMMAND"));
230401
+ for (const f of r.fixes) log(` ${chalk.cyan(f)}`);
230402
+ }
230403
+ log("");
230404
+ log(chalk.dim(" Tier 0 is the NECESSARY condition, not selectability. To measure whether your"));
230405
+ log(chalk.dim(" model actually selects, run the 15 fixtures on your own key:"));
230406
+ log(chalk.dim(" coderifts doctor --tools <file> --model <model-id>"));
230407
+ }
230408
+ async function runTier1({ tools, model, log, mock }) {
230409
+ const h = harness();
230410
+ const fixtures = h.loadSelectionFixtures();
230411
+ log("");
230412
+ log(chalk.bold(` coderifts doctor \u2014 selection benchmark (${fixtures.length} fixtures, model ${model})`));
230413
+ let client;
230414
+ if (mock) {
230415
+ client = new h.MockClient(h.perfectScript());
230416
+ log(chalk.yellow(" MOCK RUN \u2014 a scripted model that answers perfectly by construction."));
230417
+ log(chalk.yellow(" This measures the script. It is not a measurement of any model."));
230418
+ } else {
230419
+ const provider = h.PROVIDERS && Object.keys(h.PROVIDERS).find((p) => String(model).toLowerCase().includes(p));
230420
+ const factory = provider === "openai" ? h.createOpenAIClient : provider === "google" ? h.createGoogleClient : provider === "xai" ? h.createXaiClient : h.createAnthropicClient;
230421
+ const envVar = provider === "openai" ? "OPENAI_API_KEY" : provider === "google" ? "GOOGLE_API_KEY" : provider === "xai" ? "XAI_API_KEY" : "ANTHROPIC_API_KEY";
230422
+ const key = process.env[envVar];
230423
+ if (!key) {
230424
+ log("");
230425
+ log(chalk.red(` ${envVar} is not set.`));
230426
+ log(chalk.dim(" Tier 1 runs on YOUR key, on YOUR machine. CodeRifts never sees it, and"));
230427
+ log(chalk.dim(" never pays for the run. Export the key and re-run, or use --mock for a"));
230428
+ log(chalk.dim(" no-cost dry run of the harness path."));
230429
+ return { ok: false, reason: "missing_key" };
230430
+ }
230431
+ client = factory({ apiKey: key, model });
230432
+ }
230433
+ const userNames = new Set(tools.map((t) => String(t.name || "").replace(/^coderifts\./, "")));
230434
+ const withUserTable = fixtures.map((f) => ({
230435
+ ...f,
230436
+ available_tools: f.available_tools.filter((n) => userNames.has(String(n).replace(/^coderifts\./, "")))
230437
+ }));
230438
+ const unreachable = withUserTable.filter((f) => f.available_tools.length === 0).length;
230439
+ if (unreachable) {
230440
+ log(chalk.yellow(` ${unreachable} fixture(s) have no matching tool in your table \u2014 they can only score as a miss.`));
230441
+ }
230442
+ const unanswerable = withUserTable.filter((f) => {
230443
+ const want = String(f.expected_tool || "").replace(/^coderifts\./, "");
230444
+ return want && want !== "none" && !userNames.has(want);
230445
+ }).map((f) => f.id);
230446
+ if (unanswerable.length) {
230447
+ log(chalk.yellow(` ${unanswerable.length} fixture(s) expect a tool your table does not offer (${unanswerable.join(", ")}) \u2014 they CANNOT score correct. That is your table, not your model.`));
230448
+ }
230449
+ const run = await h.runBenchmark({ modelId: model, client, fixtures: withUserTable });
230450
+ const m = run && run.metrics ? run.metrics : h.computeMetrics(run.results || []);
230451
+ log("");
230452
+ for (const k of ["selection_coverage", "bypass_rate", "omission_rate", "wrong_tool_rate", "overall_accuracy"]) {
230453
+ if (m[k] !== void 0) log(` ${String(k).padEnd(20)} ${m[k]}`);
230454
+ }
230455
+ return { ok: true, metrics: m };
230456
+ }
230457
+ async function runDoctor(options = {}) {
230458
+ const log = options.logFn || ((s) => process.stdout.write(`${s}
230459
+ `));
230460
+ const exitFn = options.exitFn || ((c) => process.exit(c));
230461
+ if (!options.tools) {
230462
+ log(chalk.red(" --tools <file> is required: the tools/list your host actually serves."));
230463
+ log(chalk.dim(` Save it with your MCP client, or: curl .../mcp -d '{"method":"tools/list"}' > tools.json`));
230464
+ exitFn(2);
230465
+ return { exitCode: 2 };
230466
+ }
230467
+ const parsed = readToolsFile(options.tools);
230468
+ if (!parsed.ok) {
230469
+ log(chalk.red(` could not read the tool table: ${parsed.why}`));
230470
+ exitFn(2);
230471
+ return { exitCode: 2 };
230472
+ }
230473
+ if (options.model) {
230474
+ const r = await runTier1({ tools: parsed.tools, model: options.model, log, mock: !!options.mock });
230475
+ printBoundary(1, log);
230476
+ const code = r.ok ? 0 : 1;
230477
+ exitFn(code);
230478
+ return { exitCode: code, tier: 1, metrics: r.metrics };
230479
+ }
230480
+ const report = tier0(parsed.tools);
230481
+ renderTier0(report, log);
230482
+ printBoundary(0, log);
230483
+ exitFn(0);
230484
+ return { exitCode: 0, tier: 0, report };
230485
+ }
230486
+ module2.exports = { runDoctor, readToolsFile, renderTier0, printBoundary };
230487
+ }
230488
+ });
230489
+
230169
230490
  // src/commands/publish-gate.js
230170
230491
  var require_publish_gate = __commonJS({
230171
230492
  "src/commands/publish-gate.js"(exports2, module2) {
@@ -231171,7 +231492,9 @@ var require_required_check_contract = __commonJS({
231171
231492
  var CHECK_NAME = "CodeRifts / contract-gate";
231172
231493
  var GITHUB_ACTIONS_APP_ID = 15368;
231173
231494
  var GITHUB_ACTIONS_APP_SLUG = "github-actions";
231174
- var ENFORCING_ISSUER_APP_ID = GITHUB_ACTIONS_APP_ID;
231495
+ var CODERIFTS_APP_ID = 2860592;
231496
+ var CODERIFTS_APP_SLUG = "coderifts";
231497
+ var ENFORCING_ISSUER_APP_ID = CODERIFTS_APP_ID;
231175
231498
  function extractRequiredContexts(protection) {
231176
231499
  if (!protection || typeof protection !== "object") return [];
231177
231500
  const rsc = protection.required_status_checks;
@@ -231185,6 +231508,8 @@ var require_required_check_contract = __commonJS({
231185
231508
  GITHUB_ACTIONS_APP_ID,
231186
231509
  GITHUB_ACTIONS_APP_SLUG,
231187
231510
  ENFORCING_ISSUER_APP_ID,
231511
+ CODERIFTS_APP_ID,
231512
+ CODERIFTS_APP_SLUG,
231188
231513
  extractRequiredContexts
231189
231514
  };
231190
231515
  }
@@ -231297,13 +231622,14 @@ jobs:
231297
231622
  # monitoring-attestation: \${{ vars.CODERIFTS_MONITORING_ATTESTATION }}
231298
231623
  # monitoring-keyring: \${{ github.workspace }}/.coderifts/monitoring-keys.json
231299
231624
  #
231300
- # Optional \u2014 require an execution grant (contract-gate \u22650.5.0). The gate accepts BOTH
231301
- # cr.exec.v1 and cr.exec.v2; the ATOMIC profile issues v2.
231302
- # OFF HERE, ON IN STRICT, and the difference is deliberate \u2014 same rule as the @v0 tag
231303
- # above. Turning it on BLOCKS every PR that changes a governed contract path and carries
231304
- # no valid grant (\`grant_not_supplied\`), so it needs a working way to mint and deliver
231305
- # one per change set before it helps. This template is the easy-onboarding one and stays
231306
- # non-blocking; \`coderifts init --agents --strict\` is where the gate is armed.
231625
+ # Optional \u2014 require an execution grant (contract-gate \u22650.5.0). When armed, the
231626
+ # production grant is cr.exec.v2; cr.exec.v1 is legacy. The gate accepts BOTH so a
231627
+ # migration is not a hard cut. OFF HERE, ON IN STRICT, and the difference is deliberate
231628
+ # \u2014 same rule as the @v0 tag above. Turning it on BLOCKS every PR that changes a
231629
+ # governed contract path and carries no valid grant (\`grant_not_supplied\`), so it
231630
+ # needs a working way to mint and deliver one per change set before it helps. This
231631
+ # template is the easy-onboarding one and stays non-blocking;
231632
+ # \`coderifts init --agents --strict\` is where the gate is armed.
231307
231633
  # Do not "fix" this on and do not "fix" strict off.
231308
231634
  # require-grant: 'true'
231309
231635
  # execution-grant: \${{ vars.CODERIFTS_EXECUTION_GRANT }}
@@ -231362,18 +231688,22 @@ jobs:
231362
231688
  # Without this the three layers disagreed: the guard demands a grant in strict mode, this
231363
231689
  # workflow demanded verified monitoring, and the merge gate let a grant-less change through.
231364
231690
  #
231691
+ # PRIMARY GRANT: cr.exec.v2. Mint with grantVersion: 'v2' (or grant_version: 'v2').
231692
+ # LEGACY: cr.exec.v1 (bound to operation \u2225 target_id \u2225 after_payload) still verifies;
231693
+ # it is not what this template teaches. The gate accepts both so a migration PR is not
231694
+ # a hard cut; do not take that as "v1 is the strict-install grant".
231695
+ #
231365
231696
  # WHAT IT BLOCKS, exactly: a PR that changes a governed contract path
231366
231697
  # (openapi/graphql/grpc/asyncapi/mcp-manifest) and carries no valid grant (v1 or v2) fails
231367
231698
  # as \`grant_not_supplied\`. A PR that changes NO contract artifact is unaffected \u2014 the gate
231368
231699
  # short-circuits earlier as \`no_contract_changes\`. So the affected set is not "some PRs":
231369
231700
  # it is every PR this gate actually evaluates.
231370
231701
  #
231371
- # THE GRANT IS PER-CHANGE-SET. A grant binds operation \u2225 target_id \u2225
231372
- # after_payload, and after_payload is the AFTER-content of the changed governed files. A
231373
- # repository variable pinned once therefore covers exactly one diff and fails every other
231374
- # PR as \`grant_does_not_cover_path\`. The variable below is the delivery slot, not a
231375
- # set-and-forget value: mint the grant for the change set and publish it here, or replace
231376
- # this line with a step output from whatever mints yours.
231702
+ # THE GRANT IS PER-CHANGE-SET. A v2 grant is bound to this change set's after-payload
231703
+ # (and v2 identity fields). A repository variable pinned once therefore covers exactly
231704
+ # one diff and fails every other PR as \`grant_does_not_cover_path\`. The variable below
231705
+ # is the delivery slot, not a set-and-forget value: mint the grant for the change set
231706
+ # and publish it here, or replace this line with a step output from whatever mints yours.
231377
231707
  require-grant: 'true'
231378
231708
  # 1094: prefer the per-PR grant comment (coderifts grant publish). The repo variable
231379
231709
  # is a leftover slot for one after_payload and does not bind head_sha.
@@ -231607,13 +231937,31 @@ var require_github_enforcement = __commonJS({
231607
231937
  CHECK_NAME,
231608
231938
  GITHUB_ACTIONS_APP_SLUG,
231609
231939
  ENFORCING_ISSUER_APP_ID,
231940
+ CODERIFTS_APP_ID,
231610
231941
  extractRequiredContexts
231611
231942
  } = require_required_check_contract();
231612
231943
  var { GATE_ACTION } = require_contract_gate_workflow();
231613
231944
  var { inspectWorkflowYaml } = require_workflow_scan();
231614
231945
  var EVIDENCE_SPEC = "provider-enforcement-evidence.v2";
231615
231946
  var CODERIFTS_GITHUB_APP_SLUG = "coderifts";
231616
- var CODERIFTS_GITHUB_APP_ID = 2860592;
231947
+ var CODERIFTS_GITHUB_APP_ID = CODERIFTS_APP_ID;
231948
+ var CLAMP_RESIDUAL = 'the App check is clamped to "neutral" unless the server runs MERGEGATE_ENFORCE=true, and GitHub treats a neutral required check as passing. That setting is server-side and CANNOT BE DETERMINED FROM HERE, so this states which issuer is bound, not that the check will conclude failure on the next run.';
231949
+ function isMergegateEnforceObservedTrue(v) {
231950
+ return v === true || String(v == null ? "" : v).toLowerCase() === "true";
231951
+ }
231952
+ function reasonNamesUnobservableClamp(reason) {
231953
+ const s = String(reason || "");
231954
+ return s.includes(CLAMP_RESIDUAL) || /CANNOT BE DETERMINED FROM HERE/.test(s);
231955
+ }
231956
+ var BASIS_CLAMP_UNOBSERVABLE = "all six layers VERIFIED \u2014 binding proven; inescapable_deploy is false because enforcement requires MERGEGATE_ENFORCE, which is server-side and cannot be determined here.";
231957
+ var BASIS_NOT_ALL_VERIFIED = "inescapable_deploy stays false until every layer is VERIFIED";
231958
+ var BASIS_ENFORCE_OBSERVED = "all six layers VERIFIED and MERGEGATE_ENFORCE is observably true";
231959
+ function clampOrObservedClause(mergegateEnforceObserved) {
231960
+ if (isMergegateEnforceObservedTrue(mergegateEnforceObserved)) {
231961
+ return "MERGEGATE_ENFORCE is observably true; the App check may conclude failure and block.";
231962
+ }
231963
+ return `VERIFIED IS ABOUT THE BINDING, NOT THE NEXT CONCLUSION: ${CLAMP_RESIDUAL}`;
231964
+ }
231617
231965
  var REASON = Object.freeze({
231618
231966
  ISSUER_BOUND: "issuer_bound",
231619
231967
  NO_ISSUER_BINDING: "no_issuer_binding",
@@ -231743,7 +232091,7 @@ var require_github_enforcement = __commonJS({
231743
232091
  return out;
231744
232092
  }
231745
232093
  var RULESET_BYPASS_CAVEAT = " Bypass actors were not readable on this surface, so this does not establish that nobody can bypass the ruleset.";
231746
- function evaluateRuleset(rulesets, defaultBranch = null) {
232094
+ function evaluateRuleset(rulesets, defaultBranch = null, opts = {}) {
231747
232095
  if (rulesets == null) {
231748
232096
  return {
231749
232097
  status: STATUS.UNVERIFIABLE,
@@ -231798,7 +232146,7 @@ var require_github_enforcement = __commonJS({
231798
232146
  return {
231799
232147
  status: STATUS.VERIFIED,
231800
232148
  reason_code: REASON.RULESET_ISSUER_BOUND,
231801
- reason: `active ruleset "${bound.ruleset}" requires "${CHECK_NAME}" bound to integration_id ${ENFORCING_ISSUER_APP_ID} (${GITHUB_ACTIONS_APP_SLUG}) \u2014 the contract-gate Action, which concludes failure and blocks the merge. It targets ${defaultBranch ? `refs/heads/${defaultBranch}` : "the default branch"}.` + (bound.strict_policy === true ? " strict_required_status_checks_policy is ON, so a stale head cannot merge." : bound.strict_policy === false ? " RESIDUAL: strict_required_status_checks_policy is OFF, so a branch whose head is behind the base can merge on a check that passed against older bytes." : " strict_required_status_checks_policy was not readable here.") + RULESET_BYPASS_CAVEAT,
232149
+ reason: `active ruleset "${bound.ruleset}" requires "${CHECK_NAME}" bound to integration_id ${ENFORCING_ISSUER_APP_ID} (slug ${CODERIFTS_GITHUB_APP_SLUG}) \u2014 the dedicated CodeRifts App, the issuer the ruleset requires. ` + clampOrObservedClause(opts.mergegateEnforceObserved) + ` It targets ${defaultBranch ? `refs/heads/${defaultBranch}` : "the default branch"}.` + (bound.strict_policy === true ? " strict_required_status_checks_policy is ON, so a stale head cannot merge." : bound.strict_policy === false ? " RESIDUAL: strict_required_status_checks_policy is OFF, so a branch whose head is behind the base can merge on a check that passed against older bytes." : " strict_required_status_checks_policy was not readable here.") + RULESET_BYPASS_CAVEAT,
231802
232150
  ruleset_names: names,
231803
232151
  app_id: ENFORCING_ISSUER_APP_ID,
231804
232152
  ref_targeted: true,
@@ -231886,9 +232234,9 @@ var require_github_enforcement = __commonJS({
231886
232234
  reason: `active ruleset "${pinned[0].ruleset}" requires workflow ${pinned[0].path} pinned to sha ${pinned[0].sha} in repository_id ${pinned[0].repository_id}. Moving that pin requires editing the ruleset (repository administration), which is a different permission from workflow write. This does NOT establish that any pull request ran it, nor that bypass actors cannot skip the ruleset.`
231887
232235
  };
231888
232236
  }
231889
- function evaluateRequiredCheckAcrossSurfaces(protection, rulesets, defaultBranch = null) {
231890
- const classic = evaluateRequiredCheck(protection);
231891
- const ruleset = evaluateRuleset(rulesets, defaultBranch);
232237
+ function evaluateRequiredCheckAcrossSurfaces(protection, rulesets, defaultBranch = null, opts = {}) {
232238
+ const classic = evaluateRequiredCheck(protection, opts);
232239
+ const ruleset = evaluateRuleset(rulesets, defaultBranch, opts);
231892
232240
  const merged = (base) => ({
231893
232241
  ...base,
231894
232242
  surfaces_inspected: ["classic_branch_protection", rulesets == null ? "rulesets:unread" : "rulesets"],
@@ -231914,7 +232262,7 @@ var require_github_enforcement = __commonJS({
231914
232262
  reason: `${classic.reason} Rulesets were also inspected: ${ruleset.reason}. Neither surface binds "${CHECK_NAME}" to an issuer that can block.`
231915
232263
  });
231916
232264
  }
231917
- function evaluateRequiredCheck(protection) {
232265
+ function evaluateRequiredCheck(protection, opts = {}) {
231918
232266
  const expected = expectedIssuerAppId();
231919
232267
  const rsc = protection && protection.required_status_checks;
231920
232268
  const contexts = extractRequiredContexts(protection);
@@ -231934,19 +232282,9 @@ var require_github_enforcement = __commonJS({
231934
232282
  return {
231935
232283
  status: STATUS.VERIFIED,
231936
232284
  reason_code: REASON.ISSUER_BOUND,
231937
- reason: `required_status_checks.checks binds "${CHECK_NAME}" to GitHub App id ${ENFORCING_ISSUER_APP_ID} (slug ${GITHUB_ACTIONS_APP_SLUG}) \u2014 the issuer the coderifts/contract-gate Action posts under, which concludes failure and blocks the merge. RESIDUAL: that issuer is shared by every GitHub Actions workflow in this repository, so anyone who can edit .github/workflows can post a passing check under it. Govern those paths too.`,
231938
- required_contexts: contexts,
231939
- app_id: ENFORCING_ISSUER_APP_ID
231940
- };
231941
- }
231942
- const advisory = ours.find((c) => numericAppId(c.app_id) === expected);
231943
- if (advisory) {
231944
- return {
231945
- status: STATUS.UNVERIFIABLE,
231946
- reason_code: REASON.ISSUER_ADVISORY_APP_UNOBSERVABLE,
231947
- reason: `required_status_checks.checks binds "${CHECK_NAME}" to CodeRifts App id ${expected} (slug ${CODERIFTS_GITHUB_APP_SLUG}). That check is advisory by default: it concludes "neutral" unless the server runs with MERGEGATE_ENFORCE=true, and GitHub treats a neutral required check as passing. MERGEGATE_ENFORCE is a server-side setting this CLI cannot observe, so whether this pin gates CANNOT BE DETERMINED FROM HERE. To get a check that provably blocks, bind "${CHECK_NAME}" to app_id ${ENFORCING_ISSUER_APP_ID} (${GITHUB_ACTIONS_APP_SLUG}) \u2014 the contract-gate Action.`,
232285
+ reason: `required_status_checks.checks binds "${CHECK_NAME}" to GitHub App id ${ENFORCING_ISSUER_APP_ID} (slug ${CODERIFTS_GITHUB_APP_SLUG}) \u2014 the dedicated CodeRifts App, the issuer the ruleset requires and the one observed concluding failure with the merge blocked. ` + clampOrObservedClause(opts.mergegateEnforceObserved),
231948
232286
  required_contexts: contexts,
231949
- app_id: expected,
232287
+ app_id: ENFORCING_ISSUER_APP_ID,
231950
232288
  expected_app_id: ENFORCING_ISSUER_APP_ID
231951
232289
  };
231952
232290
  }
@@ -232112,11 +232450,12 @@ var require_github_enforcement = __commonJS({
232112
232450
  local,
232113
232451
  auth,
232114
232452
  rulesetsRead = null,
232115
- branch = null
232453
+ branch = null,
232454
+ mergegateEnforceObserved = null
232116
232455
  } = {}) {
232117
232456
  const layers = [];
232118
232457
  const localFiles = local || { contractGateFiles: [], deployGateFiles: [] };
232119
- const rulesetVerdict = evaluateRuleset(rulesetsRead, branch);
232458
+ const rulesetVerdict = evaluateRuleset(rulesetsRead, branch, { mergegateEnforceObserved });
232120
232459
  const rulesetUpgrade = (classicLayerFields) => {
232121
232460
  if (rulesetVerdict.status !== STATUS.VERIFIED) return null;
232122
232461
  return {
@@ -232219,7 +232558,7 @@ var require_github_enforcement = __commonJS({
232219
232558
  } else {
232220
232559
  const protection = prot.body && typeof prot.body === "object" ? prot.body : {};
232221
232560
  const endpoint = prot.endpoint ? `GET ${prot.endpoint}` : null;
232222
- const required = evaluateRequiredCheck(protection);
232561
+ const required = evaluateRequiredCheck(protection, { mergegateEnforceObserved });
232223
232562
  pushRequiredCheck({
232224
232563
  status: required.status,
232225
232564
  reason: required.reason,
@@ -232329,13 +232668,19 @@ var require_github_enforcement = __commonJS({
232329
232668
  }
232330
232669
  }
232331
232670
  const byId = Object.fromEntries(layers.map((l) => [l.id, l]));
232332
- const inescapable = LAYER_IDS.every((id) => byId[id] && byId[id].status === STATUS.VERIFIED);
232671
+ const allVerified = LAYER_IDS.every((id) => byId[id] && byId[id].status === STATUS.VERIFIED);
232672
+ const requiredLayer = byId.required_check;
232673
+ const clampUnobservable = !!(requiredLayer && reasonNamesUnobservableClamp(requiredLayer.reason));
232674
+ const inescapable = allVerified && !clampUnobservable;
232675
+ let basis = BASIS_NOT_ALL_VERIFIED;
232676
+ if (allVerified && clampUnobservable) basis = BASIS_CLAMP_UNOBSERVABLE;
232677
+ else if (inescapable) basis = BASIS_ENFORCE_OBSERVED;
232333
232678
  return {
232334
232679
  layers,
232335
232680
  inescapable_deploy: inescapable,
232336
232681
  claim: {
232337
232682
  inescapable_deploy: inescapable,
232338
- basis: inescapable ? "all six layers VERIFIED (issuer-bound required check + active workflow jobs + correlated environment)" : "inescapable_deploy stays false until every layer is VERIFIED"
232683
+ basis
232339
232684
  }
232340
232685
  };
232341
232686
  }
@@ -232424,6 +232769,12 @@ var require_github_enforcement = __commonJS({
232424
232769
  APP_INSTALLATION,
232425
232770
  NO_TOKEN_INSTRUCTION,
232426
232771
  LAYER_IDS,
232772
+ CLAMP_RESIDUAL,
232773
+ BASIS_CLAMP_UNOBSERVABLE,
232774
+ BASIS_NOT_ALL_VERIFIED,
232775
+ BASIS_ENFORCE_OBSERVED,
232776
+ reasonNamesUnobservableClamp,
232777
+ isMergegateEnforceObservedTrue,
232427
232778
  STATUS,
232428
232779
  FRESHNESS,
232429
232780
  EVIDENCE_TTL_SECONDS,
@@ -233875,6 +234226,825 @@ var require_mcp_repo_config = __commonJS({
233875
234226
  }
233876
234227
  });
233877
234228
 
234229
+ // src/atomic-v2-contract.js
234230
+ var require_atomic_v2_contract = __commonJS({
234231
+ "src/atomic-v2-contract.js"(exports2, module2) {
234232
+ "use strict";
234233
+ var ADAPTER_CONTRACT_VERSION = "atomic-v2-adapter/1";
234234
+ var ADAPTER_OPERATIONS = Object.freeze([
234235
+ "state_challenge",
234236
+ "consume",
234237
+ "conditional_write",
234238
+ "mutate",
234239
+ "executor_attestation",
234240
+ "provider_readback"
234241
+ ]);
234242
+ var REQUIRED_CAPABILITIES = ADAPTER_OPERATIONS;
234243
+ var ADAPTER_CONTRACT = Object.freeze({
234244
+ version: ADAPTER_CONTRACT_VERSION,
234245
+ operations: Object.freeze({
234246
+ state_challenge: Object.freeze({
234247
+ in: Object.freeze(["target_id", "environment", "now"]),
234248
+ out: Object.freeze(["ok", "state_nonce", "expires_at", "current_digest", "target_id", "jti", "scope_hash"])
234249
+ }),
234250
+ consume: Object.freeze({
234251
+ in: Object.freeze(["state_nonce", "jti", "scope_hash", "target_id"]),
234252
+ out: Object.freeze(["ok", "consumed", "jti"])
234253
+ }),
234254
+ conditional_write: Object.freeze({
234255
+ in: Object.freeze(["target_id", "expected_digest", "payload"]),
234256
+ out: Object.freeze(["ok", "new_digest"])
234257
+ }),
234258
+ mutate: Object.freeze({
234259
+ in: Object.freeze(["target_id", "grant", "payload", "attestation"]),
234260
+ out: Object.freeze(["ok", "attestation"])
234261
+ }),
234262
+ executor_attestation: Object.freeze({
234263
+ in: Object.freeze(["target_id", "operation", "digest"]),
234264
+ out: Object.freeze(["ok", "attestation", "executor_identity"])
234265
+ }),
234266
+ provider_readback: Object.freeze({
234267
+ in: Object.freeze(["target_id"]),
234268
+ out: Object.freeze(["ok", "digest", "target_id"])
234269
+ })
234270
+ })
234271
+ });
234272
+ function checkContractVersion(wiring) {
234273
+ const found = wiring && wiring.contract_version;
234274
+ if (found === ADAPTER_CONTRACT_VERSION) {
234275
+ return { ok: true, expected: ADAPTER_CONTRACT_VERSION, found };
234276
+ }
234277
+ return {
234278
+ ok: false,
234279
+ expected: ADAPTER_CONTRACT_VERSION,
234280
+ found: found == null ? null : String(found),
234281
+ message: found == null ? `adapter-contract version missing (expected ${ADAPTER_CONTRACT_VERSION})` : `adapter-contract version mismatch: found ${found}, expected ${ADAPTER_CONTRACT_VERSION}`
234282
+ };
234283
+ }
234284
+ module2.exports = {
234285
+ ADAPTER_CONTRACT_VERSION,
234286
+ ADAPTER_OPERATIONS,
234287
+ ADAPTER_CONTRACT,
234288
+ REQUIRED_CAPABILITIES,
234289
+ checkContractVersion
234290
+ };
234291
+ }
234292
+ });
234293
+
234294
+ // src/atomic-v2-claim.js
234295
+ var require_atomic_v2_claim = __commonJS({
234296
+ "src/atomic-v2-claim.js"(exports2, module2) {
234297
+ "use strict";
234298
+ var TARGET_BINDING_FIELDS = Object.freeze([
234299
+ "target_id",
234300
+ "environment",
234301
+ "executor_identity",
234302
+ "operation",
234303
+ "adapter_id"
234304
+ ]);
234305
+ function bindingPresent(input, key) {
234306
+ const v = input && input[key];
234307
+ return !(v == null || String(v).trim() === "");
234308
+ }
234309
+ function normalizeBound(input = {}) {
234310
+ const bound = {};
234311
+ for (const key of TARGET_BINDING_FIELDS) {
234312
+ if (!bindingPresent(input, key)) {
234313
+ return { ok: false, missing: key };
234314
+ }
234315
+ bound[key] = String(input[key]);
234316
+ }
234317
+ return { ok: true, bound };
234318
+ }
234319
+ function buildClaim(input = {}) {
234320
+ const customer_target_verified = input.customer_target_verified === true;
234321
+ const production_ready = input.production_ready === true;
234322
+ if (production_ready === true && customer_target_verified !== true) {
234323
+ const err = new Error(
234324
+ "UNCONSTRUCTIBLE_CLAIM: customer_target_verified:false AND production_ready:true"
234325
+ );
234326
+ err.code = "UNCONSTRUCTIBLE_CLAIM";
234327
+ throw err;
234328
+ }
234329
+ if (customer_target_verified) {
234330
+ const binding = normalizeBound(input);
234331
+ if (!binding.ok) {
234332
+ const err = new Error(
234333
+ `UNCONSTRUCTIBLE_CLAIM: customer_target_verified:true requires ${binding.missing}`
234334
+ );
234335
+ err.code = "UNCONSTRUCTIBLE_CLAIM";
234336
+ throw err;
234337
+ }
234338
+ return Object.freeze({
234339
+ customer_target_verified: true,
234340
+ production_ready: true === production_ready,
234341
+ target_id: binding.bound.target_id,
234342
+ environment: binding.bound.environment,
234343
+ executor_identity: binding.bound.executor_identity,
234344
+ operation: binding.bound.operation,
234345
+ adapter_id: binding.bound.adapter_id
234346
+ });
234347
+ }
234348
+ return Object.freeze({
234349
+ customer_target_verified: false,
234350
+ production_ready: false,
234351
+ target_id: bindingPresent(input, "target_id") ? String(input.target_id) : null,
234352
+ environment: bindingPresent(input, "environment") ? String(input.environment) : null,
234353
+ executor_identity: bindingPresent(input, "executor_identity") ? String(input.executor_identity) : null,
234354
+ operation: bindingPresent(input, "operation") ? String(input.operation) : null,
234355
+ adapter_id: bindingPresent(input, "adapter_id") ? String(input.adapter_id) : null
234356
+ });
234357
+ }
234358
+ function evidenceVerifies(claim, query = {}) {
234359
+ if (!claim || claim.customer_target_verified !== true) return false;
234360
+ for (const key of TARGET_BINDING_FIELDS) {
234361
+ if (String(claim[key] || "") !== String(query[key] || "")) return false;
234362
+ }
234363
+ return true;
234364
+ }
234365
+ module2.exports = {
234366
+ TARGET_BINDING_FIELDS,
234367
+ normalizeBound,
234368
+ buildClaim,
234369
+ evidenceVerifies
234370
+ };
234371
+ }
234372
+ });
234373
+
234374
+ // src/atomic-v2-probes.js
234375
+ var require_atomic_v2_probes = __commonJS({
234376
+ "src/atomic-v2-probes.js"(exports2, module2) {
234377
+ "use strict";
234378
+ var NEGATIVE_PROBES = Object.freeze([
234379
+ "replay",
234380
+ "expired_challenge",
234381
+ "wrong_target",
234382
+ "cas_mismatch",
234383
+ "missing_attestation",
234384
+ "mismatched_jti_scope_hash"
234385
+ ]);
234386
+ function isThenable(value) {
234387
+ return value != null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
234388
+ }
234389
+ function callOp(wiring, name, args) {
234390
+ const fn = wiring && wiring[name];
234391
+ if (typeof fn !== "function") {
234392
+ const err = new Error(`adapter missing operation ${name}`);
234393
+ err.code = "ADAPTER_OP_MISSING";
234394
+ throw err;
234395
+ }
234396
+ return fn(args);
234397
+ }
234398
+ function settle(invoke) {
234399
+ try {
234400
+ const result = invoke();
234401
+ if (isThenable(result)) {
234402
+ Promise.resolve(result).catch(() => {
234403
+ });
234404
+ return { kind: "async" };
234405
+ }
234406
+ if (result && result.ok === true) return { kind: "ok", result };
234407
+ return { kind: "reject", result, reason: result && result.reason || "ok:false" };
234408
+ } catch (err) {
234409
+ return { kind: "throw", reason: err && (err.code || err.message) || "threw" };
234410
+ }
234411
+ }
234412
+ function otherTarget(targetId) {
234413
+ return `${targetId}__NOT_${targetId}`;
234414
+ }
234415
+ function issued(ch) {
234416
+ return {
234417
+ nonce: ch && ch.state_nonce,
234418
+ jti: ch && ch.jti,
234419
+ scope_hash: ch && ch.scope_hash,
234420
+ digest: ch && ch.current_digest,
234421
+ expires_at: ch && ch.expires_at
234422
+ };
234423
+ }
234424
+ function runPositiveRoundTrip(wiring, bound) {
234425
+ const target_id = bound.target_id;
234426
+ const environment = bound.environment;
234427
+ const operation = bound.operation;
234428
+ const steps = [];
234429
+ const chS = settle(() => callOp(wiring, "state_challenge", { target_id, environment }));
234430
+ if (chS.kind !== "ok" || !chS.result.state_nonce) {
234431
+ return {
234432
+ ok: false,
234433
+ steps,
234434
+ message: `positive state_challenge did not succeed (${chS.kind}/${chS.reason || "no nonce"})`
234435
+ };
234436
+ }
234437
+ steps.push("state_challenge");
234438
+ const { nonce, jti, scope_hash, digest } = issued(chS.result);
234439
+ if (!jti || !scope_hash) {
234440
+ return { ok: false, steps, message: "positive state_challenge did not bind jti/scope_hash" };
234441
+ }
234442
+ const consS = settle(() => callOp(wiring, "consume", {
234443
+ state_nonce: nonce,
234444
+ jti,
234445
+ scope_hash,
234446
+ target_id
234447
+ }));
234448
+ if (consS.kind !== "ok") {
234449
+ return { ok: false, steps, message: `positive consume did not succeed (${consS.kind}/${consS.reason})` };
234450
+ }
234451
+ steps.push("consume");
234452
+ const rbS = settle(() => callOp(wiring, "provider_readback", { target_id }));
234453
+ if (rbS.kind !== "ok" || !rbS.result.digest) {
234454
+ return { ok: false, steps, message: `positive provider_readback did not succeed (${rbS.kind}/${rbS.reason})` };
234455
+ }
234456
+ steps.push("provider_readback");
234457
+ const casS = settle(() => callOp(wiring, "conditional_write", {
234458
+ target_id,
234459
+ expected_digest: rbS.result.digest || digest,
234460
+ payload: "positive-cas"
234461
+ }));
234462
+ if (casS.kind !== "ok" || !casS.result.new_digest) {
234463
+ return { ok: false, steps, message: `positive conditional_write did not succeed (${casS.kind}/${casS.reason})` };
234464
+ }
234465
+ steps.push("conditional_write");
234466
+ const attS = settle(() => callOp(wiring, "executor_attestation", {
234467
+ target_id,
234468
+ operation,
234469
+ digest: casS.result.new_digest
234470
+ }));
234471
+ if (attS.kind !== "ok" || !attS.result.attestation) {
234472
+ return {
234473
+ ok: false,
234474
+ steps,
234475
+ message: `positive executor_attestation did not succeed (${attS.kind}/${attS.reason})`
234476
+ };
234477
+ }
234478
+ steps.push("executor_attestation");
234479
+ const mutS = settle(() => callOp(wiring, "mutate", {
234480
+ target_id,
234481
+ grant: { jti, scope_hash, target_id, expires_at: chS.result.expires_at },
234482
+ payload: "positive-mutate",
234483
+ attestation: attS.result.attestation
234484
+ }));
234485
+ if (mutS.kind !== "ok") {
234486
+ return { ok: false, steps, message: `positive mutate did not succeed (${mutS.kind}/${mutS.reason})` };
234487
+ }
234488
+ steps.push("mutate");
234489
+ return {
234490
+ ok: true,
234491
+ steps,
234492
+ executor_identity: attS.result.executor_identity || null,
234493
+ message: "positive round-trip ok"
234494
+ };
234495
+ }
234496
+ function runNegativeProbes(wiring, bound) {
234497
+ const target_id = bound.target_id;
234498
+ const environment = bound.environment;
234499
+ const results = [];
234500
+ const chReplay = settle(() => callOp(wiring, "state_challenge", { target_id, environment }));
234501
+ if (chReplay.kind !== "ok") {
234502
+ results.push({ name: "replay", failed: false, reason: `setup_${chReplay.kind}` });
234503
+ } else {
234504
+ const iss = issued(chReplay.result);
234505
+ const first = settle(() => callOp(wiring, "consume", {
234506
+ state_nonce: iss.nonce,
234507
+ jti: iss.jti,
234508
+ scope_hash: iss.scope_hash,
234509
+ target_id
234510
+ }));
234511
+ if (first.kind !== "ok") {
234512
+ results.push({ name: "replay", failed: false, reason: "first_consume_did_not_succeed" });
234513
+ } else {
234514
+ const second = settle(() => callOp(wiring, "consume", {
234515
+ state_nonce: iss.nonce,
234516
+ jti: iss.jti,
234517
+ scope_hash: iss.scope_hash,
234518
+ target_id
234519
+ }));
234520
+ results.push({
234521
+ name: "replay",
234522
+ failed: second.kind === "reject" || second.kind === "throw",
234523
+ reason: second.kind === "async" ? "async_unprobed" : second.reason || second.kind
234524
+ });
234525
+ }
234526
+ }
234527
+ const chExp = settle(() => callOp(wiring, "state_challenge", {
234528
+ target_id,
234529
+ environment,
234530
+ now: Date.parse("1999-12-31T00:00:00Z")
234531
+ }));
234532
+ if (chExp.kind !== "ok") {
234533
+ results.push({ name: "expired_challenge", failed: false, reason: `setup_${chExp.kind}` });
234534
+ } else {
234535
+ const iss = issued(chExp.result);
234536
+ const exp = settle(() => callOp(wiring, "consume", {
234537
+ state_nonce: iss.nonce,
234538
+ jti: iss.jti,
234539
+ scope_hash: iss.scope_hash,
234540
+ target_id
234541
+ }));
234542
+ results.push({
234543
+ name: "expired_challenge",
234544
+ failed: exp.kind === "reject" || exp.kind === "throw",
234545
+ reason: exp.kind === "async" ? "async_unprobed" : exp.reason || exp.kind
234546
+ });
234547
+ }
234548
+ const chWrong = settle(() => callOp(wiring, "state_challenge", { target_id, environment }));
234549
+ if (chWrong.kind !== "ok") {
234550
+ results.push({ name: "wrong_target", failed: false, reason: `setup_${chWrong.kind}` });
234551
+ } else {
234552
+ const iss = issued(chWrong.result);
234553
+ const wt = settle(() => callOp(wiring, "consume", {
234554
+ state_nonce: iss.nonce,
234555
+ jti: iss.jti,
234556
+ scope_hash: iss.scope_hash,
234557
+ target_id: otherTarget(target_id)
234558
+ }));
234559
+ results.push({
234560
+ name: "wrong_target",
234561
+ failed: wt.kind === "reject" || wt.kind === "throw",
234562
+ reason: wt.kind === "async" ? "async_unprobed" : wt.reason || wt.kind
234563
+ });
234564
+ }
234565
+ const cas = settle(() => callOp(wiring, "conditional_write", {
234566
+ target_id,
234567
+ expected_digest: "sha256:deadbeef-not-current",
234568
+ payload: "cas-mismatch-probe"
234569
+ }));
234570
+ results.push({
234571
+ name: "cas_mismatch",
234572
+ failed: cas.kind === "reject" || cas.kind === "throw",
234573
+ reason: cas.kind === "async" ? "async_unprobed" : cas.reason || cas.kind
234574
+ });
234575
+ const miss = settle(() => callOp(wiring, "mutate", {
234576
+ target_id,
234577
+ grant: { jti: "jti-no-attest", scope_hash: "scope-no-attest", target_id },
234578
+ payload: "no-attest",
234579
+ attestation: null
234580
+ }));
234581
+ results.push({
234582
+ name: "missing_attestation",
234583
+ failed: miss.kind === "reject" || miss.kind === "throw",
234584
+ reason: miss.kind === "async" ? "async_unprobed" : miss.reason || miss.kind
234585
+ });
234586
+ const chJti = settle(() => callOp(wiring, "state_challenge", { target_id, environment }));
234587
+ if (chJti.kind !== "ok" || !chJti.result.jti) {
234588
+ results.push({ name: "mismatched_jti_scope_hash", failed: false, reason: "setup_no_issued_jti" });
234589
+ } else {
234590
+ const iss = issued(chJti.result);
234591
+ const bad = settle(() => callOp(wiring, "consume", {
234592
+ state_nonce: iss.nonce,
234593
+ jti: `${iss.jti}__NOT`,
234594
+ scope_hash: `${iss.scope_hash}__NOT`,
234595
+ target_id
234596
+ }));
234597
+ results.push({
234598
+ name: "mismatched_jti_scope_hash",
234599
+ failed: bad.kind === "reject" || bad.kind === "throw",
234600
+ reason: bad.kind === "async" ? "async_unprobed" : bad.reason || bad.kind
234601
+ });
234602
+ }
234603
+ const passed = results.filter((r) => r.failed !== true).map((r) => r.name);
234604
+ return {
234605
+ ok: passed.length === 0,
234606
+ results,
234607
+ passed,
234608
+ message: passed.length === 0 ? "all negative probes failed closed" : `negative probes accepted (must fail): ${passed.join(", ")}`
234609
+ };
234610
+ }
234611
+ module2.exports = {
234612
+ NEGATIVE_PROBES,
234613
+ runNegativeProbes,
234614
+ runPositiveRoundTrip
234615
+ };
234616
+ }
234617
+ });
234618
+
234619
+ // src/atomic-v2.js
234620
+ var require_atomic_v2 = __commonJS({
234621
+ "src/atomic-v2.js"(exports2, module2) {
234622
+ "use strict";
234623
+ var fs = require("fs");
234624
+ var path = require("path");
234625
+ var {
234626
+ ADAPTER_CONTRACT_VERSION,
234627
+ ADAPTER_OPERATIONS,
234628
+ ADAPTER_CONTRACT,
234629
+ REQUIRED_CAPABILITIES,
234630
+ checkContractVersion
234631
+ } = require_atomic_v2_contract();
234632
+ var { buildClaim, evidenceVerifies, normalizeBound, TARGET_BINDING_FIELDS } = require_atomic_v2_claim();
234633
+ var { runNegativeProbes, runPositiveRoundTrip, NEGATIVE_PROBES } = require_atomic_v2_probes();
234634
+ var CONFIG_REL = ".coderifts/atomic-v2.json";
234635
+ var WIRING_REL = ".coderifts/atomic-v2-wiring.js";
234636
+ var EXIT = Object.freeze({
234637
+ VERIFIED: 0,
234638
+ USAGE: 1,
234639
+ WIRING_REQUIRED: 2,
234640
+ VERIFICATION_FAILED: 3
234641
+ });
234642
+ var STATUS = Object.freeze({
234643
+ PROFILE_CONFIGURED: "PROFILE_CONFIGURED",
234644
+ WIRING_REQUIRED: "WIRING_REQUIRED",
234645
+ TARGET_ENFORCEMENT_VERIFIED: "TARGET_ENFORCEMENT_VERIFIED",
234646
+ VERIFICATION_FAILED: "VERIFICATION_FAILED",
234647
+ ATOMIC_V2_CONFIGURED: "ATOMIC_V2_CONFIGURED",
234648
+ ENFORCING_ATOMIC_V2: "ENFORCING_ATOMIC_V2"
234649
+ });
234650
+ function unconfiguredCapability(name) {
234651
+ const cap = String(name);
234652
+ const fn = function unconfiguredCapabilityPlaceholder() {
234653
+ const err = new Error(
234654
+ `unconfiguredCapability("${cap}"): fail-closed placeholder \u2014 this THROWS, it does not return success. Wire the capability before verify can pass.`
234655
+ );
234656
+ err.code = "UNCONFIGURED_CAPABILITY";
234657
+ err.capability = cap;
234658
+ throw err;
234659
+ };
234660
+ Object.defineProperty(fn, "unconfigured", { value: true, enumerable: true });
234661
+ Object.defineProperty(fn, "capability", { value: cap, enumerable: true });
234662
+ return fn;
234663
+ }
234664
+ function isUnconfiguredFn(fn) {
234665
+ return typeof fn === "function" && fn.unconfigured === true;
234666
+ }
234667
+ function configuredState(missing, opts = {}) {
234668
+ const list = Array.isArray(missing) ? [...missing] : [];
234669
+ const incomplete = list.length > 0;
234670
+ const targetVerified = opts.targetVerified === true && !incomplete;
234671
+ if (incomplete || !targetVerified) {
234672
+ return {
234673
+ profile: "ENFORCING_ATOMIC_V2",
234674
+ contract_version: ADAPTER_CONTRACT_VERSION,
234675
+ configuration_status: STATUS.PROFILE_CONFIGURED,
234676
+ enforcement_status: incomplete ? STATUS.WIRING_REQUIRED : opts.enforcement_status || STATUS.WIRING_REQUIRED,
234677
+ state: STATUS.ATOMIC_V2_CONFIGURED,
234678
+ atomic_v2_verified: false,
234679
+ missing_capabilities: list
234680
+ };
234681
+ }
234682
+ const bound = opts.bound || {};
234683
+ return {
234684
+ profile: "ENFORCING_ATOMIC_V2",
234685
+ contract_version: ADAPTER_CONTRACT_VERSION,
234686
+ configuration_status: STATUS.PROFILE_CONFIGURED,
234687
+ enforcement_status: STATUS.TARGET_ENFORCEMENT_VERIFIED,
234688
+ state: STATUS.ENFORCING_ATOMIC_V2,
234689
+ atomic_v2_verified: true,
234690
+ missing_capabilities: [],
234691
+ target_id: bound.target_id || null,
234692
+ environment: bound.environment || null,
234693
+ executor_identity: bound.executor_identity || null,
234694
+ operation: bound.operation || null,
234695
+ adapter_id: bound.adapter_id || null
234696
+ };
234697
+ }
234698
+ function refuseLie(doc, missing) {
234699
+ if (doc && doc.atomic_v2_verified === true && missing.length > 0) return true;
234700
+ if (doc && doc.state === STATUS.ENFORCING_ATOMIC_V2 && missing.length > 0) return true;
234701
+ if (doc && doc.enforcement_status === STATUS.TARGET_ENFORCEMENT_VERIFIED && missing.length > 0) {
234702
+ return true;
234703
+ }
234704
+ return false;
234705
+ }
234706
+ function wiringSource() {
234707
+ const caps = REQUIRED_CAPABILITIES.map((c) => ` ${c}: unconfiguredCapability(${JSON.stringify(c)}),`).join("\n");
234708
+ return `'use strict';
234709
+
234710
+ /**
234711
+ * ATOMIC_V2 wiring \u2014 generated by \`coderifts init --strict --atomic-v2\`.
234712
+ * Normative adapter-contract ${ADAPTER_CONTRACT_VERSION} (not a template).
234713
+ * Each operation is a FAIL-CLOSED placeholder. It THROWS. Replacing one with a
234714
+ * no-op that returns success is how incomplete wiring ships as verified.
234715
+ * Wire the real capability, then run \`coderifts verify atomic-v2 --target \u2026\`.
234716
+ */
234717
+ function unconfiguredCapability(name) {
234718
+ const cap = String(name);
234719
+ const fn = function unconfiguredCapabilityPlaceholder() {
234720
+ const err = new Error(
234721
+ 'unconfiguredCapability("' + cap + '"): fail-closed placeholder \u2014 '
234722
+ + 'this THROWS, it does not return success. Wire the capability before verify can pass.',
234723
+ );
234724
+ err.code = 'UNCONFIGURED_CAPABILITY';
234725
+ err.capability = cap;
234726
+ throw err;
234727
+ };
234728
+ Object.defineProperty(fn, 'unconfigured', { value: true, enumerable: true });
234729
+ Object.defineProperty(fn, 'capability', { value: cap, enumerable: true });
234730
+ return fn;
234731
+ }
234732
+
234733
+ module.exports = {
234734
+ contract_version: ${JSON.stringify(ADAPTER_CONTRACT_VERSION)},
234735
+ ${caps}
234736
+ };
234737
+ `;
234738
+ }
234739
+ function assertWiringFailClosed(wiringPath) {
234740
+ const wiring = loadWiring(path.resolve(wiringPath));
234741
+ const fn = wiring && wiring.conditional_write;
234742
+ if (typeof fn !== "function") {
234743
+ throw new Error("atomic-v2 wiring missing conditional_write");
234744
+ }
234745
+ let threw = false;
234746
+ try {
234747
+ fn();
234748
+ } catch (err) {
234749
+ threw = true;
234750
+ if (!(err && err.code === "UNCONFIGURED_CAPABILITY")) {
234751
+ throw new Error(
234752
+ `unconfiguredCapability("conditional_write") must throw UNCONFIGURED_CAPABILITY, got ${err && (err.code || err.message)}`
234753
+ );
234754
+ }
234755
+ }
234756
+ if (!threw) {
234757
+ throw new Error(
234758
+ 'unconfiguredCapability("conditional_write") must THROW at init, not return success'
234759
+ );
234760
+ }
234761
+ }
234762
+ function writeAtomicV2(outDir, deps = {}) {
234763
+ const writeFile = deps.writeFile || ((p, c) => {
234764
+ fs.mkdirSync(path.dirname(p), { recursive: true });
234765
+ fs.writeFileSync(p, c, "utf8");
234766
+ });
234767
+ const exists = deps.exists || fs.existsSync.bind(fs);
234768
+ const dryRun = !!deps.dryRun;
234769
+ const written = [];
234770
+ const skipped = [];
234771
+ const jsonPath = path.join(outDir, CONFIG_REL);
234772
+ const wiringPath = path.join(outDir, WIRING_REL);
234773
+ const doc = configuredState([...REQUIRED_CAPABILITIES]);
234774
+ if (doc.atomic_v2_verified !== false) {
234775
+ throw new Error("atomic-v2 init refused to write verified:true");
234776
+ }
234777
+ if (doc.state === STATUS.ENFORCING_ATOMIC_V2) {
234778
+ throw new Error("atomic-v2 init refused to write state ENFORCING_ATOMIC_V2 with incomplete wiring");
234779
+ }
234780
+ for (const [rel, body] of [[CONFIG_REL, `${JSON.stringify(doc, null, 2)}
234781
+ `], [WIRING_REL, wiringSource()]]) {
234782
+ const dest = path.join(outDir, rel);
234783
+ if (exists(dest) && !deps.force) {
234784
+ skipped.push(rel);
234785
+ continue;
234786
+ }
234787
+ if (!dryRun) writeFile(dest, body);
234788
+ written.push(rel);
234789
+ }
234790
+ if (!dryRun && written.includes(WIRING_REL) && fs.existsSync(wiringPath)) {
234791
+ assertWiringFailClosed(wiringPath);
234792
+ }
234793
+ return { written, skipped, configRel: CONFIG_REL, wiringRel: WIRING_REL, jsonPath, wiringPath, doc };
234794
+ }
234795
+ function loadWiring(wiringPath) {
234796
+ try {
234797
+ delete require.cache[require.resolve(wiringPath)];
234798
+ } catch (_) {
234799
+ }
234800
+ return require(wiringPath);
234801
+ }
234802
+ function isThenable(value) {
234803
+ return value != null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
234804
+ }
234805
+ function isPositiveProof(result, name) {
234806
+ return !!(result && typeof result === "object" && result.ok === true && result.capability === name);
234807
+ }
234808
+ function discoverCapabilities(wiring) {
234809
+ const discovery = {};
234810
+ const missing = [];
234811
+ for (const name of REQUIRED_CAPABILITIES) {
234812
+ const fn = wiring && wiring[name];
234813
+ const probe = probeCapability(typeof fn === "function" ? fn : void 0, name);
234814
+ discovery[name] = {
234815
+ wired: !probe.missing,
234816
+ reason: probe.reason,
234817
+ source: "machine_probe"
234818
+ };
234819
+ if (probe.missing) missing.push(name);
234820
+ }
234821
+ return { discovery, missing };
234822
+ }
234823
+ function probeCapability(fn, name) {
234824
+ if (typeof fn !== "function") {
234825
+ return { missing: true, reason: "not_a_function" };
234826
+ }
234827
+ if (isUnconfiguredFn(fn)) {
234828
+ return { missing: true, reason: "unconfiguredCapability" };
234829
+ }
234830
+ try {
234831
+ const result = fn({ probe: true, capability: name });
234832
+ if (isThenable(result)) {
234833
+ Promise.resolve(result).catch(() => {
234834
+ });
234835
+ return { missing: true, reason: "async_unprobed" };
234836
+ }
234837
+ if (!isPositiveProof(result, name)) {
234838
+ return { missing: true, reason: "no_positive_proof" };
234839
+ }
234840
+ return { missing: false, reason: null };
234841
+ } catch (err) {
234842
+ if (err && (err.code === "UNCONFIGURED_CAPABILITY" || /unconfiguredCapability\(/.test(String(err.message || "")))) {
234843
+ return { missing: true, reason: "unconfiguredCapability" };
234844
+ }
234845
+ return { missing: true, reason: "threw", error: err && err.message };
234846
+ }
234847
+ }
234848
+ function evaluateAtomicV2(outDir, boundInput = {}) {
234849
+ const jsonPath = path.join(outDir, CONFIG_REL);
234850
+ const wiringPath = path.join(outDir, WIRING_REL);
234851
+ const unverifiedClaim = () => buildClaim({
234852
+ ...boundInput,
234853
+ customer_target_verified: false,
234854
+ production_ready: false
234855
+ });
234856
+ if (!fs.existsSync(jsonPath)) {
234857
+ return {
234858
+ exitCode: EXIT.USAGE,
234859
+ code: "CONFIG_MISSING",
234860
+ message: `atomic-v2 config not found at ${CONFIG_REL} \u2014 run: coderifts init --strict --atomic-v2`,
234861
+ claim: unverifiedClaim()
234862
+ };
234863
+ }
234864
+ let doc;
234865
+ try {
234866
+ doc = JSON.parse(fs.readFileSync(jsonPath, "utf8"));
234867
+ } catch (err) {
234868
+ return { exitCode: EXIT.USAGE, code: "CONFIG_UNREADABLE", message: err.message, claim: unverifiedClaim() };
234869
+ }
234870
+ if (!fs.existsSync(wiringPath)) {
234871
+ return {
234872
+ exitCode: EXIT.WIRING_REQUIRED,
234873
+ code: STATUS.WIRING_REQUIRED,
234874
+ report: configuredState([...REQUIRED_CAPABILITIES]),
234875
+ claim: unverifiedClaim(),
234876
+ message: `wiring template missing (${WIRING_REL})`
234877
+ };
234878
+ }
234879
+ let wiring;
234880
+ try {
234881
+ wiring = loadWiring(path.resolve(wiringPath));
234882
+ } catch (err) {
234883
+ return {
234884
+ exitCode: EXIT.VERIFICATION_FAILED,
234885
+ code: STATUS.VERIFICATION_FAILED,
234886
+ message: `wiring module failed to load: ${err.message}`,
234887
+ claim: unverifiedClaim()
234888
+ };
234889
+ }
234890
+ const versionCheck = checkContractVersion(wiring);
234891
+ if (!versionCheck.ok) {
234892
+ return {
234893
+ exitCode: EXIT.VERIFICATION_FAILED,
234894
+ code: "CONTRACT_VERSION_MISMATCH",
234895
+ message: versionCheck.message,
234896
+ report: configuredState([...REQUIRED_CAPABILITIES], { enforcement_status: STATUS.VERIFICATION_FAILED }),
234897
+ claim: unverifiedClaim()
234898
+ };
234899
+ }
234900
+ const { discovery, missing } = discoverCapabilities(wiring);
234901
+ const probes = discovery;
234902
+ if (refuseLie(doc, missing)) {
234903
+ return {
234904
+ exitCode: EXIT.VERIFICATION_FAILED,
234905
+ code: STATUS.VERIFICATION_FAILED,
234906
+ message: "atomic-v2 document claims ENFORCING_ATOMIC_V2 / verified:true with incomplete wiring \u2014 refused",
234907
+ report: configuredState(missing, { enforcement_status: STATUS.VERIFICATION_FAILED }),
234908
+ discovery,
234909
+ probes,
234910
+ claim: unverifiedClaim()
234911
+ };
234912
+ }
234913
+ if (missing.length > 0) {
234914
+ return {
234915
+ exitCode: EXIT.WIRING_REQUIRED,
234916
+ code: STATUS.WIRING_REQUIRED,
234917
+ report: configuredState(missing),
234918
+ discovery,
234919
+ probes,
234920
+ claim: unverifiedClaim(),
234921
+ message: `ATOMIC_V2_CONFIGURED / WIRING_REQUIRED \u2014 missing: ${missing.join(", ")}`
234922
+ };
234923
+ }
234924
+ const binding = normalizeBound(boundInput);
234925
+ if (!binding.ok) {
234926
+ return {
234927
+ exitCode: EXIT.VERIFICATION_FAILED,
234928
+ code: "TARGET_BINDING_REQUIRED",
234929
+ message: `target-bound verification requires ${TARGET_BINDING_FIELDS.join(", ")} (missing ${binding.missing}); reference-executor success is not inherited`,
234930
+ report: configuredState([], { enforcement_status: STATUS.VERIFICATION_FAILED }),
234931
+ discovery,
234932
+ probes,
234933
+ claim: unverifiedClaim()
234934
+ };
234935
+ }
234936
+ const positive = runPositiveRoundTrip(wiring, binding.bound);
234937
+ if (!positive.ok) {
234938
+ return {
234939
+ exitCode: EXIT.VERIFICATION_FAILED,
234940
+ code: STATUS.VERIFICATION_FAILED,
234941
+ message: positive.message,
234942
+ report: configuredState([], { enforcement_status: STATUS.VERIFICATION_FAILED }),
234943
+ discovery,
234944
+ probes,
234945
+ positive,
234946
+ claim: unverifiedClaim()
234947
+ };
234948
+ }
234949
+ if (wiring.adapter_id != null && String(wiring.adapter_id) !== binding.bound.adapter_id) {
234950
+ return {
234951
+ exitCode: EXIT.VERIFICATION_FAILED,
234952
+ code: STATUS.VERIFICATION_FAILED,
234953
+ message: `adapter_id mismatch: wiring ${wiring.adapter_id} vs bound ${binding.bound.adapter_id}`,
234954
+ report: configuredState([], { enforcement_status: STATUS.VERIFICATION_FAILED }),
234955
+ discovery,
234956
+ probes,
234957
+ positive,
234958
+ claim: unverifiedClaim()
234959
+ };
234960
+ }
234961
+ if (positive.executor_identity != null && String(positive.executor_identity) !== binding.bound.executor_identity) {
234962
+ return {
234963
+ exitCode: EXIT.VERIFICATION_FAILED,
234964
+ code: STATUS.VERIFICATION_FAILED,
234965
+ message: `executor_identity mismatch: adapter ${positive.executor_identity} vs bound ${binding.bound.executor_identity}`,
234966
+ report: configuredState([], { enforcement_status: STATUS.VERIFICATION_FAILED }),
234967
+ discovery,
234968
+ probes,
234969
+ positive,
234970
+ claim: unverifiedClaim()
234971
+ };
234972
+ }
234973
+ const negatives = runNegativeProbes(wiring, binding.bound);
234974
+ if (!negatives.ok) {
234975
+ return {
234976
+ exitCode: EXIT.VERIFICATION_FAILED,
234977
+ code: STATUS.VERIFICATION_FAILED,
234978
+ message: negatives.message,
234979
+ report: configuredState([], { enforcement_status: STATUS.VERIFICATION_FAILED }),
234980
+ discovery,
234981
+ probes,
234982
+ positive,
234983
+ negatives,
234984
+ claim: unverifiedClaim()
234985
+ };
234986
+ }
234987
+ const claim = buildClaim({
234988
+ customer_target_verified: true,
234989
+ production_ready: true,
234990
+ ...binding.bound
234991
+ });
234992
+ if (!evidenceVerifies(claim, binding.bound)) {
234993
+ return {
234994
+ exitCode: EXIT.VERIFICATION_FAILED,
234995
+ code: STATUS.VERIFICATION_FAILED,
234996
+ message: "claim does not bind the verified target",
234997
+ report: configuredState([], { enforcement_status: STATUS.VERIFICATION_FAILED }),
234998
+ discovery,
234999
+ probes,
235000
+ claim: unverifiedClaim()
235001
+ };
235002
+ }
235003
+ const report = configuredState([], { targetVerified: true, bound: binding.bound });
235004
+ return {
235005
+ exitCode: EXIT.VERIFIED,
235006
+ code: STATUS.TARGET_ENFORCEMENT_VERIFIED,
235007
+ report,
235008
+ discovery,
235009
+ probes,
235010
+ positive,
235011
+ negatives,
235012
+ claim,
235013
+ message: `TARGET_ENFORCEMENT_VERIFIED target_id=${claim.target_id} adapter_id=${claim.adapter_id}`
235014
+ };
235015
+ }
235016
+ module2.exports = {
235017
+ CONFIG_REL,
235018
+ WIRING_REL,
235019
+ REQUIRED_CAPABILITIES,
235020
+ ADAPTER_OPERATIONS,
235021
+ ADAPTER_CONTRACT_VERSION,
235022
+ ADAPTER_CONTRACT,
235023
+ EXIT,
235024
+ STATUS,
235025
+ unconfiguredCapability,
235026
+ isUnconfiguredFn,
235027
+ configuredState,
235028
+ refuseLie,
235029
+ writeAtomicV2,
235030
+ evaluateAtomicV2,
235031
+ wiringSource,
235032
+ assertWiringFailClosed,
235033
+ isPositiveProof,
235034
+ probeCapability,
235035
+ discoverCapabilities,
235036
+ checkContractVersion,
235037
+ buildClaim,
235038
+ evidenceVerifies,
235039
+ normalizeBound,
235040
+ TARGET_BINDING_FIELDS,
235041
+ NEGATIVE_PROBES,
235042
+ runNegativeProbes,
235043
+ runPositiveRoundTrip
235044
+ };
235045
+ }
235046
+ });
235047
+
233878
235048
  // src/commands/init-agents.js
233879
235049
  var require_init_agents = __commonJS({
233880
235050
  "src/commands/init-agents.js"(exports2, module2) {
@@ -233897,8 +235067,9 @@ var require_init_agents = __commonJS({
233897
235067
  writeContractGateWorkflow,
233898
235068
  workflowPresent
233899
235069
  } = require_contract_gate_workflow();
235070
+ var { writeAtomicV2, CONFIG_REL, WIRING_REL } = require_atomic_v2();
233900
235071
  if (process.env.NO_COLOR) chalk.level = 0;
233901
- var USAGE = `Usage: coderifts init --agents [--hosts=claude,cursor,copilot,all] [--no-hook] [--no-workflow] [--strict] [--dry-run] [--check] [--out <dir>]
235072
+ var USAGE = `Usage: coderifts init --agents [--hosts=claude,cursor,copilot,all] [--no-hook] [--no-workflow] [--strict] [--atomic-v2] [--dry-run] [--check] [--out <dir>]
233902
235073
 
233903
235074
  Wire this repository for governed agent work in ONE command:
233904
235075
  1. repo-level MCP config (per host: .mcp.json / .cursor/mcp.json / .vscode/mcp.json)
@@ -233909,7 +235080,8 @@ var require_init_agents = __commonJS({
233909
235080
  --hosts <list> claude, cursor, copilot, or all (default: all)
233910
235081
  --no-hook Skip host hook install
233911
235082
  --no-workflow Skip writing the CI workflow
233912
- --strict STRICT workflow: require-verified-monitoring: true (default template stays false)
235083
+ --strict STRICT workflow: require-verified-monitoring + require-grant (cr.exec.v2 primary; v1 legacy)
235084
+ --atomic-v2 Write ENFORCING_ATOMIC_V2 config + fail-closed wiring placeholders (implies --agents --strict)
233913
235085
  --dry-run Print the plan without writing
233914
235086
  --check Report which of the four pieces are present (no write)
233915
235087
  --out <dir> Target directory (default: cwd)
@@ -233970,9 +235142,9 @@ ${USAGE}`
233970
235142
  return { hosts, allRules: false };
233971
235143
  }
233972
235144
  function agentFlagsRequireAgents(options = {}) {
233973
- return !!(options.check || options.dryRun || options.out || options.hosts != null && String(options.hosts) !== "all" || options.hook === false || options.workflow === false || options.noHook === true || options.noWorkflow === true || options.strict === true);
235145
+ return !!(options.check || options.dryRun || options.out || options.hosts != null && String(options.hosts) !== "all" || options.hook === false || options.workflow === false || options.noHook === true || options.noWorkflow === true || options.strict === true || options.atomicV2 === true);
233974
235146
  }
233975
- var AGENT_FLAGS_REQUIRE_AGENTS = "Error: --check/--dry-run/--out/--hosts/--no-hook/--no-workflow/--strict require --agents";
235147
+ var AGENT_FLAGS_REQUIRE_AGENTS = "Error: --check/--dry-run/--out/--hosts/--no-hook/--no-workflow/--strict/--atomic-v2 require --agents";
233976
235148
  var AGENTS_NO_TEMPLATE = "Error: init --agents does not take a template. Did you mean `coderifts init --agents` (not `coderifts init agent`)?";
233977
235149
  function rulePathsForHosts(hosts, allRules) {
233978
235150
  const out = [SHARED_RULE];
@@ -234068,6 +235240,15 @@ ${USAGE}`
234068
235240
  }
234069
235241
  const workflowWanted = wantWorkflow(options);
234070
235242
  const wfPresent = workflowWanted && workflowPresent(outDir, fsDeps);
235243
+ const atomicWanted = options.atomicV2 === true;
235244
+ const atomicMissing = [];
235245
+ const atomicPresent = [];
235246
+ if (atomicWanted) {
235247
+ for (const rel of [CONFIG_REL, WIRING_REL]) {
235248
+ if (fsDeps.exists(path.join(outDir, rel))) atomicPresent.push(rel);
235249
+ else atomicMissing.push(rel);
235250
+ }
235251
+ }
234071
235252
  const pieces = {
234072
235253
  mcp: { present: mcpPresent, missing: mcpMissing },
234073
235254
  rules: { present: rulesPresent, missing: rulesMissing },
@@ -234080,9 +235261,14 @@ ${USAGE}`
234080
235261
  wanted: workflowWanted,
234081
235262
  present: wfPresent,
234082
235263
  missing: workflowWanted && !wfPresent ? [WORKFLOW_REL] : []
235264
+ },
235265
+ atomicV2: {
235266
+ wanted: atomicWanted,
235267
+ present: atomicPresent,
235268
+ missing: atomicMissing
234083
235269
  }
234084
235270
  };
234085
- const missingCount = mcpMissing.length + rulesMissing.length + hooksMissing.length + (workflowWanted && !wfPresent ? 1 : 0);
235271
+ const missingCount = mcpMissing.length + rulesMissing.length + hooksMissing.length + (workflowWanted && !wfPresent ? 1 : 0) + atomicMissing.length;
234086
235272
  return {
234087
235273
  exitCode: missingCount === 0 ? 0 : 1,
234088
235274
  pieces,
@@ -234115,8 +235301,13 @@ ${USAGE}`
234115
235301
  } else {
234116
235302
  log(pieces.workflow.present ? ` CI workflow: present (${WORKFLOW_REL})` : ` CI workflow: missing (${WORKFLOW_REL})`);
234117
235303
  }
235304
+ if (pieces.atomicV2 && pieces.atomicV2.wanted) {
235305
+ const st = pieces.atomicV2.missing.length === 0 ? "present" : "missing";
235306
+ const detail = pieces.atomicV2.missing.length === 0 ? pieces.atomicV2.present.join(", ") : pieces.atomicV2.missing.join(", ");
235307
+ log(` ATOMIC_V2: ${st} (${detail})`);
235308
+ }
234118
235309
  log("");
234119
- if (allPresent) log(chalk.green(" All four pieces present."));
235310
+ if (allPresent) log(chalk.green(pieces.atomicV2 && pieces.atomicV2.wanted ? " All requested pieces present." : " All four pieces present."));
234120
235311
  else log(chalk.yellow(" Incomplete \u2014 run: coderifts init --agents"));
234121
235312
  }
234122
235313
  function runInitAgents(options = {}, deps = {}) {
@@ -234240,9 +235431,28 @@ ${USAGE}`
234240
235431
  section: "workflow",
234241
235432
  action: r.action,
234242
235433
  relPath: r.relPath,
234243
- note: r.action === "create" ? options.strict ? `${GATE_ACTION} (STRICT require-verified-monitoring)` : GATE_ACTION : r.reason
235434
+ note: r.action === "create" ? options.strict ? `${GATE_ACTION} (STRICT require-verified-monitoring + require-grant; cr.exec.v2)` : GATE_ACTION : r.reason
234244
235435
  });
234245
235436
  }
235437
+ if (options.atomicV2) {
235438
+ const av = writeAtomicV2(outDir, { ...fsDeps, dryRun });
235439
+ for (const rel of av.written) {
235440
+ items.push({
235441
+ section: "atomic-v2",
235442
+ action: "create",
235443
+ relPath: rel,
235444
+ note: rel === CONFIG_REL ? "PROFILE_CONFIGURED / WIRING_REQUIRED (atomic_v2_verified:false)" : "fail-closed unconfiguredCapability placeholders"
235445
+ });
235446
+ }
235447
+ for (const rel of av.skipped) {
235448
+ items.push({
235449
+ section: "atomic-v2",
235450
+ action: "skip",
235451
+ relPath: rel,
235452
+ note: "exists; installer does not overwrite"
235453
+ });
235454
+ }
235455
+ }
234246
235456
  const created = items.filter((i) => i.action === "create").length;
234247
235457
  const merged = items.filter((i) => i.action === "merge").length;
234248
235458
  const skipped = items.filter((i) => i.action === "skip").length;
@@ -234287,7 +235497,8 @@ ${USAGE}`
234287
235497
  ["mcp", "MCP config"],
234288
235498
  ["rules", "Agent rules"],
234289
235499
  ["hooks", "Host hooks"],
234290
- ["workflow", "CI workflow"]
235500
+ ["workflow", "CI workflow"],
235501
+ ["atomic-v2", "ATOMIC_V2"]
234291
235502
  ];
234292
235503
  for (const [key, title] of sections) {
234293
235504
  lines.push(` ${title}`);
@@ -261428,7 +262639,7 @@ var require_enforce_check = __commonJS({
261428
262639
  "",
261429
262640
  "Query the provider (GitHub) and local workflow files. Report, per layer:",
261430
262641
  " VERIFIED / NOT_VERIFIED / UNVERIFIABLE(reason).",
261431
- "inescapable_deploy is true only when every layer is VERIFIED.",
262642
+ "inescapable_deploy is true only when every layer is VERIFIED and MERGEGATE_ENFORCE is observably true.",
261432
262643
  "",
261433
262644
  "Auth: GITHUB_TOKEN (or GH_TOKEN). Never prints token values.",
261434
262645
  "The CodeRifts GitHub App installation cannot query branch protection",
@@ -261585,7 +262796,8 @@ var require_enforce_check = __commonJS({
261585
262796
  // roadmap 1052a — the ruleset surface, which reads without a credential and can establish
261586
262797
  // required_check where classic branch protection is unreadable.
261587
262798
  rulesetsRead,
261588
- branch
262799
+ branch,
262800
+ mergegateEnforceObserved: options.mergegateEnforceObserved
261589
262801
  });
261590
262802
  const report = {
261591
262803
  command: "enforce --check",
@@ -261693,7 +262905,7 @@ var require_enforce = __commonJS({
261693
262905
  "setup commands (setup-required-check, hook install, deploy-gate guidance).",
261694
262906
  "",
261695
262907
  "--check: query GitHub + local workflows and report VERIFIED / NOT_VERIFIED /",
261696
- "UNVERIFIABLE per layer. inescapable_deploy is true only when every layer is VERIFIED.",
262908
+ "UNVERIFIABLE per layer. inescapable_deploy is true only when every layer is VERIFIED and MERGEGATE_ENFORCE is observably true.",
261697
262909
  "Does not use the CodeRifts API key. Auth: GITHUB_TOKEN. Read-only.",
261698
262910
  "",
261699
262911
  "DRY-RUN BY DEFAULT \u2014 without --apply, prints what WOULD run and mutates NOTHING.",
@@ -263008,6 +264220,74 @@ Unparseable stdin denies (fail-closed).
263008
264220
  }
263009
264221
  });
263010
264222
 
264223
+ // src/commands/verify-atomic-v2.js
264224
+ var require_verify_atomic_v2 = __commonJS({
264225
+ "src/commands/verify-atomic-v2.js"(exports2, module2) {
264226
+ "use strict";
264227
+ var path = require("path");
264228
+ var chalk = require_source();
264229
+ var { evaluateAtomicV2, EXIT, STATUS } = require_atomic_v2();
264230
+ if (process.env.NO_COLOR) chalk.level = 0;
264231
+ var USAGE = `Usage: coderifts verify atomic-v2 [--out <dir>] [--json]
264232
+ [--target <id>] [--environment <env>] [--executor-identity <id>]
264233
+ [--operation <op>] [--adapter-id <id>]
264234
+
264235
+ Exit 0 TARGET_ENFORCEMENT_VERIFIED (THIS named target fully verified)
264236
+ Exit 2 WIRING_REQUIRED (config installed, placeholders still throw)
264237
+ Exit 3 VERIFICATION_FAILED (wiring present but verification failed / document lied / negatives accepted / target unbound)
264238
+ Exit 1 usage or missing config
264239
+
264240
+ Target-bound: --target --environment --executor-identity --operation --adapter-id.
264241
+ A reference-executor success is not inherited by a different target.
264242
+ `;
264243
+ function runVerifyAtomicV2(options = {}, deps = {}) {
264244
+ const log = deps.log || console.log.bind(console);
264245
+ const logErr = deps.logErr || console.error.bind(console);
264246
+ const doExit = deps.exit !== false;
264247
+ const outDir = options.out ? path.resolve(String(options.out)) : deps.cwd || process.cwd();
264248
+ const result = evaluateAtomicV2(outDir, {
264249
+ target_id: options.target,
264250
+ environment: options.environment,
264251
+ executor_identity: options.executorIdentity,
264252
+ operation: options.operation,
264253
+ adapter_id: options.adapterId
264254
+ });
264255
+ const payload = {
264256
+ exitCode: result.exitCode,
264257
+ code: result.code,
264258
+ message: result.message,
264259
+ report: result.report || null,
264260
+ discovery: result.discovery || null,
264261
+ claim: result.claim || null,
264262
+ negatives: result.negatives || null
264263
+ };
264264
+ if (options.json) {
264265
+ log(JSON.stringify(payload, null, 2));
264266
+ } else {
264267
+ const line = result.message || result.code;
264268
+ if (result.exitCode === EXIT.VERIFIED) log(chalk.green(line));
264269
+ else if (result.exitCode === EXIT.WIRING_REQUIRED) log(chalk.yellow(line));
264270
+ else logErr(chalk.red(line));
264271
+ if (result.report) {
264272
+ log(` configuration_status: ${result.report.configuration_status}`);
264273
+ log(` enforcement_status: ${result.report.enforcement_status}`);
264274
+ log(` state: ${result.report.state}`);
264275
+ log(` atomic_v2_verified: ${result.report.atomic_v2_verified}`);
264276
+ log(` missing_capabilities: ${JSON.stringify(result.report.missing_capabilities)}`);
264277
+ }
264278
+ if (result.claim) {
264279
+ log(` customer_target_verified: ${result.claim.customer_target_verified}`);
264280
+ log(` production_ready: ${result.claim.production_ready}`);
264281
+ if (result.claim.target_id) log(` target_id: ${result.claim.target_id}`);
264282
+ }
264283
+ }
264284
+ if (doExit) process.exit(result.exitCode);
264285
+ return result;
264286
+ }
264287
+ module2.exports = { runVerifyAtomicV2, USAGE, EXIT, STATUS };
264288
+ }
264289
+ });
264290
+
263011
264291
  // corpus/vectors-mcp-fpfn.json
263012
264292
  var require_vectors_mcp_fpfn = __commonJS({
263013
264293
  "corpus/vectors-mcp-fpfn.json"(exports2, module2) {
@@ -264666,6 +265946,10 @@ program.command("deploy-gate").description("Gate a deploy on the current { envir
264666
265946
  const { runDeployGate } = require_deploy_gate2();
264667
265947
  await runDeployGate(options);
264668
265948
  });
265949
+ program.command("doctor").description("Would an agent select CodeRifts for a contract change? Structural check (no key), or the 15-fixture benchmark on your own model.").option("--tools <file>", "Your host's tools/list response (array, { tools }, or { result: { tools } })").option("--model <id>", "TIER 1: run the fixtures through this model using YOUR key from the environment").option("--mock", "TIER 1 dry run: a deterministic scripted model. Measures the script, not a model.").action(async (options) => {
265950
+ const { runDoctor } = require_doctor2();
265951
+ await runDoctor(options);
265952
+ });
264669
265953
  program.command("publish-gate").description("Gate npm publish on contract-artifact preflight (before=git baseline, after=working tree)").option("--spec <path>", "Contract artifact path (default: git config coderifts.specPath or api/openapi.yaml)").option("--json", "Machine-readable JSON result").action(async (options) => {
264670
265954
  const { runPublishGate } = require_publish_gate();
264671
265955
  const result = await runPublishGate(options);
@@ -264714,14 +265998,14 @@ program.command("grant").description("Execution-grant helpers").command("publish
264714
265998
  }
264715
265999
  process.stdout.write(result.text + "\n");
264716
266000
  });
264717
- program.command("init [template]").description("Generate a .coderifts.yml from a policy template, or wire governed agent work (--agents)").option("--agents", "Wire this repo for governed agent work (MCP config, rule files, host hook, CI gate)").option("--hosts <list>", "With --agents: claude, cursor, copilot, or all (default: all)", "all").option("--no-hook", "With --agents: skip host hook install").option("--no-workflow", "With --agents: skip writing .github/workflows/coderifts.yml").option("--strict", "With --agents: STRICT workflow (require-verified-monitoring: true)").option("--dry-run", "With --agents: print the plan without writing").option("--check", "With --agents: report which of the four pieces are present (no write)").option("--out <dir>", "With --agents: target directory (default: cwd)").action(async (template, options) => {
266001
+ program.command("init [template]").description("Generate a .coderifts.yml from a policy template, or wire governed agent work (--agents)").option("--agents", "Wire this repo for governed agent work (MCP config, rule files, host hook, CI gate)").option("--hosts <list>", "With --agents: claude, cursor, copilot, or all (default: all)", "all").option("--no-hook", "With --agents: skip host hook install").option("--no-workflow", "With --agents: skip writing .github/workflows/coderifts.yml").option("--strict", "With --agents: STRICT workflow (require-verified-monitoring + require-grant; cr.exec.v2 primary)").option("--atomic-v2", "Write ENFORCING_ATOMIC_V2 config + fail-closed wiring (implies --agents --strict)").option("--dry-run", "With --agents: print the plan without writing").option("--check", "With --agents: report which of the four pieces are present (no write)").option("--out <dir>", "With --agents: target directory (default: cwd)").action(async (template, options) => {
264718
266002
  const {
264719
266003
  runInitAgents,
264720
266004
  agentFlagsRequireAgents,
264721
266005
  AGENT_FLAGS_REQUIRE_AGENTS,
264722
266006
  AGENTS_NO_TEMPLATE
264723
266007
  } = require_init_agents();
264724
- if (options.agents) {
266008
+ if (options.agents || options.atomicV2) {
264725
266009
  if (template) {
264726
266010
  console.error(AGENTS_NO_TEMPLATE);
264727
266011
  process.exitCode = 1;
@@ -264734,7 +266018,8 @@ program.command("init [template]").description("Generate a .coderifts.yml from a
264734
266018
  dryRun: !!options.dryRun,
264735
266019
  check: !!options.check,
264736
266020
  out: options.out,
264737
- strict: !!options.strict
266021
+ strict: !!options.strict || !!options.atomicV2,
266022
+ atomicV2: !!options.atomicV2
264738
266023
  });
264739
266024
  if (result && typeof result.exitCode === "number") {
264740
266025
  process.exitCode = result.exitCode;
@@ -264881,6 +266166,23 @@ hookCmd.command("status").description("Show whether the CodeRifts pre-push hook
264881
266166
  status();
264882
266167
  });
264883
266168
  var corpusCmd = program.command("corpus").description("Reproduce the CodeRifts accuracy proof matrix (MCP always; OpenAPI needs oasdiff)");
266169
+ program.command("verify <target>").description("Verify an installed profile. Target: atomic-v2. Exit 0 = TARGET_ENFORCEMENT_VERIFIED (named target); 2 = WIRING_REQUIRED; 3 = VERIFICATION_FAILED; 1 = usage.").option("--out <dir>", "Target directory (default: cwd)").option("--json", "Print the structured status JSON").option("--target <id>", "Bind verification to this target_id").option("--environment <env>", "Bind verification to this environment").option("--executor-identity <id>", "Bind verification to this executor identity").option("--operation <op>", "Bind verification to this operation").option("--adapter-id <id>", "Bind verification to this adapter_id").action((target, options) => {
266170
+ if (String(target) !== "atomic-v2") {
266171
+ console.error(`verify: unknown target "${target}" (use atomic-v2)`);
266172
+ process.exitCode = 1;
266173
+ return;
266174
+ }
266175
+ const { runVerifyAtomicV2 } = require_verify_atomic_v2();
266176
+ runVerifyAtomicV2({
266177
+ out: options.out,
266178
+ json: !!options.json,
266179
+ target: options.target,
266180
+ environment: options.environment,
266181
+ executorIdentity: options.executorIdentity,
266182
+ operation: options.operation,
266183
+ adapterId: options.adapterId
266184
+ });
266185
+ });
264884
266186
  corpusCmd.command("verify", { isDefault: true }).description("Evaluate every trust vector and print the proof matrix (exit 1 on any FAIL)").option("--json", "Machine-readable output: { vectors, summary }").action((options) => {
264885
266187
  const { corpusVerify } = require_corpus();
264886
266188
  corpusVerify(options);