@aiwg/cli 2026.9.24 → 2026.10.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/agentic/code/providers/capability-matrix.yaml +2 -1
- package/dist/src/artifacts/discovery-shadow-evaluator.js +177 -0
- package/dist/src/artifacts/discovery-shadow.js +195 -0
- package/dist/src/artifacts/index-builder.js +47 -9
- package/dist/src/artifacts/query-engine.js +94 -1
- package/dist/src/artifacts/types.js +1 -0
- package/dist/src/cli/handlers/decision.js +177 -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 +29 -3
- package/dist/src/decision/ask.js +352 -0
- 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 +432 -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 +13 -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/jev-credentials.js +121 -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/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 +228 -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 +40 -18
- 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
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { validateGateDocument } from './schema.js';
|
|
2
|
+
import { splitPackId } from './registry.js';
|
|
3
|
+
const OUTCOME_RANK = { PROMOTE: 0, HOLD: 1, ROLLBACK: 2 };
|
|
4
|
+
const OUTCOMES = ['PROMOTE', 'HOLD', 'ROLLBACK'];
|
|
5
|
+
const VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
6
|
+
const DIGEST_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
7
|
+
/**
|
|
8
|
+
* Operator default floor (ADR section 12): every decision study observes the
|
|
9
|
+
* eval-integrity ceiling. This is a reference to the shipped
|
|
10
|
+
* `aiwg:decision-engine/integrity-ceiling` pack — the single source of truth
|
|
11
|
+
* — applied at expansion time (`expandFloorPacks`), never an inline copy.
|
|
12
|
+
* The default is suppressed only by a configured floor gate with id
|
|
13
|
+
* `integrity-ceiling` that is an all-scoped `upstream-ceiling` gate
|
|
14
|
+
* tightening the shipped gate (floor flag included).
|
|
15
|
+
*/
|
|
16
|
+
export const INTEGRITY_CEILING_FLOOR_PACK_ID = 'aiwg:decision-engine/integrity-ceiling';
|
|
17
|
+
export const INTEGRITY_CEILING_FLOOR_PACK_VERSION = '1.0.0';
|
|
18
|
+
/**
|
|
19
|
+
* A binding ceiling satisfies the configured per-study ceiling when it is at
|
|
20
|
+
* least as strict. An absent configured ceiling is always satisfied.
|
|
21
|
+
*/
|
|
22
|
+
export function projectCeilingSatisfied(declared, configured) {
|
|
23
|
+
if (configured === undefined)
|
|
24
|
+
return true;
|
|
25
|
+
return OUTCOME_RANK[declared ?? 'PROMOTE'] >= OUTCOME_RANK[configured];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Resolves the effective project floors: the configured entries, verbatim.
|
|
29
|
+
* The operator default integrity-ceiling floor is NOT injected here — it is
|
|
30
|
+
* applied at expansion time (`expandFloorPacks`) from the shipped
|
|
31
|
+
* `aiwg:decision-engine/integrity-ceiling` pack, where the registry can prove
|
|
32
|
+
* (via `assertGateTightens`) whether a configured floor genuinely tightens
|
|
33
|
+
* it. A same-id gate that is not an all-scoped `upstream-ceiling` tightening
|
|
34
|
+
* never suppresses the default; it is flagged by `validateGatesConfig` and
|
|
35
|
+
* fails closed at resolution.
|
|
36
|
+
*/
|
|
37
|
+
export function resolveProjectFloors(gates) {
|
|
38
|
+
assertCeilingDefaults(gates?.ceilings);
|
|
39
|
+
return {
|
|
40
|
+
floors: [...(gates?.floors ?? [])],
|
|
41
|
+
ceilings: { ...(gates?.ceilings ?? {}) },
|
|
42
|
+
...(gates?.providers === undefined ? {} : { providers: [...gates.providers] }),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The star-ceiling rule (R1/C6), enforced wherever ceilings are consumed —
|
|
47
|
+
* `resolveProjectFloors` and binding resolution — not only by
|
|
48
|
+
* `validateGatesConfig`: any per-study ceiling requires a valid `'*'`
|
|
49
|
+
* default, and no per-study ceiling may loosen it. Throws on violation.
|
|
50
|
+
*/
|
|
51
|
+
export function assertCeilingDefaults(ceilings) {
|
|
52
|
+
if (ceilings === undefined)
|
|
53
|
+
return;
|
|
54
|
+
if (!ceilings || typeof ceilings !== 'object' || Array.isArray(ceilings)) {
|
|
55
|
+
throw new Error('gates.ceilings: must be an object mapping study ids to outcome ceilings');
|
|
56
|
+
}
|
|
57
|
+
const star = ceilings['*'];
|
|
58
|
+
const starValid = typeof star === 'string' && OUTCOMES.includes(star);
|
|
59
|
+
for (const [study, ceiling] of Object.entries(ceilings)) {
|
|
60
|
+
if (typeof ceiling !== 'string' || !OUTCOMES.includes(ceiling)) {
|
|
61
|
+
throw new Error(`gates.ceilings.${study}: must be PROMOTE, HOLD or ROLLBACK`);
|
|
62
|
+
}
|
|
63
|
+
if (study === '*')
|
|
64
|
+
continue;
|
|
65
|
+
if (!starValid)
|
|
66
|
+
throw new Error(`gates.ceilings: per-study ceilings require the project-wide '*' default ceiling`);
|
|
67
|
+
if (OUTCOME_RANK[ceiling] < OUTCOME_RANK[star]) {
|
|
68
|
+
throw new Error(`gates.ceilings.${study}: must tighten the project default ceiling ${String(star)}, not loosen it`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const isRecord = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
73
|
+
/**
|
|
74
|
+
* Validates the `gates` section of `.aiwg/aiwg.config`, returning human-readable
|
|
75
|
+
* error strings (empty = valid). Follows the hand-rolled aiwg.config convention
|
|
76
|
+
* (`validateIndexConfig`, `validateExternalLinks`): unknown fields, non-literal
|
|
77
|
+
* shapes and unparseable pins fail closed here, before any binding resolves.
|
|
78
|
+
* Inline floor packs are validated against the closed GatePack schema, and
|
|
79
|
+
* their ids must use the `project:` namespace; pack references may point at
|
|
80
|
+
* any registered pack (typically an `aiwg:` pack such as the integrity-ceiling
|
|
81
|
+
* pack, or a `project:` pack).
|
|
82
|
+
*/
|
|
83
|
+
export function validateGatesConfig(gates) {
|
|
84
|
+
if (gates === undefined || gates === null)
|
|
85
|
+
return [];
|
|
86
|
+
if (!isRecord(gates))
|
|
87
|
+
return ['gates: must be an object'];
|
|
88
|
+
const errors = [];
|
|
89
|
+
for (const field of Object.keys(gates)) {
|
|
90
|
+
if (field !== 'floors' && field !== 'ceilings' && field !== 'providers') {
|
|
91
|
+
errors.push(`gates.${field}: unknown field`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (gates.floors !== undefined) {
|
|
95
|
+
if (!Array.isArray(gates.floors)) {
|
|
96
|
+
errors.push('gates.floors: must be an array');
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
gates.floors.forEach((entry, index) => {
|
|
100
|
+
errors.push(...validateFloorSource(entry, `gates.floors[${index}]`));
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (gates.ceilings !== undefined) {
|
|
105
|
+
if (!isRecord(gates.ceilings)) {
|
|
106
|
+
errors.push('gates.ceilings: must be an object mapping study ids to outcome ceilings');
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
for (const [study, ceiling] of Object.entries(gates.ceilings)) {
|
|
110
|
+
if (!study.trim())
|
|
111
|
+
errors.push('gates.ceilings: study id must be a non-empty string');
|
|
112
|
+
else if (typeof ceiling !== 'string' || !OUTCOMES.includes(ceiling)) {
|
|
113
|
+
errors.push(`gates.ceilings.${study}: must be PROMOTE, HOLD or ROLLBACK`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const star = gates.ceilings['*'];
|
|
117
|
+
const studies = Object.entries(gates.ceilings).filter(([study]) => study !== '*');
|
|
118
|
+
// A per-study ceiling without the project-wide default is a rename
|
|
119
|
+
// escape: `study-a-v2` would silently inherit no ceiling. Require '*'.
|
|
120
|
+
if (studies.length > 0 && !(typeof star === 'string' && OUTCOMES.includes(star))) {
|
|
121
|
+
errors.push(`gates.ceilings: per-study ceilings require the project-wide '*' default ceiling`);
|
|
122
|
+
}
|
|
123
|
+
if (typeof star === 'string' && OUTCOMES.includes(star)) {
|
|
124
|
+
for (const [study, ceiling] of Object.entries(gates.ceilings)) {
|
|
125
|
+
if (study !== '*' && typeof ceiling === 'string'
|
|
126
|
+
&& OUTCOMES.includes(ceiling)
|
|
127
|
+
&& OUTCOME_RANK[ceiling] < OUTCOME_RANK[star]) {
|
|
128
|
+
errors.push(`gates.ceilings.${study}: must tighten the project default ceiling ${star}, not loosen it`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (gates.providers !== undefined) {
|
|
135
|
+
if (!Array.isArray(gates.providers)) {
|
|
136
|
+
errors.push('gates.providers: must be an array');
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
const seen = new Set();
|
|
140
|
+
gates.providers.forEach((entry, index) => {
|
|
141
|
+
errors.push(...validateProviderAllowlistEntry(entry, `gates.providers[${index}]`, seen));
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return errors;
|
|
146
|
+
}
|
|
147
|
+
function validateProviderAllowlistEntry(entry, where, seen) {
|
|
148
|
+
if (!isRecord(entry))
|
|
149
|
+
return [`${where}: must be an object`];
|
|
150
|
+
const errors = [];
|
|
151
|
+
for (const field of Object.keys(entry)) {
|
|
152
|
+
if (field !== 'bundleId' && field !== 'providerId' && field !== 'codeDigest'
|
|
153
|
+
&& field !== 'reviewer' && field !== 'reviewedAt') {
|
|
154
|
+
errors.push(`${where}.${field}: unknown field`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (typeof entry.bundleId !== 'string' || !entry.bundleId.trim()) {
|
|
158
|
+
errors.push(`${where}.bundleId: required, must be a non-empty string`);
|
|
159
|
+
}
|
|
160
|
+
if (typeof entry.providerId !== 'string' || !entry.providerId.trim()) {
|
|
161
|
+
errors.push(`${where}.providerId: required, must be a non-empty string`);
|
|
162
|
+
}
|
|
163
|
+
if (typeof entry.codeDigest !== 'string' || !DIGEST_PATTERN.test(entry.codeDigest)) {
|
|
164
|
+
errors.push(`${where}.codeDigest: required, must be a sha256 digest`);
|
|
165
|
+
}
|
|
166
|
+
if (typeof entry.reviewer !== 'string' || !entry.reviewer.trim() || entry.reviewer.length > 128) {
|
|
167
|
+
errors.push(`${where}.reviewer: required, must be a non-empty string`);
|
|
168
|
+
}
|
|
169
|
+
if (typeof entry.reviewedAt !== 'string' || !Number.isFinite(Date.parse(entry.reviewedAt))) {
|
|
170
|
+
errors.push(`${where}.reviewedAt: required, must be a date-time`);
|
|
171
|
+
}
|
|
172
|
+
if (typeof entry.bundleId === 'string' && typeof entry.providerId === 'string') {
|
|
173
|
+
const key = `${entry.bundleId}\0${entry.providerId}`;
|
|
174
|
+
if (seen.has(key))
|
|
175
|
+
errors.push(`${where}: duplicate allowlist entry for ${entry.bundleId} ${entry.providerId}`);
|
|
176
|
+
else
|
|
177
|
+
seen.add(key);
|
|
178
|
+
}
|
|
179
|
+
return errors;
|
|
180
|
+
}
|
|
181
|
+
function validateFloorSource(entry, where) {
|
|
182
|
+
if (!isRecord(entry))
|
|
183
|
+
return [`${where}: must be an object with exactly one of 'pack' or 'packRef'`];
|
|
184
|
+
const keys = Object.keys(entry);
|
|
185
|
+
const unknown = keys.filter(key => key !== 'pack' && key !== 'packRef');
|
|
186
|
+
if (unknown.length)
|
|
187
|
+
return [`${where}.${unknown[0]}: unknown field`];
|
|
188
|
+
if (entry.pack !== undefined && entry.packRef !== undefined) {
|
|
189
|
+
return [`${where}: must set exactly one of 'pack' or 'packRef'`];
|
|
190
|
+
}
|
|
191
|
+
if (entry.pack !== undefined)
|
|
192
|
+
return validateInlineFloorPack(entry.pack, where);
|
|
193
|
+
if (entry.packRef !== undefined)
|
|
194
|
+
return validateFloorPackRef(entry.packRef, where);
|
|
195
|
+
return [`${where}: must set exactly one of 'pack' or 'packRef'`];
|
|
196
|
+
}
|
|
197
|
+
function validateInlineFloorPack(pack, where) {
|
|
198
|
+
let parsed;
|
|
199
|
+
try {
|
|
200
|
+
parsed = validateGateDocument(pack);
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
return [`${where}.pack: ${error instanceof Error ? error.message : 'invalid gate pack'}`];
|
|
204
|
+
}
|
|
205
|
+
if (parsed.kind !== 'GatePack')
|
|
206
|
+
return [`${where}.pack: floor pack must have kind GatePack`];
|
|
207
|
+
try {
|
|
208
|
+
const { namespace } = splitPackId(parsed.metadata.id);
|
|
209
|
+
if (namespace !== 'project') {
|
|
210
|
+
return [`${where}.pack: floor pack id must use the project: namespace (got '${parsed.metadata.id}')`];
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
return [`${where}.pack: ${error instanceof Error ? error.message : 'invalid pack id'}`];
|
|
215
|
+
}
|
|
216
|
+
const errors = [];
|
|
217
|
+
for (const gate of parsed.spec.gates) {
|
|
218
|
+
if (gate.id === 'integrity-ceiling'
|
|
219
|
+
&& (gate.kind !== 'upstream-ceiling' || gate.scope.mode !== 'all')) {
|
|
220
|
+
errors.push(`${where}.pack: floor gate 'integrity-ceiling' must be an all-scoped upstream-ceiling gate`
|
|
221
|
+
+ ` to govern the default ceiling (a weaker same-id gate never suppresses it;`
|
|
222
|
+
+ ` full tightening against the shipped pack is enforced at resolution)`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return errors;
|
|
226
|
+
}
|
|
227
|
+
function validateFloorPackRef(packRef, where) {
|
|
228
|
+
if (!isRecord(packRef))
|
|
229
|
+
return [`${where}.packRef: must be an object`];
|
|
230
|
+
const errors = [];
|
|
231
|
+
for (const field of Object.keys(packRef)) {
|
|
232
|
+
if (field !== 'id' && field !== 'version' && field !== 'digest') {
|
|
233
|
+
errors.push(`${where}.packRef.${field}: unknown field`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (typeof packRef.id !== 'string' || !packRef.id) {
|
|
237
|
+
errors.push(`${where}.packRef.id: required, must be a non-empty string`);
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
try {
|
|
241
|
+
splitPackId(packRef.id);
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
errors.push(`${where}.packRef.id: ${error instanceof Error ? error.message : 'invalid pack id'}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (typeof packRef.version !== 'string' || !VERSION_PATTERN.test(packRef.version)) {
|
|
248
|
+
errors.push(`${where}.packRef.version: required, must be a semantic version (X.Y.Z)`);
|
|
249
|
+
}
|
|
250
|
+
if (typeof packRef.digest !== 'string' || !DIGEST_PATTERN.test(packRef.digest)) {
|
|
251
|
+
errors.push(`${where}.packRef.digest: required, must be a sha256 digest`);
|
|
252
|
+
}
|
|
253
|
+
return errors;
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=floors.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gates capability phase 1 core (epic #2824): declarative gate packs, a pure deterministic
|
|
3
|
+
* evaluator and digest-bound reports. Experimental and default-off: nothing in the
|
|
4
|
+
* decision runtime imports this module, so existing behavior is unchanged.
|
|
5
|
+
*/
|
|
6
|
+
export { GATES_API_VERSION, qualifyGateParameter } from './types.js';
|
|
7
|
+
export { GateSchemaError, validateGateDocument } from './schema.js';
|
|
8
|
+
export { GateRegistryError, GATE_NAMESPACES, splitPackId, validateResolvedPack, resolveThresholdDefault, assertGateTightens, applyGateExtends, composeGatePack, resolveGateBinding, expandFloorPacks, enforceProjectFloors, authoredGatePacksOf, gateProvidersOf, GateRegistry, } from './registry.js';
|
|
9
|
+
export { INTEGRITY_CEILING_FLOOR_PACK_ID, INTEGRITY_CEILING_FLOOR_PACK_VERSION, assertCeilingDefaults, projectCeilingSatisfied, resolveProjectFloors, validateGatesConfig, } from './floors.js';
|
|
10
|
+
export { GateEvaluationError, maxOutcome, gateStatusOutcome, sealUpstream, sealGateHoldout, evaluateGates, } from './evaluate.js';
|
|
11
|
+
export { validateGateReport } from './report.js';
|
|
12
|
+
export { createCoreProviderRegistry, evidenceProvider, pairedProvider, proportionProvider, scalarProvider, screeningProvider } from './providers/index.js';
|
|
13
|
+
export { MetricProviderRegistry } from './providers/index.js';
|
|
14
|
+
export { GATE_PACKS_DIR, GATE_PACK_MAX_BYTES, isGatePackFile, listGatePackFiles, readBundleGatePacksDeclaration, loadGatePackFile, originForPackDir, registerBundleGatePacks, resolveGatePacksDir, discoverShippedGatePacks, } from './discovery.js';
|
|
15
|
+
export { buildGatesRegistry, validateGateFile, loadHoldoutFile, loadUpstreamFile, evaluateGatesFromFiles, installedAiwgRoot, listGatePacks, loadProjectFloorsForEvaluate, showGatePack, packsReferencedByRule, } from './driver.js';
|
|
16
|
+
export { GateProviderError, computeProviderCodeDigest, deriveIsolatedSeed, loadGateBundleProviders, invokeBundleProvider, providerBindingPin, runIsolatedProvider, runIsolatedProviderSync, sealProviderSection, snapshotProviderDir, isLoaderIssuedProvider, isolationLaunchPlan, isolationSandboxStatus, parseIsolatedFrame, probeIsolationSandbox, isBundleProvidersEnabled, GATE_PROVIDER_MAX_FILE_BYTES, GATE_PROVIDER_MAX_FILES, GATE_PROVIDER_MAX_TOTAL_BYTES, GATE_PROVIDER_DEFAULT_TIMEOUT_MS, GATE_PROVIDER_MAX_TIMEOUT_MS, GATE_PROVIDER_DEFAULT_MAX_RECORDS, GATE_PROVIDER_MAX_OUTPUT_BYTES, } from './providers/loader.js';
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { providerSourceDigest, requireRecords } from './types.js';
|
|
2
|
+
/** Sorted, de-duplicated attestations shared by the evidence providers. */
|
|
3
|
+
export function collectAttestations(rows, label) {
|
|
4
|
+
const seen = new Set();
|
|
5
|
+
const available = [];
|
|
6
|
+
for (const row of rows) {
|
|
7
|
+
if (!row || typeof row.id !== 'string' || !row.id.trim() || typeof row.passed !== 'boolean'
|
|
8
|
+
|| (row.expiresAt !== undefined && row.expiresAt !== null && typeof row.expiresAt !== 'string')
|
|
9
|
+
|| seen.has(row.id)) {
|
|
10
|
+
throw new Error(`${label} records require unique nonempty ids, a boolean passed and an optional expiry`);
|
|
11
|
+
}
|
|
12
|
+
seen.add(row.id);
|
|
13
|
+
available.push({ id: row.id, passed: row.passed, ...(row.expiresAt === undefined ? {} : { expiresAt: row.expiresAt }) });
|
|
14
|
+
}
|
|
15
|
+
return [...available].sort((a, b) => a.id.localeCompare(b.id));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Core evidence provider: required-evidence attestations are caller-asserted records
|
|
19
|
+
* evaluated against the binding clock. Powers `evidence` gates. The provider reports
|
|
20
|
+
* presence, pass state and expiry; the gate decides.
|
|
21
|
+
*/
|
|
22
|
+
export const evidenceProvider = {
|
|
23
|
+
id: 'test.evidence/v1',
|
|
24
|
+
version: '1.0.0',
|
|
25
|
+
description: 'Caller-asserted evidence attestations with pass state and expiry.',
|
|
26
|
+
metrics: {
|
|
27
|
+
'attestations': { kind: 'evidence', description: 'Evidence attestations by id.' },
|
|
28
|
+
},
|
|
29
|
+
sourceDigest: providerSourceDigest({ id: 'test.evidence/v1', version: '1.0.0',
|
|
30
|
+
metrics: { 'attestations': { kind: 'evidence' } } }),
|
|
31
|
+
compute(records) {
|
|
32
|
+
const rows = requireRecords(records, 'evidence');
|
|
33
|
+
const pooled = { available: collectAttestations(rows, 'evidence') };
|
|
34
|
+
return { version: '1.0.0', sourceDigest: evidenceProvider.sourceDigest,
|
|
35
|
+
metrics: { 'attestations': { bySlice: {}, pooled } } };
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=evidence.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { evidenceProvider } from './evidence.js';
|
|
2
|
+
import { pairedProvider } from './paired.js';
|
|
3
|
+
import { proportionProvider } from './proportion.js';
|
|
4
|
+
import { MetricProviderRegistry } from './registry.js';
|
|
5
|
+
import { scalarProvider } from './scalar.js';
|
|
6
|
+
import { screeningProvider } from './screening.js';
|
|
7
|
+
export { MetricProviderRegistry } from './registry.js';
|
|
8
|
+
export { evidenceProvider } from './evidence.js';
|
|
9
|
+
export { pairedProvider } from './paired.js';
|
|
10
|
+
export { proportionProvider } from './proportion.js';
|
|
11
|
+
export { scalarProvider } from './scalar.js';
|
|
12
|
+
export { screeningProvider } from './screening.js';
|
|
13
|
+
/** Core providers registered for v1alpha1 offline evaluation. */
|
|
14
|
+
export function createCoreProviderRegistry() {
|
|
15
|
+
const registry = new MetricProviderRegistry();
|
|
16
|
+
const providers = [proportionProvider, pairedProvider, scalarProvider, evidenceProvider, screeningProvider];
|
|
17
|
+
for (const provider of providers)
|
|
18
|
+
registry.register(provider);
|
|
19
|
+
return registry;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=index.js.map
|