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/CHANGELOG.md +19 -0
- package/README.md +23 -8
- package/bin/coderifts.js +46 -3
- package/dist/.build-source-sha +2 -2
- package/dist/cli.js +1365 -63
- package/package.json +4 -3
- package/scripts/check-packed-install.js +91 -0
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.
|
|
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.
|
|
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
|
-
|
|
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 {
|
|
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
|
-
//
|
|
227602
|
-
// (
|
|
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
|
|
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
|
-
|
|
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(
|
|
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
|
|
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).
|
|
231301
|
-
# cr.exec.
|
|
231302
|
-
# OFF HERE, ON IN STRICT, and the difference is deliberate
|
|
231303
|
-
# above. Turning it on BLOCKS every PR that changes a
|
|
231304
|
-
# no valid grant (\`grant_not_supplied\`), so it
|
|
231305
|
-
# one per change set before it helps. This
|
|
231306
|
-
#
|
|
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
|
|
231372
|
-
#
|
|
231373
|
-
#
|
|
231374
|
-
#
|
|
231375
|
-
#
|
|
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 =
|
|
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} (${
|
|
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 ${
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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);
|