@aiwg/cli 2026.9.21 → 2026.10.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/agentic/code/providers/capability-matrix.yaml +2 -1
- package/dist/src/artifacts/cli.js +23 -18
- package/dist/src/artifacts/discovery-shadow-evaluator.js +177 -0
- package/dist/src/artifacts/discovery-shadow.js +195 -0
- package/dist/src/artifacts/fortemi-core-query-adapter.js +6 -2
- package/dist/src/artifacts/index-builder.js +47 -9
- package/dist/src/artifacts/query-engine.js +108 -5
- package/dist/src/artifacts/types.js +1 -0
- package/dist/src/cli/handlers/decision.js +88 -0
- package/dist/src/cli/handlers/gates.js +154 -0
- package/dist/src/cli/handlers/index.js +5 -1
- package/dist/src/cli/handlers/sessions.js +10 -7
- package/dist/src/cli/handlers/utilities.js +20 -0
- package/dist/src/config/aiwg-config.js +15 -2
- package/dist/src/decision/acceptance.js +25 -0
- package/dist/src/decision/adapters/jev.js +24 -2
- package/dist/src/decision/calibration/registry.js +9 -0
- package/dist/src/decision/compose.js +74 -15
- package/dist/src/decision/context-live-promotion.js +344 -0
- package/dist/src/decision/context-live-qualification.js +591 -0
- package/dist/src/decision/context-pruning.js +847 -0
- package/dist/src/decision/driver.js +430 -0
- package/dist/src/decision/egress-live-qualification.js +874 -0
- package/dist/src/decision/ensemble/contract.js +64 -1
- package/dist/src/decision/ensemble/index.js +1 -0
- package/dist/src/decision/ensemble/report.js +8 -42
- package/dist/src/decision/ensemble/runtime.js +571 -0
- package/dist/src/decision/ensemble-study/artifacts.js +85 -0
- package/dist/src/decision/ensemble-study/calibration.js +443 -0
- package/dist/src/decision/ensemble-study/corpus.js +229 -0
- package/dist/src/decision/ensemble-study/multifact-artifacts.js +23 -0
- package/dist/src/decision/ensemble-study/multifact-study.js +596 -0
- package/dist/src/decision/ensemble-study/multifact.js +241 -0
- package/dist/src/decision/ensemble-study/protocol.js +77 -0
- package/dist/src/decision/ensemble-study/score.js +462 -0
- package/dist/src/decision/ensemble-study/staged.js +87 -0
- package/dist/src/decision/ensemble-study/statistics.js +84 -0
- package/dist/src/decision/evaluate.js +227 -14
- package/dist/src/decision/export.js +4 -0
- package/dist/src/decision/feature-export.js +1074 -0
- package/dist/src/decision/graph-index.js +16 -0
- package/dist/src/decision/graph-live-qualification.js +1041 -0
- package/dist/src/decision/graph-live-workload.js +245 -0
- package/dist/src/decision/graph-skill-bridge.js +21 -3
- package/dist/src/decision/heldout/calibration.js +140 -0
- package/dist/src/decision/heldout/collector.js +430 -0
- package/dist/src/decision/heldout/contract.js +309 -0
- package/dist/src/decision/heldout/d29-generator-ids.js +12 -0
- package/dist/src/decision/heldout/d29-passage-baseline-v2.js +93 -0
- package/dist/src/decision/heldout/d29-passage-baseline-v3.js +100 -0
- package/dist/src/decision/heldout/d29-passage-baseline.js +66 -0
- package/dist/src/decision/heldout/d29-pools-v8.js +575 -0
- package/dist/src/decision/heldout/d29-pools.js +288 -0
- package/dist/src/decision/heldout/d29-v6.js +169 -0
- package/dist/src/decision/heldout/d29-v7.js +202 -0
- package/dist/src/decision/heldout/d29-v8.js +586 -0
- package/dist/src/decision/heldout/generator-registry.js +67 -0
- package/dist/src/decision/heldout/generators.js +696 -0
- package/dist/src/decision/heldout/index.js +8 -0
- package/dist/src/decision/heldout/journal.js +346 -0
- package/dist/src/decision/heldout/study-generators.js +64 -0
- package/dist/src/decision/heldout/types.js +2 -0
- package/dist/src/decision/host-policy.js +61 -0
- package/dist/src/decision/index.js +11 -0
- package/dist/src/decision/interop-profile.v1.json +112 -0
- package/dist/src/decision/interop.js +653 -0
- package/dist/src/decision/issue-triage/index.js +3 -0
- package/dist/src/decision/issue-triage/runtime.js +1069 -0
- package/dist/src/decision/issue-triage/types.js +2 -0
- package/dist/src/decision/patterns/catalog.js +28 -8
- package/dist/src/decision/patterns/playground.js +28 -11
- package/dist/src/decision/patterns/specs.js +19 -10
- package/dist/src/decision/preprocessed-evidence.js +724 -0
- package/dist/src/decision/qualification/capture.js +8 -2
- package/dist/src/decision/qualification/gate-evidence.js +19 -4
- package/dist/src/decision/qualification/load.js +8 -1
- package/dist/src/decision/qualification/quality.js +57 -49
- package/dist/src/decision/qualification/release.js +76 -3
- package/dist/src/decision/qualification/runner.js +5 -2
- package/dist/src/decision/routing/contract.js +175 -0
- package/dist/src/decision/routing/index.js +5 -0
- package/dist/src/decision/routing/report.js +216 -0
- package/dist/src/decision/routing/runtime.js +685 -0
- package/dist/src/decision/routing/types.js +2 -0
- package/dist/src/decision/sdlc-screening.js +1157 -0
- package/dist/src/decision/sensitivity/comparative.js +154 -0
- package/dist/src/decision/sensitivity/contract.js +218 -0
- package/dist/src/decision/sensitivity/index.js +5 -0
- package/dist/src/decision/sensitivity/runtime.js +912 -0
- package/dist/src/decision/sensitivity/types.js +2 -0
- package/dist/src/decision/validate.js +26 -0
- package/dist/src/extensions/commands/definitions.js +38 -0
- package/dist/src/extensions/manifest.js +44 -0
- package/dist/src/gates/discovery.js +315 -0
- package/dist/src/gates/driver.js +388 -0
- package/dist/src/gates/evaluate.js +719 -0
- package/dist/src/gates/floors.js +255 -0
- package/dist/src/gates/index.js +17 -0
- package/dist/src/gates/providers/evidence.js +38 -0
- package/dist/src/gates/providers/index.js +21 -0
- package/dist/src/gates/providers/isolated-child-source.js +446 -0
- package/dist/src/gates/providers/loader.js +1069 -0
- package/dist/src/gates/providers/paired.js +52 -0
- package/dist/src/gates/providers/proportion.js +60 -0
- package/dist/src/gates/providers/registry.js +40 -0
- package/dist/src/gates/providers/scalar.js +41 -0
- package/dist/src/gates/providers/screening.js +53 -0
- package/dist/src/gates/providers/types.js +25 -0
- package/dist/src/gates/registry.js +1003 -0
- package/dist/src/gates/report.js +102 -0
- package/dist/src/gates/schema.js +56 -0
- package/dist/src/gates/stats/binomial.js +26 -0
- package/dist/src/gates/stats/bootstrap.js +62 -0
- package/dist/src/gates/stats/clopper-pearson.js +95 -0
- package/dist/src/gates/stats/digest.js +26 -0
- package/dist/src/gates/stats/error.js +5 -0
- package/dist/src/gates/stats/index.js +9 -0
- package/dist/src/gates/stats/normal.js +35 -0
- package/dist/src/gates/stats/paired.js +120 -0
- package/dist/src/gates/stats/splits.js +30 -0
- package/dist/src/gates/types.js +8 -0
- package/dist/src/governance/redaction.js +14 -4
- package/dist/src/mcp/muse-native-config.mjs +123 -0
- package/dist/src/mcp/tools/decision.mjs +188 -0
- package/dist/src/mcp/tools/subsystems.mjs +2 -0
- package/dist/src/providers/capability-matrix.yaml +2 -1
- package/dist/src/providers/provider-definitions.js +2 -1
- package/dist/src/sessions/adapters/muse.js +336 -39
- package/dist/src/sessions/batch-import.js +7 -0
- package/dist/src/sessions/workspace-discovery.js +13 -2
- package/package.json +1 -1
- package/schemas/decision/ConformalFrozenOpenData.v2.schema.json +371 -0
- package/schemas/decision/ConformalOpenDataReport.v2.schema.json +421 -0
- package/schemas/decision/ConformalPreregistration.v2.schema.json +529 -0
- package/schemas/decision/ContextPruningCandidate.v1.schema.json +47 -0
- package/schemas/decision/ContextPruningEvaluationReport.v1.schema.json +758 -0
- package/schemas/decision/ContextPruningPreregistration.v1.schema.json +175 -0
- package/schemas/decision/ContextPruningReceipt.v1.schema.json +72 -0
- package/schemas/decision/D17Multifact.v1.schema.json +1851 -0
- package/schemas/decision/D17StudyAnalysis.v1.schema.json +42 -0
- package/schemas/decision/D17StudyAnalysis.v2.schema.json +51 -0
- package/schemas/decision/D17StudyCalibration.v1.schema.json +819 -0
- package/schemas/decision/D17StudyDryRun.v1.schema.json +169 -0
- package/schemas/decision/D17StudyDryRun.v2.schema.json +239 -0
- package/schemas/decision/D17StudyGold.v1.schema.json +108 -0
- package/schemas/decision/D17StudyGuide.v1.schema.json +63 -0
- package/schemas/decision/D17StudyNativeTemplates.v1.schema.json +619 -0
- package/schemas/decision/D17StudyProtocol.v1.schema.json +241 -0
- package/schemas/decision/D17StudyReport.v1.schema.json +902 -0
- package/schemas/decision/D17StudyReport.v2.schema.json +1319 -0
- package/schemas/decision/D17StudyReview.v1.schema.json +175 -0
- package/schemas/decision/D17StudySplits.v1.schema.json +217 -0
- package/schemas/decision/D29Study.v1.schema.json +1903 -0
- package/schemas/decision/D29Study.v2.schema.json +1344 -0
- package/schemas/decision/D29Study.v3.schema.json +609 -0
- package/schemas/decision/D29Study.v4.schema.json +1133 -0
- package/schemas/decision/D29Study.v6.schema.json +1205 -0
- package/schemas/decision/D29Study.v7.schema.json +1471 -0
- package/schemas/decision/D29Study.v8.schema.json +671 -0
- package/schemas/decision/D29Study.v9.schema.json +778 -0
- package/schemas/decision/DecisionComparativeReplayAuditSample.v1.schema.json +137 -0
- package/schemas/decision/DecisionComparativeReplayCorpus.v1.schema.json +258 -0
- package/schemas/decision/DecisionComparativeReplayFreeze.v1.schema.json +74 -0
- package/schemas/decision/DecisionComparativeReplayGold.v1.schema.json +50 -0
- package/schemas/decision/DecisionComparativeReplayGoldAsset.v1.schema.json +37 -0
- package/schemas/decision/DecisionComparativeReplayIntegrity.v1.schema.json +81 -0
- package/schemas/decision/DecisionComparativeReplayMembers.v1.schema.json +52 -0
- package/schemas/decision/DecisionComparativeReplayPreregistration.v1.schema.json +113 -0
- package/schemas/decision/DecisionComparativeReplayReport.v1.schema.json +407 -0
- package/schemas/decision/DecisionComparativeReplayReviewPackets.v1.schema.json +260 -0
- package/schemas/decision/DecisionComparativeReplaySplit.v1.schema.json +84 -0
- package/schemas/decision/DecisionFeatureObservation.v1.schema.json +564 -0
- package/schemas/decision/DecisionFeatureSet.v1.schema.json +155 -0
- package/schemas/decision/DecisionInteropMapping.v1.schema.json +85 -0
- package/schemas/decision/DecisionIssueTriageEvaluationManifest.v1.schema.json +174 -0
- package/schemas/decision/DecisionIssueTriageEvaluationReport.v1.schema.json +280 -0
- package/schemas/decision/DecisionIssueTriagePilotPack.v1.schema.json +114 -0
- package/schemas/decision/DecisionRouteReceipt.v1.schema.json +155 -0
- package/schemas/decision/DecisionRoutingPolicy.v1.schema.json +132 -0
- package/schemas/decision/DecisionRoutingShadowReport.v1.schema.json +170 -0
- package/schemas/decision/DecisionRoutingTask.v1.schema.json +49 -0
- package/schemas/decision/DecisionRuleset.schema.json +8 -2
- package/schemas/decision/DecisionRuleset.v1alpha2.schema.json +8 -2
- package/schemas/decision/DecisionSensitivityPlan.v1.schema.json +191 -0
- package/schemas/decision/DecisionSensitivityReport.v1.schema.json +163 -0
- package/schemas/decision/HeldoutApproval.v1.schema.json +312 -0
- package/schemas/decision/HeldoutAttempt.v1.schema.json +211 -0
- package/schemas/decision/HeldoutBaseline.v1.schema.json +90 -0
- package/schemas/decision/HeldoutCalibrationPhase.v1.schema.json +87 -0
- package/schemas/decision/HeldoutCorpus.v1.schema.json +167 -0
- package/schemas/decision/HeldoutEvent.v1.schema.json +41 -0
- package/schemas/decision/HeldoutFrozen.v1.schema.json +142 -0
- package/schemas/decision/HeldoutPreregistration.v1.schema.json +222 -0
- package/schemas/decision/HeldoutSpendEvent.v1.schema.json +122 -0
- package/schemas/decision/HeldoutSpendHead.v1.schema.json +25 -0
- package/schemas/decision/HeldoutSpendHead.v2.schema.json +46 -0
- package/schemas/decision/HeldoutSummary.v1.schema.json +101 -0
- package/schemas/decision/OpaDecisionLogExport.v1.schema.json +65 -0
- package/schemas/decision/PreprocessedEvidence.v1.schema.json +306 -0
- package/schemas/decision/RulesetResult.v1alpha2.schema.json +175 -0
- package/schemas/decision/SdlcEvidenceScreening.v1.schema.json +499 -0
- package/schemas/decision/SdlcScreeningPreregistration.v1.schema.json +132 -0
- package/schemas/decision/SdlcScreeningPreregistration.v2.schema.json +138 -0
- package/schemas/decision/SdlcScreeningRelease.v1.schema.json +654 -0
- package/schemas/decision/SdlcScreeningRelease.v2.schema.json +654 -0
- package/tools/agents/deploy-agents.mjs +1 -1
- package/tools/agents/providers/base.mjs +26 -7
- package/tools/agents/providers/factory.mjs +10 -2
- package/tools/agents/providers/muse-hooks.mjs +1 -29
- package/tools/agents/providers/muse.mjs +6 -3
|
@@ -295,7 +295,50 @@ export function validateEnsembleAggregate(value) {
|
|
|
295
295
|
semantic(problems, 'ensemble aggregate rejected');
|
|
296
296
|
return aggregate;
|
|
297
297
|
}
|
|
298
|
-
/**
|
|
298
|
+
/** D17 findings derived from the carried #2037/#2048 integrity fields alone. */
|
|
299
|
+
export function integrityMetadataFindings(integrity, minimumPairs) {
|
|
300
|
+
const findings = [];
|
|
301
|
+
if (integrity.integrity_state !== 'verified')
|
|
302
|
+
findings.push('integrity-not-verified');
|
|
303
|
+
if (integrity.integrity_mode === 'standard')
|
|
304
|
+
findings.push('integrity-mode-standard');
|
|
305
|
+
if (integrity.trusted_score_source === 'local-unverified')
|
|
306
|
+
findings.push('untrusted-score-source');
|
|
307
|
+
if (integrity.fresh_workspace_required && !integrity.fresh_workspace_verified)
|
|
308
|
+
findings.push('fresh-workspace-unverified');
|
|
309
|
+
if (integrity.uncertainty === null)
|
|
310
|
+
findings.push('uncertainty-missing');
|
|
311
|
+
if (integrity.paired_baseline === null)
|
|
312
|
+
findings.push('paired-baseline-missing');
|
|
313
|
+
if (integrity.weak_signal_reason !== null)
|
|
314
|
+
findings.push('weak-signal');
|
|
315
|
+
if (integrity.compromise_labels.length > 0)
|
|
316
|
+
findings.push('compromised');
|
|
317
|
+
if (integrity.sample_n < minimumPairs)
|
|
318
|
+
findings.push('insufficient-samples');
|
|
319
|
+
return findings;
|
|
320
|
+
}
|
|
321
|
+
/** The finding for one paired delta against its preregistered threshold, or null when it passes. */
|
|
322
|
+
export function pairedDeltaFinding(threshold, item) {
|
|
323
|
+
if (!item)
|
|
324
|
+
return `paired-delta-missing:${threshold.metric}`;
|
|
325
|
+
if (item.delta === null || !Number.isFinite(item.delta))
|
|
326
|
+
return `paired-delta-unknown:${threshold.metric}`;
|
|
327
|
+
if (!Number.isSafeInteger(item.pairs) || item.pairs < threshold.minimumPairs)
|
|
328
|
+
return `paired-delta-insufficient:${threshold.metric}`;
|
|
329
|
+
if (threshold.comparison === 'delta-at-least' ? item.delta < threshold.bound : item.delta > threshold.bound)
|
|
330
|
+
return `paired-delta-failed:${threshold.metric}`;
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
/** Upstream ROLLBACK or any compromise gives ROLLBACK; upstream HOLD or any finding gives HOLD. */
|
|
334
|
+
export function ensembleIntegrityDecision(integrity, findingCount) {
|
|
335
|
+
const upstream = integrity.release_gate.decision;
|
|
336
|
+
const compromised = integrity.integrity_state === 'compromised' || integrity.compromise_labels.length > 0;
|
|
337
|
+
return upstream === 'ROLLBACK' || compromised ? 'ROLLBACK' : upstream === 'HOLD' || findingCount > 0 ? 'HOLD' : 'PROMOTE';
|
|
338
|
+
}
|
|
339
|
+
/** A D17 report may keep or tighten the upstream #2037/#2048 decision, never loosen it. Every
|
|
340
|
+
* finding, passed flag and the decision are recomputed from the carried integrity fields and the
|
|
341
|
+
* preregistered thresholds; D09-derived findings need the record and are rechecked at promotion. */
|
|
299
342
|
export function validateEnsembleIntegrityReport(value) {
|
|
300
343
|
checkEnsembleSchema('integrityReport', value);
|
|
301
344
|
const report = value;
|
|
@@ -307,6 +350,26 @@ export function validateEnsembleIntegrityReport(value) {
|
|
|
307
350
|
problems.push(`D17 cannot upgrade ${report.upstreamDecision} to ${report.decision}`);
|
|
308
351
|
if (report.decision === 'PROMOTE' && (report.findings.length > 0 || report.pairedDeltas.some(item => !item.passed)))
|
|
309
352
|
problems.push('PROMOTE requires every D17 check to pass');
|
|
353
|
+
const metrics = report.pairedDeltas.map(item => item.metric);
|
|
354
|
+
if (canonicalJson(metrics) !== canonicalJson([...REQUIRED_PAIRED_METRICS].sort(compareEnsembleKeys)))
|
|
355
|
+
problems.push('paired deltas must list every required metric once in canonical order');
|
|
356
|
+
if (canonicalJson(report.findings) !== canonicalJson([...new Set(report.findings)].sort()))
|
|
357
|
+
problems.push('findings must be unique and sorted');
|
|
358
|
+
const expected = integrityMetadataFindings(report.integrity, Math.max(...report.pairedDeltas.map(item => item.minimumPairs)));
|
|
359
|
+
for (const item of report.pairedDeltas) {
|
|
360
|
+
const finding = pairedDeltaFinding(item, item);
|
|
361
|
+
if (item.passed !== (finding === null))
|
|
362
|
+
problems.push(`paired delta ${item.metric} passed flag does not match its threshold`);
|
|
363
|
+
// A missing observation is carried as delta null / pairs 0, so either label records the failure.
|
|
364
|
+
if (finding && !(finding === `paired-delta-unknown:${item.metric}` && report.findings.includes(`paired-delta-missing:${item.metric}`)))
|
|
365
|
+
expected.push(finding);
|
|
366
|
+
}
|
|
367
|
+
for (const finding of expected)
|
|
368
|
+
if (!report.findings.includes(finding))
|
|
369
|
+
problems.push(`finding ${finding} is missing`);
|
|
370
|
+
const decision = ensembleIntegrityDecision(report.integrity, report.findings.length);
|
|
371
|
+
if (report.decision !== decision)
|
|
372
|
+
problems.push(`decision ${report.decision} does not follow from its integrity and findings (${decision})`);
|
|
310
373
|
if (digest !== ensembleContractDigest(payload))
|
|
311
374
|
problems.push('integrity report digest does not match its content');
|
|
312
375
|
semantic(problems, 'ensemble integrity report rejected');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { championChallengerEligibilityProblems, ensembleContractDigest, EnsembleContractError, validateChampionChallenger, validateEnsembleIntegrityReport, } from './contract.js';
|
|
1
|
+
import { championChallengerEligibilityProblems, ensembleContractDigest, EnsembleContractError, ensembleIntegrityDecision, integrityMetadataFindings, pairedDeltaFinding, validateChampionChallenger, validateEnsembleIntegrityReport, } from './contract.js';
|
|
2
2
|
/** Extends the eval-integrity report with paired champion/challenger evidence. D17 findings can
|
|
3
3
|
* only hold or roll back: HOLD and ROLLBACK from the upstream gate are never upgraded. */
|
|
4
4
|
export function buildEnsembleIntegrityReport(input) {
|
|
@@ -10,24 +10,8 @@ export function buildEnsembleIntegrityReport(input) {
|
|
|
10
10
|
else
|
|
11
11
|
for (const problem of championChallengerEligibilityProblems(record, input.eligibility))
|
|
12
12
|
findings.add(`d09-${problem}`);
|
|
13
|
-
|
|
14
|
-
findings.add(
|
|
15
|
-
if (integrity.integrity_mode === 'standard')
|
|
16
|
-
findings.add('integrity-mode-standard');
|
|
17
|
-
if (integrity.trusted_score_source === 'local-unverified')
|
|
18
|
-
findings.add('untrusted-score-source');
|
|
19
|
-
if (integrity.fresh_workspace_required && !integrity.fresh_workspace_verified)
|
|
20
|
-
findings.add('fresh-workspace-unverified');
|
|
21
|
-
if (integrity.uncertainty === null)
|
|
22
|
-
findings.add('uncertainty-missing');
|
|
23
|
-
if (integrity.paired_baseline === null)
|
|
24
|
-
findings.add('paired-baseline-missing');
|
|
25
|
-
if (integrity.weak_signal_reason !== null)
|
|
26
|
-
findings.add('weak-signal');
|
|
27
|
-
if (integrity.compromise_labels.length > 0)
|
|
28
|
-
findings.add('compromised');
|
|
29
|
-
if (integrity.sample_n < Math.max(...record.pairedMetrics.map(item => item.minimumPairs)))
|
|
30
|
-
findings.add('insufficient-samples');
|
|
13
|
+
for (const finding of integrityMetadataFindings(integrity, Math.max(...record.pairedMetrics.map(item => item.minimumPairs))))
|
|
14
|
+
findings.add(finding);
|
|
31
15
|
const observed = new Map();
|
|
32
16
|
for (const item of input.pairedDeltas) {
|
|
33
17
|
if (observed.has(item.metric))
|
|
@@ -36,31 +20,13 @@ export function buildEnsembleIntegrityReport(input) {
|
|
|
36
20
|
}
|
|
37
21
|
const pairedDeltas = record.pairedMetrics.map(threshold => {
|
|
38
22
|
const item = observed.get(threshold.metric);
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
findings.add(`paired-delta-missing:${threshold.metric}`);
|
|
44
|
-
passed = false;
|
|
45
|
-
}
|
|
46
|
-
else if (delta === null || !Number.isFinite(delta)) {
|
|
47
|
-
findings.add(`paired-delta-unknown:${threshold.metric}`);
|
|
48
|
-
passed = false;
|
|
49
|
-
}
|
|
50
|
-
else if (!Number.isSafeInteger(pairs) || pairs < threshold.minimumPairs) {
|
|
51
|
-
findings.add(`paired-delta-insufficient:${threshold.metric}`);
|
|
52
|
-
passed = false;
|
|
53
|
-
}
|
|
54
|
-
else if (threshold.comparison === 'delta-at-least' ? delta < threshold.bound : delta > threshold.bound) {
|
|
55
|
-
findings.add(`paired-delta-failed:${threshold.metric}`);
|
|
56
|
-
passed = false;
|
|
57
|
-
}
|
|
58
|
-
return { ...threshold, delta, pairs, passed };
|
|
23
|
+
const finding = pairedDeltaFinding(threshold, item);
|
|
24
|
+
if (finding)
|
|
25
|
+
findings.add(finding);
|
|
26
|
+
return { ...threshold, delta: item?.delta ?? null, pairs: item?.pairs ?? 0, passed: finding === null };
|
|
59
27
|
}).sort((a, b) => a.metric < b.metric ? -1 : a.metric > b.metric ? 1 : 0);
|
|
60
28
|
const upstreamDecision = integrity.release_gate.decision;
|
|
61
|
-
const
|
|
62
|
-
const decision = upstreamDecision === 'ROLLBACK' || compromised ? 'ROLLBACK'
|
|
63
|
-
: upstreamDecision === 'HOLD' || findings.size > 0 ? 'HOLD' : 'PROMOTE';
|
|
29
|
+
const decision = ensembleIntegrityDecision(integrity, findings.size);
|
|
64
30
|
const payload = {
|
|
65
31
|
schemaVersion: 'decision-ensemble-integrity-report/v1',
|
|
66
32
|
subject: { kind: 'champion-challenger', id: record.id, digest, eligibilityId: record.eligibilityId },
|