coderifts 5.0.0 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +55 -25
- package/package.json +2 -2
- package/scripts/assert-guard-major.js +160 -4
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: "5.0.
|
|
3031
|
+
version: "5.0.1",
|
|
3032
3032
|
description: "Detect breaking API changes from the command line. Works locally or with the CodeRifts cloud API.",
|
|
3033
3033
|
author: "CodeRifts <hello@coderifts.com>",
|
|
3034
3034
|
license: "MIT",
|
|
@@ -3073,7 +3073,7 @@ var require_package = __commonJS({
|
|
|
3073
3073
|
test: "node --test test/*.test.js"
|
|
3074
3074
|
},
|
|
3075
3075
|
dependencies: {
|
|
3076
|
-
"@coderifts/agent-guard": "^
|
|
3076
|
+
"@coderifts/agent-guard": "^12.0.0",
|
|
3077
3077
|
chalk: "^4.1.2",
|
|
3078
3078
|
"cli-table3": "^0.6.4",
|
|
3079
3079
|
commander: "^12.0.0",
|
|
@@ -66357,7 +66357,7 @@ var require_execution_time_fingerprint = __commonJS({
|
|
|
66357
66357
|
exports2.authorizedFingerprintFromEnvelope = authorizedFingerprintFromEnvelope;
|
|
66358
66358
|
exports2.checkExecutionTimeFingerprint = checkExecutionTimeFingerprint;
|
|
66359
66359
|
var node_crypto_1 = require("node:crypto");
|
|
66360
|
-
var
|
|
66360
|
+
var US = "";
|
|
66361
66361
|
var BUNDLE_FP_DOMAIN = "crbundle.v1";
|
|
66362
66362
|
function sha256hex(s) {
|
|
66363
66363
|
return (0, node_crypto_1.createHash)("sha256").update(s, "utf8").digest("hex");
|
|
@@ -66372,13 +66372,13 @@ var require_execution_time_fingerprint = __commonJS({
|
|
|
66372
66372
|
}
|
|
66373
66373
|
function computeCanonicalBundleFingerprint(artifacts, context) {
|
|
66374
66374
|
const sorted = artifacts.slice().sort((x, y) => {
|
|
66375
|
-
const kx = `${x.type}${
|
|
66376
|
-
const ky = `${y.type}${
|
|
66375
|
+
const kx = `${x.type}${US}${x.id}`;
|
|
66376
|
+
const ky = `${y.type}${US}${y.id}`;
|
|
66377
66377
|
return kx < ky ? -1 : kx > ky ? 1 : 0;
|
|
66378
66378
|
});
|
|
66379
66379
|
const parts = [BUNDLE_FP_DOMAIN, String(artifacts.length)];
|
|
66380
66380
|
for (const a of sorted) {
|
|
66381
|
-
parts.push([a.type, a.id, sha256hex(specStr(a.before)), sha256hex(specStr(a.after))].join(
|
|
66381
|
+
parts.push([a.type, a.id, sha256hex(specStr(a.before)), sha256hex(specStr(a.after))].join(US));
|
|
66382
66382
|
}
|
|
66383
66383
|
const ctx = context || {};
|
|
66384
66384
|
parts.push([
|
|
@@ -66388,8 +66388,8 @@ var require_execution_time_fingerprint = __commonJS({
|
|
|
66388
66388
|
scalar(ctx.branch),
|
|
66389
66389
|
scalar(ctx.pull_request),
|
|
66390
66390
|
scalar(ctx.policy_profile)
|
|
66391
|
-
].join(
|
|
66392
|
-
return `sha256:${sha256hex(parts.join(
|
|
66391
|
+
].join(US));
|
|
66392
|
+
return `sha256:${sha256hex(parts.join(US))}`;
|
|
66393
66393
|
}
|
|
66394
66394
|
exports2.EXECUTION_TIME_FP_REASONS = Object.freeze({
|
|
66395
66395
|
MATCH: "match",
|
|
@@ -66485,7 +66485,7 @@ var require_enforcement_gate = __commonJS({
|
|
|
66485
66485
|
function isAction(v) {
|
|
66486
66486
|
return v === "CONTINUE" || v === "CONTINUE_WITH_MONITORING" || v === "REQUEST_APPROVAL" || v === "STOP";
|
|
66487
66487
|
}
|
|
66488
|
-
var
|
|
66488
|
+
var US = "";
|
|
66489
66489
|
function sha256hex(s) {
|
|
66490
66490
|
return (0, node_crypto_1.createHash)("sha256").update(s).digest("hex");
|
|
66491
66491
|
}
|
|
@@ -66493,7 +66493,7 @@ var require_enforcement_gate = __commonJS({
|
|
|
66493
66493
|
return v == null ? "" : typeof v === "string" ? v : JSON.stringify(v);
|
|
66494
66494
|
}
|
|
66495
66495
|
function computeArtifactDigest(artifacts) {
|
|
66496
|
-
const preimage = artifacts.slice().sort((a, b) => `${a.type}${
|
|
66496
|
+
const preimage = artifacts.slice().sort((a, b) => `${a.type}${US}${a.id}` < `${b.type}${US}${b.id}` ? -1 : 1).map((a) => `${sha256hex(specStr(a.before))}${sha256hex(specStr(a.after))}`).join(US);
|
|
66497
66497
|
return `sha256:${sha256hex(preimage)}`;
|
|
66498
66498
|
}
|
|
66499
66499
|
function computeBundleFingerprint(artifacts, context) {
|
|
@@ -66699,7 +66699,8 @@ var require_execution_proof = __commonJS({
|
|
|
66699
66699
|
if (input.preflighted !== true || input.receiptVerified !== true) {
|
|
66700
66700
|
throw new Error("@coderifts/agent-guard: enforced:true without receiptVerified+preflighted (runtime invariant)");
|
|
66701
66701
|
}
|
|
66702
|
-
|
|
66702
|
+
const mutating = input.mutating === void 0 ? input.writeStyle === true : input.mutating === true;
|
|
66703
|
+
if (input.requireConditionalWrite === true && mutating) {
|
|
66703
66704
|
if (input.conditionalWrite !== true) {
|
|
66704
66705
|
throw new Error("@coderifts/agent-guard: enforced:true without conditional_write:true under requireConditionalWrite (runtime invariant)");
|
|
66705
66706
|
}
|
|
@@ -66763,6 +66764,7 @@ var require_execution_proof = __commonJS({
|
|
|
66763
66764
|
receiptVerified,
|
|
66764
66765
|
requireConditionalWrite: cwb?.require_conditional_write,
|
|
66765
66766
|
writeStyle: cwb?.write_style,
|
|
66767
|
+
mutating: cwb?.mutating,
|
|
66766
66768
|
conditionalWrite: cwb?.conditional_write
|
|
66767
66769
|
});
|
|
66768
66770
|
const env = envelopeOf(input.verdict);
|
|
@@ -66854,6 +66856,7 @@ var require_freshness = __commonJS({
|
|
|
66854
66856
|
exports2.assessWriteStylePrior = assessWriteStylePrior;
|
|
66855
66857
|
exports2.freshnessAllowsEnforce = freshnessAllowsEnforce;
|
|
66856
66858
|
exports2.isWriteStyleCall = isWriteStyleCall;
|
|
66859
|
+
exports2.isMutatingCall = isMutatingCall;
|
|
66857
66860
|
exports2.artifactIdsForResolve = artifactIdsForResolve;
|
|
66858
66861
|
exports2.collectFreshnessCallContext = collectFreshnessCallContext;
|
|
66859
66862
|
exports2.buildFreshnessBasis = buildFreshnessBasis;
|
|
@@ -66987,6 +66990,24 @@ var require_freshness = __commonJS({
|
|
|
66987
66990
|
}
|
|
66988
66991
|
return false;
|
|
66989
66992
|
}
|
|
66993
|
+
function isMutatingCall(call) {
|
|
66994
|
+
const arts = call.artifacts;
|
|
66995
|
+
if (Array.isArray(arts)) {
|
|
66996
|
+
for (const a of arts) {
|
|
66997
|
+
if (a && typeof a.after === "string" && a.after.length > 0)
|
|
66998
|
+
return true;
|
|
66999
|
+
}
|
|
67000
|
+
}
|
|
67001
|
+
const args = call.arguments && typeof call.arguments === "object" ? call.arguments : {};
|
|
67002
|
+
for (const k of ["contents", "content", "new_string", "old_string", "patch"]) {
|
|
67003
|
+
const v = args[k];
|
|
67004
|
+
if (typeof v === "string" && v.length > 0)
|
|
67005
|
+
return true;
|
|
67006
|
+
}
|
|
67007
|
+
if (Array.isArray(args.edits) && args.edits.length > 0)
|
|
67008
|
+
return true;
|
|
67009
|
+
return false;
|
|
67010
|
+
}
|
|
66990
67011
|
function artifactIdsForResolve(call) {
|
|
66991
67012
|
const ids = [];
|
|
66992
67013
|
if (Array.isArray(call.artifacts)) {
|
|
@@ -67159,12 +67180,14 @@ var require_conditional_write = __commonJS({
|
|
|
67159
67180
|
function buildConditionalWriteBasis(input) {
|
|
67160
67181
|
const require_conditional_write2 = input.requireConditionalWrite === true;
|
|
67161
67182
|
const write_style = input.writeStyle === true;
|
|
67183
|
+
const mutating = input.mutating === void 0 ? write_style : input.mutating === true;
|
|
67162
67184
|
const ctx = input.ctx && typeof input.ctx === "object" ? input.ctx : {};
|
|
67163
67185
|
const conditional_write = normalizeReport(ctx.conditional_write);
|
|
67164
67186
|
const basis = {
|
|
67165
67187
|
conditional_write,
|
|
67166
67188
|
require_conditional_write: require_conditional_write2,
|
|
67167
|
-
write_style
|
|
67189
|
+
write_style,
|
|
67190
|
+
mutating
|
|
67168
67191
|
};
|
|
67169
67192
|
if (conditional_write === true) {
|
|
67170
67193
|
if (typeof ctx.conditioned_on_token === "string") {
|
|
@@ -67175,7 +67198,7 @@ var require_conditional_write = __commonJS({
|
|
|
67175
67198
|
basis.conditioned_on_token = null;
|
|
67176
67199
|
}
|
|
67177
67200
|
}
|
|
67178
|
-
if (
|
|
67201
|
+
if (mutating && require_conditional_write2 && conditional_write !== true) {
|
|
67179
67202
|
return { basis, blockCause: "CONDITIONAL_WRITE_REQUIRED" };
|
|
67180
67203
|
}
|
|
67181
67204
|
return { basis };
|
|
@@ -67184,7 +67207,8 @@ var require_conditional_write = __commonJS({
|
|
|
67184
67207
|
function conditionalWriteResidual(input) {
|
|
67185
67208
|
if (input.requireConditionalWrite !== true)
|
|
67186
67209
|
return null;
|
|
67187
|
-
|
|
67210
|
+
const mutating = input.mutating === void 0 ? input.writeStyle === true : input.mutating === true;
|
|
67211
|
+
if (!mutating)
|
|
67188
67212
|
return null;
|
|
67189
67213
|
if (input.conditionalWrite === true)
|
|
67190
67214
|
return null;
|
|
@@ -70303,9 +70327,11 @@ var require_guard = __commonJS({
|
|
|
70303
70327
|
allowStaleContext: config.allowStaleContext
|
|
70304
70328
|
});
|
|
70305
70329
|
}
|
|
70306
|
-
function conditionalWriteFor(config, redacted, ctx) {
|
|
70330
|
+
function conditionalWriteFor(config, redacted, ctx, detectedArts) {
|
|
70331
|
+
const mutating = (0, freshness_js_1.isMutatingCall)(redacted) || Array.isArray(detectedArts) && (0, freshness_js_1.isMutatingCall)({ artifacts: detectedArts });
|
|
70307
70332
|
return (0, conditional_write_js_1.buildConditionalWriteBasis)({
|
|
70308
70333
|
writeStyle: (0, freshness_js_1.isWriteStyleCall)(redacted),
|
|
70334
|
+
mutating,
|
|
70309
70335
|
requireConditionalWrite: config.requireConditionalWrite === true,
|
|
70310
70336
|
ctx
|
|
70311
70337
|
});
|
|
@@ -70377,7 +70403,7 @@ var require_guard = __commonJS({
|
|
|
70377
70403
|
}
|
|
70378
70404
|
}
|
|
70379
70405
|
{
|
|
70380
|
-
const { blockCause } = conditionalWriteFor(config, redacted, cwctx);
|
|
70406
|
+
const { blockCause } = conditionalWriteFor(config, redacted, cwctx, detection.artifacts);
|
|
70381
70407
|
if (blockCause === "CONDITIONAL_WRITE_REQUIRED") {
|
|
70382
70408
|
breakerRecord(config);
|
|
70383
70409
|
return closedIntegrity(config, blockCause, failPolicy, fctx, cwctx, redacted, detection.artifacts);
|
|
@@ -70388,7 +70414,7 @@ var require_guard = __commonJS({
|
|
|
70388
70414
|
const count = breakers.get(config)?.fails.length ?? 0;
|
|
70389
70415
|
const v = unavailableVerdict({ cause: "MISSING_ARTIFACT_CONTENT", failPolicy, resolution: "CLOSED", action: "STOP" }, count);
|
|
70390
70416
|
const { basis } = freshnessFor(config, redacted, fctx, detection.artifacts);
|
|
70391
|
-
const { basis: cw } = conditionalWriteFor(config, redacted, cwctx);
|
|
70417
|
+
const { basis: cw } = conditionalWriteFor(config, redacted, cwctx, detection.artifacts);
|
|
70392
70418
|
return blocked(config, v, false, basis, cw);
|
|
70393
70419
|
}
|
|
70394
70420
|
if (failPolicy === "lkg" && !config.lkg) {
|
|
@@ -70425,7 +70451,7 @@ var require_guard = __commonJS({
|
|
|
70425
70451
|
breakerRecord(config);
|
|
70426
70452
|
const count = breakers.get(config)?.fails.length ?? 1;
|
|
70427
70453
|
const { basis } = freshnessFor(config, redacted, fctx, detection.artifacts);
|
|
70428
|
-
const { basis: cw } = conditionalWriteFor(config, redacted, cwctx);
|
|
70454
|
+
const { basis: cw } = conditionalWriteFor(config, redacted, cwctx, detection.artifacts);
|
|
70429
70455
|
if (pf.integrity) {
|
|
70430
70456
|
emit(config, { type: "breaker_tripped", at: iso(), cause: pf.cause });
|
|
70431
70457
|
const v2 = unavailableVerdict({ cause: pf.cause, failPolicy, resolution: "CLOSED", action: "STOP" }, count);
|
|
@@ -70493,7 +70519,7 @@ var require_guard = __commonJS({
|
|
|
70493
70519
|
}
|
|
70494
70520
|
if (gate.verdict === "block-strict") {
|
|
70495
70521
|
const { basis } = freshnessFor(config, redacted, fctx, detection.artifacts);
|
|
70496
|
-
const { basis: cw } = conditionalWriteFor(config, redacted, cwctx);
|
|
70522
|
+
const { basis: cw } = conditionalWriteFor(config, redacted, cwctx, detection.artifacts);
|
|
70497
70523
|
return gate.decision === "BLOCK" ? blocked(config, { kind: "BLOCK", action: "STOP", envelope, receiptVerified }, true, basis, cw, void 0, void 0, grantObs) : blocked(config, { kind: "APPROVAL", action: "REQUEST_APPROVAL", envelope, receiptVerified }, true, basis, cw, void 0, void 0, grantObs);
|
|
70498
70524
|
}
|
|
70499
70525
|
const kind = gate.kind;
|
|
@@ -70564,7 +70590,7 @@ var require_guard = __commonJS({
|
|
|
70564
70590
|
breakerRecord(config);
|
|
70565
70591
|
return closedIntegrity(config, freshBlock, failPolicy, fctx, cwctx, redacted, detection.artifacts, void 0, void 0, grantObs);
|
|
70566
70592
|
}
|
|
70567
|
-
const { basis: cwBasis, blockCause: cwBlock } = conditionalWriteFor(config, redacted, cwctx);
|
|
70593
|
+
const { basis: cwBasis, blockCause: cwBlock } = conditionalWriteFor(config, redacted, cwctx, detection.artifacts);
|
|
70568
70594
|
if (cwBlock === "CONDITIONAL_WRITE_REQUIRED") {
|
|
70569
70595
|
breakerRecord(config);
|
|
70570
70596
|
return closedIntegrity(config, cwBlock, failPolicy, fctx, cwctx, redacted, detection.artifacts, void 0, void 0, grantObs);
|
|
@@ -70639,7 +70665,7 @@ var require_guard = __commonJS({
|
|
|
70639
70665
|
emit(config, { type: "breaker_tripped", at: iso(), cause });
|
|
70640
70666
|
const v = unavailableVerdict({ cause, failPolicy, resolution: "CLOSED", action: "STOP" }, count);
|
|
70641
70667
|
const { basis } = freshnessFor(config, redacted, fctx, arts);
|
|
70642
|
-
const { basis: cw } = conditionalWriteFor(config, redacted, cwctx);
|
|
70668
|
+
const { basis: cw } = conditionalWriteFor(config, redacted, cwctx, arts);
|
|
70643
70669
|
return blocked(config, v, false, basis, cw, monitoring_delivery, monitoring_attestation, grantObs);
|
|
70644
70670
|
}
|
|
70645
70671
|
function isExpired(envelope) {
|
|
@@ -74818,7 +74844,8 @@ var require_execute_tool_call = __commonJS({
|
|
|
74818
74844
|
var CW_NOT_REPORTED = Object.freeze({
|
|
74819
74845
|
conditional_write: "not_reported",
|
|
74820
74846
|
require_conditional_write: false,
|
|
74821
|
-
write_style: false
|
|
74847
|
+
write_style: false,
|
|
74848
|
+
mutating: false
|
|
74822
74849
|
});
|
|
74823
74850
|
function notObserved() {
|
|
74824
74851
|
return {
|
|
@@ -75271,9 +75298,9 @@ var require_cjs4 = __commonJS({
|
|
|
75271
75298
|
"use strict";
|
|
75272
75299
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
75273
75300
|
exports2.monitorAttestSigningInput = exports2.kidFromMonitoringAttestation = exports2.tryIssueMonitoringAttestation = exports2.DEFAULT_MONITORING_SINK_TIMEOUT_MS = exports2.ackBytes = exports2.verifyAckHmac = exports2.monitoringDeliveryFailClosed = exports2.formatMonitoringDeliveryLine = exports2.deliverMonitoring = exports2.hashObservedContent = exports2.observeCommit = exports2.deriveKeySignal = exports2.pathClass = exports2.classifyCommand = exports2.projectState = exports2.emptySessionState = exports2.computeTainted = exports2.evaluate = exports2.updateSession = exports2.SESSION_TAINT_VERSION = exports2.SessionTaintTracker = exports2.readDecision = exports2.EXECUTION_TIME_FP_REASONS = exports2.EXECUTION_STATE_UNMEASURABLE_NOTE = exports2.isUnmeasurableExecutionStateReason = exports2.computeCanonicalBundleFingerprint = exports2.authorizedFingerprintFromEnvelope = exports2.checkExecutionTimeFingerprint = exports2.computeBundleFingerprint = exports2.computeArtifactDigest = exports2.evaluateEnvelope = exports2.RECEIPT_PREV_NULL = exports2.decodeReceiptBodyPrev = exports2.previousReceiptCommitment = exports2.verifyReceiptChainLinkage = exports2.canonicalJson = exports2.computeBodyHash = exports2.bindReceiptToEnvelope = exports2.DETECTOR_VERSION = exports2.builtinDetector = exports2.resetPolicyWarnForTests = exports2.warnPolicyAbsentOnce = exports2.observePolicyPresence = exports2.detectPolicyPresence = exports2.policyPresenceOf = exports2.withPolicy = exports2.POLICY_ABSENT_WARN = exports2.POLICY_MARKER = exports2.CODERIFTS_POLICY = exports2.guardToolCall = void 0;
|
|
75274
|
-
exports2.
|
|
75275
|
-
exports2.
|
|
75276
|
-
exports2.kidFromToolsetAttestation = exports2.tryIssueToolsetAttestation = exports2.toolsetAttestSigningInput = exports2.declarationEntriesFromTools = exports2.computeToolsetDigest = exports2.TOOLSET_ATTEST_STATEMENT = exports2.TOOLSET_ATTEST_ENVELOPE_TAG = exports2.TOOLSET_ATTEST_SIGNING_PREFIX = exports2.TOOLSET_ATTEST_VERSION = exports2.surfaceEnvelopeFields = exports2.isGuardOutcome = exports2.executeLangGraphToolCall = exports2.executeGeminiToolCall = exports2.executeAnthropicToolCall = exports2.executeOpenAIToolCall = exports2.executeProtectedTool = exports2.defaultSerializeGeminiToolResult = exports2.bindGeminiGuardOutcome = exports2.protectedToolToFunctionDeclaration = exports2.toGeminiTools = exports2.geminiToolAdapter = exports2.withCodeRiftsGemini = exports2.wrapWriteWithFsCas = exports2.inferFullFileWriteContent = exports2.inferFsPathFromArgs = exports2.FRESHNESS_RESOLVER_FIX = exports2.freshnessRefusalTeaching = exports2.formatGateRefusalBody = exports2.defaultSerializeLangGraphToolResult = exports2.bindLangGraphGuardOutcome = exports2.LangGraphToolsNotStructuredError = exports2.isLangGraphReactAgentTool = exports2.bindLangGraphTools = exports2.protectedToolToLangGraph = exports2.toLangGraphTools = exports2.langGraphToolAdapter = exports2.withCodeRiftsLangGraph = exports2.defaultSerializeAnthropicToolResult = exports2.bindAnthropicGuardOutcome = exports2.protectedToolToAnthropic = exports2.toAnthropicTools = exports2.anthropicToolAdapter = exports2.withCodeRiftsAnthropic = exports2.defaultSerializeOpenAIToolResult = exports2.bindOpenAIGuardOutcome = exports2.protectedToolToOpenAI = exports2.toOpenAITools = exports2.openAIToolAdapter = exports2.withCodeRiftsOpenAI = void 0;
|
|
75301
|
+
exports2.DB_ABSENT_TOKEN = exports2.DB_VERSION_TOKEN_PREFIX = exports2.dbTokenRaw = exports2.writeDbIfUnchanged = exports2.createDbVersionToken = exports2.API_ABSENT_TOKEN = exports2.API_VERSION_TOKEN_PREFIX = exports2.apiTokenRaw = exports2.writeApiIfUnchanged = exports2.createApiVersionToken = exports2.FS_ABSENT_TOKEN = exports2.FS_VERSION_TOKEN_PREFIX = exports2.fsTokenContentHash = exports2.createFsPriorContentResolver = exports2.writeFileIfUnchanged = exports2.readVersionedFile = exports2.createFsVersionToken = exports2.StaleVersionTokenAbort = exports2.executeIfUnchanged = exports2.RESIDUAL_UNCONDITIONAL_WRITE = exports2.conditionalWriteResidual = exports2.tokensEqual = exports2.buildConditionalWriteBasis = exports2.buildFreshnessBasis = exports2.collectFreshnessCallContext = exports2.artifactIdsForResolve = exports2.isMutatingCall = exports2.isWriteStyleCall = exports2.freshnessAllowsEnforce = exports2.computePathSetTreeHash = exports2.contentByteIdentical = exports2.assessWriteStylePrior = exports2.assessFreshness = exports2.deriveProofBanner = exports2.attachProofToAgentResponse = exports2.renderFinalAnswerProof = exports2.EXECUTION_PROOF_SPEC = exports2.assertEnforcedReceiptInvariant = exports2.hashExecutionResult = exports2.buildExecutionProof = exports2.COVERAGE_ATTEST_ENVELOPE_TAG = exports2.COVERAGE_ATTEST_SIGNING_PREFIX = exports2.COVERAGE_ATTEST_VERSION = exports2.coverageAttestSigningInput = exports2.kidFromCoverageAttestation = exports2.tryIssueCoverageAttestation = exports2.MONITOR_ATTEST_ENVELOPE_TAG = exports2.MONITOR_ATTEST_SIGNING_PREFIX = exports2.MONITOR_ATTEST_VERSION = exports2.receiptDigestOfToken = void 0;
|
|
75302
|
+
exports2.freezeCoverageObserved = exports2.createCoverageObserver = exports2.readExecutionGrantToken = exports2.isExecutionGrantEnabled = exports2.guardedFractionAmongRoutes = exports2.foldTableSettledCalls = exports2.withCodeRifts = exports2.AUTO_DERIVE_READ_TIMEOUT_MS = exports2.AUTO_DERIVE_SOURCE = exports2.defaultFsReader = exports2.normalizeAutoDerive = exports2.runAutoDerive = exports2.AUTO_RECHECK_MAX_CAP = exports2.clampMaxAttempts = exports2.normalizeAutoRecheck = exports2.runAutoRecheckLoop = exports2.coverageReport = exports2.DEPLOY_REPAIRABLE_REASONS = exports2.bindDeploy = exports2.verifyDeployReceiptToken = exports2.DEPLOY_RECEIPT_VIEW_SPEC = exports2.isVerifiedDeployReceiptView = exports2.asVerifiedDeployReceiptView = exports2.deployGate = exports2.gateDecision = exports2.RegistryConstructionError = exports2.guardToolRegistry = exports2.globToRegExp = exports2.matchGlob = exports2.blobMapKey = exports2.classifyByName = exports2.resolveArtifacts = exports2.REMEDIATION_LOOP_ATTESTATION_SPEC = exports2.isCasAttestation = exports2.readPriorBlockRemediation = exports2.readRemediationTransaction = exports2.buildRemediationLoopAttestation = exports2.COMMIT_EVIDENCE_MISSING = exports2.CAS_ATTESTATION_SPEC = exports2.strictCommitObservation = exports2.extractExecutorAttestationToken = exports2.evaluateCasEvidence = exports2.isExecuteIfUnchangedOutcome = exports2.isGuardExecutionProof = exports2.buildCasAttestation = exports2.REGISTRY_ABSENT_TOKEN = exports2.REGISTRY_VERSION_TOKEN_PREFIX = exports2.registryTokenRaw = exports2.writeRegistryIfUnchanged = exports2.createRegistryVersionToken = void 0;
|
|
75303
|
+
exports2.kidFromToolsetAttestation = exports2.tryIssueToolsetAttestation = exports2.toolsetAttestSigningInput = exports2.declarationEntriesFromTools = exports2.computeToolsetDigest = exports2.TOOLSET_ATTEST_STATEMENT = exports2.TOOLSET_ATTEST_ENVELOPE_TAG = exports2.TOOLSET_ATTEST_SIGNING_PREFIX = exports2.TOOLSET_ATTEST_VERSION = exports2.surfaceEnvelopeFields = exports2.isGuardOutcome = exports2.executeLangGraphToolCall = exports2.executeGeminiToolCall = exports2.executeAnthropicToolCall = exports2.executeOpenAIToolCall = exports2.executeProtectedTool = exports2.defaultSerializeGeminiToolResult = exports2.bindGeminiGuardOutcome = exports2.protectedToolToFunctionDeclaration = exports2.toGeminiTools = exports2.geminiToolAdapter = exports2.withCodeRiftsGemini = exports2.wrapWriteWithFsCas = exports2.inferFullFileWriteContent = exports2.inferFsPathFromArgs = exports2.FRESHNESS_RESOLVER_FIX = exports2.freshnessRefusalTeaching = exports2.formatGateRefusalBody = exports2.defaultSerializeLangGraphToolResult = exports2.bindLangGraphGuardOutcome = exports2.LangGraphToolsNotStructuredError = exports2.isLangGraphReactAgentTool = exports2.bindLangGraphTools = exports2.protectedToolToLangGraph = exports2.toLangGraphTools = exports2.langGraphToolAdapter = exports2.withCodeRiftsLangGraph = exports2.defaultSerializeAnthropicToolResult = exports2.bindAnthropicGuardOutcome = exports2.protectedToolToAnthropic = exports2.toAnthropicTools = exports2.anthropicToolAdapter = exports2.withCodeRiftsAnthropic = exports2.defaultSerializeOpenAIToolResult = exports2.bindOpenAIGuardOutcome = exports2.protectedToolToOpenAI = exports2.toOpenAITools = exports2.openAIToolAdapter = exports2.withCodeRiftsOpenAI = exports2.formatCoverageObservedLine = void 0;
|
|
75277
75304
|
var guard_js_1 = require_guard();
|
|
75278
75305
|
Object.defineProperty(exports2, "guardToolCall", { enumerable: true, get: function() {
|
|
75279
75306
|
return guard_js_1.guardToolCall;
|
|
@@ -75509,6 +75536,9 @@ var require_cjs4 = __commonJS({
|
|
|
75509
75536
|
Object.defineProperty(exports2, "isWriteStyleCall", { enumerable: true, get: function() {
|
|
75510
75537
|
return freshness_js_1.isWriteStyleCall;
|
|
75511
75538
|
} });
|
|
75539
|
+
Object.defineProperty(exports2, "isMutatingCall", { enumerable: true, get: function() {
|
|
75540
|
+
return freshness_js_1.isMutatingCall;
|
|
75541
|
+
} });
|
|
75512
75542
|
Object.defineProperty(exports2, "artifactIdsForResolve", { enumerable: true, get: function() {
|
|
75513
75543
|
return freshness_js_1.artifactIdsForResolve;
|
|
75514
75544
|
} });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coderifts",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.1",
|
|
4
4
|
"description": "Detect breaking API changes from the command line. Works locally or with the CodeRifts cloud API.",
|
|
5
5
|
"author": "CodeRifts <hello@coderifts.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"test": "node --test test/*.test.js"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@coderifts/agent-guard": "^
|
|
48
|
+
"@coderifts/agent-guard": "^12.0.0",
|
|
49
49
|
"chalk": "^4.1.2",
|
|
50
50
|
"cli-table3": "^0.6.4",
|
|
51
51
|
"commander": "^12.0.0",
|
|
@@ -25,13 +25,33 @@
|
|
|
25
25
|
* rises anyway, because a semantics floor is about what the CLI may RUN against, not about what
|
|
26
26
|
* it happens to import today — a fingerprint that disagrees with the server is exactly the class
|
|
27
27
|
* of difference this gate exists to refuse.)
|
|
28
|
+
* 5.0.0: floor raised to 12 (requireConditionalWrite now FIRES on an ordinary mutation. Through
|
|
29
|
+
* 11.0.1 the policy gated on isWriteStyleCall, which answers "did the caller supply a both-sides
|
|
30
|
+
* snapshot" — the right question for FRESHNESS, which it was written for, and the wrong one for
|
|
31
|
+
* atomicity. So a mutation carrying artifacts[] with non-empty before AND after classified as
|
|
32
|
+
* not-write-style and the demand never fired: reproduced against the published 11.0.1 tarball,
|
|
33
|
+
* where the side effect RAN with enforced:true and conditional_write:"not_reported". It bites on
|
|
34
|
+
* the NORMAL path, not an exotic config, because the tool-registry defaultBinder lifts
|
|
35
|
+
* old_string/new_string and edits[] into exactly that shape — so an agent editing a contract
|
|
36
|
+
* artifact under ENFORCING_STRICT wrote unconditionally. 12.0.0 adds isMutatingCall and gates on
|
|
37
|
+
* it; ConditionalWriteBasis gains a required `mutating` field. COST MEASURED AS ZERO, the same
|
|
38
|
+
* way the 11-raise was: the CLI imports only deployGate, asVerifiedDeployReceiptView,
|
|
39
|
+
* DEPLOY_RECEIPT_VIEW_SPEC and matchGlob, whose implementing modules (deploy-gate.js,
|
|
40
|
+
* resolver-glob.js, deploy-receipt-token.js) are BYTE-IDENTICAL 11.0.1 -> 12.0.0; the CLI
|
|
41
|
+
* constructs no ConditionalWriteBasis and never sets requireConditionalWrite, so the one
|
|
42
|
+
* type-level break cannot reach it — it is JS besides. Suite on 12.0.0: 556/554/2, identical to
|
|
43
|
+
* 11.0.0 with a byte-identical failure set; the only edits the raise needed were this gate's own
|
|
44
|
+
* two value-pins in assert-guard-major-coverage.test.js, which exist to move with each recorded
|
|
45
|
+
* raise, and no product code. The floor rises anyway, because a semantics floor is about
|
|
46
|
+
* what the CLI may RUN against: a guard that silently skips the atomicity demand on an ordinary
|
|
47
|
+
* edit is exactly the class of difference this gate exists to refuse.)
|
|
28
48
|
*/
|
|
29
49
|
|
|
30
50
|
const fs = require('fs');
|
|
31
51
|
const path = require('path');
|
|
32
52
|
|
|
33
53
|
/** Minimum acceptable major for @coderifts/agent-guard in THIS package (the CLI). */
|
|
34
|
-
const MIN_GUARD_MAJOR =
|
|
54
|
+
const MIN_GUARD_MAJOR = 12;
|
|
35
55
|
const DEP = '@coderifts/agent-guard';
|
|
36
56
|
|
|
37
57
|
/**
|
|
@@ -91,6 +111,18 @@ const CHECKOUTS = [
|
|
|
91
111
|
* 11 makes the bump neither easier nor harder — the blocker is unchanged and the deferral still
|
|
92
112
|
* holds for exactly the reason above, not for a residual shape that moved.
|
|
93
113
|
*
|
|
114
|
+
*
|
|
115
|
+
* WHAT THE RESOLVED-RANGE CHECK SAYS ABOUT THIS ENTRY: NOTHING, and that is the correct
|
|
116
|
+
* answer rather than a lucky one. The check added for the 5.0.0 finding grades whether the
|
|
117
|
+
* DECLARED range and the RESOLVED install AGREE. The root declares ^3.0.0 and resolves 3.0.0,
|
|
118
|
+
* so they agree exactly and it reports "in range". The root's gap is not drift between its
|
|
119
|
+
* manifest and its tree — it is a deliberately LOW FLOOR, and a floor is a human decision this
|
|
120
|
+
* gate records rather than derives. That decision lives in `floor: 3` and the reason above.
|
|
121
|
+
*
|
|
122
|
+
* A check that DID flag it — "resolved major must equal the newest published major" — was
|
|
123
|
+
* considered and rejected: it would force exactly the bump the paragraphs above say must not
|
|
124
|
+
* be forced before the residual-precedence reconciliation. The gate must not legislate a
|
|
125
|
+
* decision it is only supposed to remember.
|
|
94
126
|
* WHAT THE BUMP ROUND MUST DECIDE: whether the guard should emit all holding residuals (then
|
|
95
127
|
* the app consumes gateOut.residuals and collectBindingResiduals is deleted), or whether the
|
|
96
128
|
* single-slot shape is deliberate (then the app keeps its collector and the duplication is
|
|
@@ -148,6 +180,94 @@ function resolvedVersionFor(startDir) {
|
|
|
148
180
|
return null;
|
|
149
181
|
}
|
|
150
182
|
|
|
183
|
+
/**
|
|
184
|
+
* RESOLVED-VERSION GRADING — the half the floor check cannot do.
|
|
185
|
+
*
|
|
186
|
+
* WHY THIS EXISTS. coderifts@5.0.0 published declaring `@coderifts/agent-guard: ^11.0.0` while
|
|
187
|
+
* guard 12.0.0 was already out carrying a semantics break (requireConditionalWrite began firing on
|
|
188
|
+
* ordinary mutations). This gate PASSED, and it was not wrong to: it graded the declared floor
|
|
189
|
+
* (11 >= 11) and the resolved version (11.0.0 >= 11) against a constant a human maintains by hand.
|
|
190
|
+
* Both facts were true. Both were stale. A gate that can only compare against the last floor
|
|
191
|
+
* someone remembered to raise cannot notice a major it has never been told about.
|
|
192
|
+
*
|
|
193
|
+
* So the constant is not the whole gate. What CAN be checked without a registry call is whether
|
|
194
|
+
* the tree and the manifest AGREE — and they must agree in both directions:
|
|
195
|
+
*
|
|
196
|
+
* · resolved BELOW the declared range → a stale install. The suite measured an older guard than
|
|
197
|
+
* the one we ship against, so every "cost measured as zero" conclusion is about the wrong
|
|
198
|
+
* package.
|
|
199
|
+
* · resolved ABOVE the declared range → the more dangerous direction, and the one that produced
|
|
200
|
+
* this finding's shape. Staging a NEWER guard into node_modules to measure a raise, then
|
|
201
|
+
* publishing with the old range, means the suite proved something adopters never receive: they
|
|
202
|
+
* resolve the range, not our node_modules. A green suite over a version we do not declare is a
|
|
203
|
+
* false confidence, not a measurement.
|
|
204
|
+
*
|
|
205
|
+
* NOT RESOLVED IS A FAILURE, not a pass. The previous code returned a success line reading
|
|
206
|
+
* "not resolved in tree" — "we could not look" recorded as "we looked and it is fine", which is
|
|
207
|
+
* the exact fail-open class this repository refuses elsewhere (a 404 on the source_ref anchor is
|
|
208
|
+
* deliberately on the FAIL side for the same reason). A publish gate that verifies nothing must
|
|
209
|
+
* say so by failing.
|
|
210
|
+
*
|
|
211
|
+
* WHAT THIS STILL CANNOT DO, named rather than implied: it makes no network call, so it cannot
|
|
212
|
+
* know that a newer major exists. Raising the floor stays a human act with a recorded reason. This
|
|
213
|
+
* check only guarantees that what we measured is what we declare.
|
|
214
|
+
*/
|
|
215
|
+
|
|
216
|
+
/** Parse "1.2.3" (ignoring any prerelease/build suffix) to [1,2,3], or null. */
|
|
217
|
+
function parseVersion(v) {
|
|
218
|
+
const m = /^(\d+)\.(\d+)\.(\d+)/.exec(String(v || '').trim());
|
|
219
|
+
return m ? [parseInt(m[1], 10), parseInt(m[2], 10), parseInt(m[3], 10)] : null;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** -1 / 0 / 1 over [maj,min,pat] triples. */
|
|
223
|
+
function compareVersions(a, b) {
|
|
224
|
+
for (let i = 0; i < 3; i += 1) {
|
|
225
|
+
if (a[i] !== b[i]) return a[i] < b[i] ? -1 : 1;
|
|
226
|
+
}
|
|
227
|
+
return 0;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Inclusive lower bound and EXCLUSIVE upper bound for the range forms this gate already accepts.
|
|
232
|
+
* Deliberately dependency-free — the rest of this file is, and a publish gate that needs an
|
|
233
|
+
* install to run is a gate that stops running.
|
|
234
|
+
*
|
|
235
|
+
* ^1.2.3 -> [1.2.3, 2.0.0) ~1.2.3 -> [1.2.3, 1.3.0) >=1.2.3 -> [1.2.3, inf)
|
|
236
|
+
* 1.2.3 -> [1.2.3, 1.2.4) 1.x -> [1.0.0, 2.0.0)
|
|
237
|
+
* Anything else -> null (caller treats an unparseable range as unverifiable, never as satisfied).
|
|
238
|
+
*/
|
|
239
|
+
function rangeBounds(range) {
|
|
240
|
+
const s = String(range || '').trim();
|
|
241
|
+
const m = /^(\^|~|>=|=)?\s*(\d+)(?:\.(\d+|x|\*))?(?:\.(\d+|x|\*))?/.exec(s);
|
|
242
|
+
if (!m) return null;
|
|
243
|
+
const op = m[1] || '';
|
|
244
|
+
const maj = parseInt(m[2], 10);
|
|
245
|
+
const minRaw = m[3];
|
|
246
|
+
const patRaw = m[4];
|
|
247
|
+
const wild = (t) => t === undefined || t === 'x' || t === '*';
|
|
248
|
+
const min = wild(minRaw) ? 0 : parseInt(minRaw, 10);
|
|
249
|
+
const pat = wild(patRaw) ? 0 : parseInt(patRaw, 10);
|
|
250
|
+
const lower = [maj, min, pat];
|
|
251
|
+
if (wild(minRaw)) return { lower, upper: [maj + 1, 0, 0] }; // 1.x
|
|
252
|
+
if (op === '^') return { lower, upper: [maj + 1, 0, 0] };
|
|
253
|
+
if (op === '~') return { lower, upper: [maj, min + 1, 0] };
|
|
254
|
+
if (op === '>=') return { lower, upper: null };
|
|
255
|
+
if (wild(patRaw)) return { lower, upper: [maj, min + 1, 0] }; // 1.2.x
|
|
256
|
+
return { lower, upper: [maj, min, pat + 1] }; // exact
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* @returns {'in'|'below'|'above'|'unknown'} where `version` sits relative to `range`.
|
|
261
|
+
*/
|
|
262
|
+
function versionVsRange(version, range) {
|
|
263
|
+
const v = parseVersion(version);
|
|
264
|
+
const b = rangeBounds(range);
|
|
265
|
+
if (!v || !b) return 'unknown';
|
|
266
|
+
if (compareVersions(v, b.lower) < 0) return 'below';
|
|
267
|
+
if (b.upper && compareVersions(v, b.upper) >= 0) return 'above';
|
|
268
|
+
return 'in';
|
|
269
|
+
}
|
|
270
|
+
|
|
151
271
|
/** Check ONE checkout. Returns a line for the summary; calls fail() and exits on a violation. */
|
|
152
272
|
function checkCheckout(c) {
|
|
153
273
|
if (!fs.existsSync(c.pkgPath)) {
|
|
@@ -173,7 +293,15 @@ function checkCheckout(c) {
|
|
|
173
293
|
|
|
174
294
|
const resolved = resolvedVersionFor(path.dirname(c.pkgPath));
|
|
175
295
|
if (!resolved) {
|
|
176
|
-
|
|
296
|
+
// FAIL-CLOSED, with NO opt-out. An `allowUnresolved` flag was written and then removed on
|
|
297
|
+
// purpose: the first time this fires in CI the cheapest response is to set the flag, and the
|
|
298
|
+
// hole is back with a config line to justify it. If a checkout ever legitimately ships
|
|
299
|
+
// uninstalled, add the exemption THEN, with the measurement that earned it.
|
|
300
|
+
fail(
|
|
301
|
+
`${c.label}: ${DEP} is declared ${JSON.stringify(range)} but is NOT RESOLVABLE from `
|
|
302
|
+
+ `${path.dirname(c.pkgPath)}. This gate cannot verify what will ship, and an unverified `
|
|
303
|
+
+ 'publish is not a verified one. Install dependencies for this checkout and re-run.',
|
|
304
|
+
);
|
|
177
305
|
}
|
|
178
306
|
const rm = /^(\d+)/.exec(resolved);
|
|
179
307
|
const rMajor = rm ? parseInt(rm[1], 10) : null;
|
|
@@ -183,7 +311,32 @@ function checkCheckout(c) {
|
|
|
183
311
|
if (rMajor < floor) {
|
|
184
312
|
fail(`${c.label}: resolved ${DEP}@${resolved} major ${rMajor} is below declared range floor ${floor}`);
|
|
185
313
|
}
|
|
186
|
-
|
|
314
|
+
|
|
315
|
+
// THE DECLARED RANGE AND THE INSTALLED TREE MUST AGREE — both directions, full precision.
|
|
316
|
+
const where = versionVsRange(resolved, range);
|
|
317
|
+
if (where === 'below') {
|
|
318
|
+
fail(
|
|
319
|
+
`${c.label}: resolved ${DEP}@${resolved} is BELOW the declared range ${JSON.stringify(range)} `
|
|
320
|
+
+ '— a stale install. Every cost measured against this tree describes an older guard than the '
|
|
321
|
+
+ 'one this package declares. Run npm install for this checkout and re-measure.',
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
if (where === 'above') {
|
|
325
|
+
fail(
|
|
326
|
+
`${c.label}: resolved ${DEP}@${resolved} is ABOVE the declared range ${JSON.stringify(range)}. `
|
|
327
|
+
+ 'The tree runs a guard this package does not declare, so the suite measured a version '
|
|
328
|
+
+ 'adopters will never receive — they resolve the range, not our node_modules. Either raise '
|
|
329
|
+
+ `the declared range to admit ${resolved} (and record WHY in the history block), or remove `
|
|
330
|
+
+ 'the staged install.',
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
if (where === 'unknown') {
|
|
334
|
+
fail(
|
|
335
|
+
`${c.label}: cannot decide whether resolved ${DEP}@${resolved} satisfies declared range `
|
|
336
|
+
+ `${JSON.stringify(range)} — unparseable. A range this gate cannot grade must not ship.`,
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
return `${c.label}: declared ${range} (floor ${floor} >= ${c.floor}); resolved ${resolved} (in range)`;
|
|
187
340
|
}
|
|
188
341
|
|
|
189
342
|
function main() {
|
|
@@ -206,4 +359,7 @@ function main() {
|
|
|
206
359
|
// floorMajorFromRange without triggering a process.exit.
|
|
207
360
|
if (require.main === module) main();
|
|
208
361
|
|
|
209
|
-
module.exports = {
|
|
362
|
+
module.exports = {
|
|
363
|
+
CHECKOUTS, floorMajorFromRange, MIN_GUARD_MAJOR, DEP,
|
|
364
|
+
parseVersion, compareVersions, rangeBounds, versionVsRange, resolvedVersionFor,
|
|
365
|
+
};
|