@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.
Files changed (210) hide show
  1. package/agentic/code/providers/capability-matrix.yaml +2 -1
  2. package/dist/src/artifacts/cli.js +23 -18
  3. package/dist/src/artifacts/discovery-shadow-evaluator.js +177 -0
  4. package/dist/src/artifacts/discovery-shadow.js +195 -0
  5. package/dist/src/artifacts/fortemi-core-query-adapter.js +6 -2
  6. package/dist/src/artifacts/index-builder.js +47 -9
  7. package/dist/src/artifacts/query-engine.js +108 -5
  8. package/dist/src/artifacts/types.js +1 -0
  9. package/dist/src/cli/handlers/decision.js +88 -0
  10. package/dist/src/cli/handlers/gates.js +154 -0
  11. package/dist/src/cli/handlers/index.js +5 -1
  12. package/dist/src/cli/handlers/sessions.js +10 -7
  13. package/dist/src/cli/handlers/utilities.js +20 -0
  14. package/dist/src/config/aiwg-config.js +15 -2
  15. package/dist/src/decision/acceptance.js +25 -0
  16. package/dist/src/decision/adapters/jev.js +24 -2
  17. package/dist/src/decision/calibration/registry.js +9 -0
  18. package/dist/src/decision/compose.js +74 -15
  19. package/dist/src/decision/context-live-promotion.js +344 -0
  20. package/dist/src/decision/context-live-qualification.js +591 -0
  21. package/dist/src/decision/context-pruning.js +847 -0
  22. package/dist/src/decision/driver.js +430 -0
  23. package/dist/src/decision/egress-live-qualification.js +874 -0
  24. package/dist/src/decision/ensemble/contract.js +64 -1
  25. package/dist/src/decision/ensemble/index.js +1 -0
  26. package/dist/src/decision/ensemble/report.js +8 -42
  27. package/dist/src/decision/ensemble/runtime.js +571 -0
  28. package/dist/src/decision/ensemble-study/artifacts.js +85 -0
  29. package/dist/src/decision/ensemble-study/calibration.js +443 -0
  30. package/dist/src/decision/ensemble-study/corpus.js +229 -0
  31. package/dist/src/decision/ensemble-study/multifact-artifacts.js +23 -0
  32. package/dist/src/decision/ensemble-study/multifact-study.js +596 -0
  33. package/dist/src/decision/ensemble-study/multifact.js +241 -0
  34. package/dist/src/decision/ensemble-study/protocol.js +77 -0
  35. package/dist/src/decision/ensemble-study/score.js +462 -0
  36. package/dist/src/decision/ensemble-study/staged.js +87 -0
  37. package/dist/src/decision/ensemble-study/statistics.js +84 -0
  38. package/dist/src/decision/evaluate.js +227 -14
  39. package/dist/src/decision/export.js +4 -0
  40. package/dist/src/decision/feature-export.js +1074 -0
  41. package/dist/src/decision/graph-index.js +16 -0
  42. package/dist/src/decision/graph-live-qualification.js +1041 -0
  43. package/dist/src/decision/graph-live-workload.js +245 -0
  44. package/dist/src/decision/graph-skill-bridge.js +21 -3
  45. package/dist/src/decision/heldout/calibration.js +140 -0
  46. package/dist/src/decision/heldout/collector.js +430 -0
  47. package/dist/src/decision/heldout/contract.js +309 -0
  48. package/dist/src/decision/heldout/d29-generator-ids.js +12 -0
  49. package/dist/src/decision/heldout/d29-passage-baseline-v2.js +93 -0
  50. package/dist/src/decision/heldout/d29-passage-baseline-v3.js +100 -0
  51. package/dist/src/decision/heldout/d29-passage-baseline.js +66 -0
  52. package/dist/src/decision/heldout/d29-pools-v8.js +575 -0
  53. package/dist/src/decision/heldout/d29-pools.js +288 -0
  54. package/dist/src/decision/heldout/d29-v6.js +169 -0
  55. package/dist/src/decision/heldout/d29-v7.js +202 -0
  56. package/dist/src/decision/heldout/d29-v8.js +586 -0
  57. package/dist/src/decision/heldout/generator-registry.js +67 -0
  58. package/dist/src/decision/heldout/generators.js +696 -0
  59. package/dist/src/decision/heldout/index.js +8 -0
  60. package/dist/src/decision/heldout/journal.js +346 -0
  61. package/dist/src/decision/heldout/study-generators.js +64 -0
  62. package/dist/src/decision/heldout/types.js +2 -0
  63. package/dist/src/decision/host-policy.js +61 -0
  64. package/dist/src/decision/index.js +11 -0
  65. package/dist/src/decision/interop-profile.v1.json +112 -0
  66. package/dist/src/decision/interop.js +653 -0
  67. package/dist/src/decision/issue-triage/index.js +3 -0
  68. package/dist/src/decision/issue-triage/runtime.js +1069 -0
  69. package/dist/src/decision/issue-triage/types.js +2 -0
  70. package/dist/src/decision/patterns/catalog.js +28 -8
  71. package/dist/src/decision/patterns/playground.js +28 -11
  72. package/dist/src/decision/patterns/specs.js +19 -10
  73. package/dist/src/decision/preprocessed-evidence.js +724 -0
  74. package/dist/src/decision/qualification/capture.js +8 -2
  75. package/dist/src/decision/qualification/gate-evidence.js +19 -4
  76. package/dist/src/decision/qualification/load.js +8 -1
  77. package/dist/src/decision/qualification/quality.js +57 -49
  78. package/dist/src/decision/qualification/release.js +76 -3
  79. package/dist/src/decision/qualification/runner.js +5 -2
  80. package/dist/src/decision/routing/contract.js +175 -0
  81. package/dist/src/decision/routing/index.js +5 -0
  82. package/dist/src/decision/routing/report.js +216 -0
  83. package/dist/src/decision/routing/runtime.js +685 -0
  84. package/dist/src/decision/routing/types.js +2 -0
  85. package/dist/src/decision/sdlc-screening.js +1157 -0
  86. package/dist/src/decision/sensitivity/comparative.js +154 -0
  87. package/dist/src/decision/sensitivity/contract.js +218 -0
  88. package/dist/src/decision/sensitivity/index.js +5 -0
  89. package/dist/src/decision/sensitivity/runtime.js +912 -0
  90. package/dist/src/decision/sensitivity/types.js +2 -0
  91. package/dist/src/decision/validate.js +26 -0
  92. package/dist/src/extensions/commands/definitions.js +38 -0
  93. package/dist/src/extensions/manifest.js +44 -0
  94. package/dist/src/gates/discovery.js +315 -0
  95. package/dist/src/gates/driver.js +388 -0
  96. package/dist/src/gates/evaluate.js +719 -0
  97. package/dist/src/gates/floors.js +255 -0
  98. package/dist/src/gates/index.js +17 -0
  99. package/dist/src/gates/providers/evidence.js +38 -0
  100. package/dist/src/gates/providers/index.js +21 -0
  101. package/dist/src/gates/providers/isolated-child-source.js +446 -0
  102. package/dist/src/gates/providers/loader.js +1069 -0
  103. package/dist/src/gates/providers/paired.js +52 -0
  104. package/dist/src/gates/providers/proportion.js +60 -0
  105. package/dist/src/gates/providers/registry.js +40 -0
  106. package/dist/src/gates/providers/scalar.js +41 -0
  107. package/dist/src/gates/providers/screening.js +53 -0
  108. package/dist/src/gates/providers/types.js +25 -0
  109. package/dist/src/gates/registry.js +1003 -0
  110. package/dist/src/gates/report.js +102 -0
  111. package/dist/src/gates/schema.js +56 -0
  112. package/dist/src/gates/stats/binomial.js +26 -0
  113. package/dist/src/gates/stats/bootstrap.js +62 -0
  114. package/dist/src/gates/stats/clopper-pearson.js +95 -0
  115. package/dist/src/gates/stats/digest.js +26 -0
  116. package/dist/src/gates/stats/error.js +5 -0
  117. package/dist/src/gates/stats/index.js +9 -0
  118. package/dist/src/gates/stats/normal.js +35 -0
  119. package/dist/src/gates/stats/paired.js +120 -0
  120. package/dist/src/gates/stats/splits.js +30 -0
  121. package/dist/src/gates/types.js +8 -0
  122. package/dist/src/governance/redaction.js +14 -4
  123. package/dist/src/mcp/muse-native-config.mjs +123 -0
  124. package/dist/src/mcp/tools/decision.mjs +188 -0
  125. package/dist/src/mcp/tools/subsystems.mjs +2 -0
  126. package/dist/src/providers/capability-matrix.yaml +2 -1
  127. package/dist/src/providers/provider-definitions.js +2 -1
  128. package/dist/src/sessions/adapters/muse.js +336 -39
  129. package/dist/src/sessions/batch-import.js +7 -0
  130. package/dist/src/sessions/workspace-discovery.js +13 -2
  131. package/package.json +1 -1
  132. package/schemas/decision/ConformalFrozenOpenData.v2.schema.json +371 -0
  133. package/schemas/decision/ConformalOpenDataReport.v2.schema.json +421 -0
  134. package/schemas/decision/ConformalPreregistration.v2.schema.json +529 -0
  135. package/schemas/decision/ContextPruningCandidate.v1.schema.json +47 -0
  136. package/schemas/decision/ContextPruningEvaluationReport.v1.schema.json +758 -0
  137. package/schemas/decision/ContextPruningPreregistration.v1.schema.json +175 -0
  138. package/schemas/decision/ContextPruningReceipt.v1.schema.json +72 -0
  139. package/schemas/decision/D17Multifact.v1.schema.json +1851 -0
  140. package/schemas/decision/D17StudyAnalysis.v1.schema.json +42 -0
  141. package/schemas/decision/D17StudyAnalysis.v2.schema.json +51 -0
  142. package/schemas/decision/D17StudyCalibration.v1.schema.json +819 -0
  143. package/schemas/decision/D17StudyDryRun.v1.schema.json +169 -0
  144. package/schemas/decision/D17StudyDryRun.v2.schema.json +239 -0
  145. package/schemas/decision/D17StudyGold.v1.schema.json +108 -0
  146. package/schemas/decision/D17StudyGuide.v1.schema.json +63 -0
  147. package/schemas/decision/D17StudyNativeTemplates.v1.schema.json +619 -0
  148. package/schemas/decision/D17StudyProtocol.v1.schema.json +241 -0
  149. package/schemas/decision/D17StudyReport.v1.schema.json +902 -0
  150. package/schemas/decision/D17StudyReport.v2.schema.json +1319 -0
  151. package/schemas/decision/D17StudyReview.v1.schema.json +175 -0
  152. package/schemas/decision/D17StudySplits.v1.schema.json +217 -0
  153. package/schemas/decision/D29Study.v1.schema.json +1903 -0
  154. package/schemas/decision/D29Study.v2.schema.json +1344 -0
  155. package/schemas/decision/D29Study.v3.schema.json +609 -0
  156. package/schemas/decision/D29Study.v4.schema.json +1133 -0
  157. package/schemas/decision/D29Study.v6.schema.json +1205 -0
  158. package/schemas/decision/D29Study.v7.schema.json +1471 -0
  159. package/schemas/decision/D29Study.v8.schema.json +671 -0
  160. package/schemas/decision/D29Study.v9.schema.json +778 -0
  161. package/schemas/decision/DecisionComparativeReplayAuditSample.v1.schema.json +137 -0
  162. package/schemas/decision/DecisionComparativeReplayCorpus.v1.schema.json +258 -0
  163. package/schemas/decision/DecisionComparativeReplayFreeze.v1.schema.json +74 -0
  164. package/schemas/decision/DecisionComparativeReplayGold.v1.schema.json +50 -0
  165. package/schemas/decision/DecisionComparativeReplayGoldAsset.v1.schema.json +37 -0
  166. package/schemas/decision/DecisionComparativeReplayIntegrity.v1.schema.json +81 -0
  167. package/schemas/decision/DecisionComparativeReplayMembers.v1.schema.json +52 -0
  168. package/schemas/decision/DecisionComparativeReplayPreregistration.v1.schema.json +113 -0
  169. package/schemas/decision/DecisionComparativeReplayReport.v1.schema.json +407 -0
  170. package/schemas/decision/DecisionComparativeReplayReviewPackets.v1.schema.json +260 -0
  171. package/schemas/decision/DecisionComparativeReplaySplit.v1.schema.json +84 -0
  172. package/schemas/decision/DecisionFeatureObservation.v1.schema.json +564 -0
  173. package/schemas/decision/DecisionFeatureSet.v1.schema.json +155 -0
  174. package/schemas/decision/DecisionInteropMapping.v1.schema.json +85 -0
  175. package/schemas/decision/DecisionIssueTriageEvaluationManifest.v1.schema.json +174 -0
  176. package/schemas/decision/DecisionIssueTriageEvaluationReport.v1.schema.json +280 -0
  177. package/schemas/decision/DecisionIssueTriagePilotPack.v1.schema.json +114 -0
  178. package/schemas/decision/DecisionRouteReceipt.v1.schema.json +155 -0
  179. package/schemas/decision/DecisionRoutingPolicy.v1.schema.json +132 -0
  180. package/schemas/decision/DecisionRoutingShadowReport.v1.schema.json +170 -0
  181. package/schemas/decision/DecisionRoutingTask.v1.schema.json +49 -0
  182. package/schemas/decision/DecisionRuleset.schema.json +8 -2
  183. package/schemas/decision/DecisionRuleset.v1alpha2.schema.json +8 -2
  184. package/schemas/decision/DecisionSensitivityPlan.v1.schema.json +191 -0
  185. package/schemas/decision/DecisionSensitivityReport.v1.schema.json +163 -0
  186. package/schemas/decision/HeldoutApproval.v1.schema.json +312 -0
  187. package/schemas/decision/HeldoutAttempt.v1.schema.json +211 -0
  188. package/schemas/decision/HeldoutBaseline.v1.schema.json +90 -0
  189. package/schemas/decision/HeldoutCalibrationPhase.v1.schema.json +87 -0
  190. package/schemas/decision/HeldoutCorpus.v1.schema.json +167 -0
  191. package/schemas/decision/HeldoutEvent.v1.schema.json +41 -0
  192. package/schemas/decision/HeldoutFrozen.v1.schema.json +142 -0
  193. package/schemas/decision/HeldoutPreregistration.v1.schema.json +222 -0
  194. package/schemas/decision/HeldoutSpendEvent.v1.schema.json +122 -0
  195. package/schemas/decision/HeldoutSpendHead.v1.schema.json +25 -0
  196. package/schemas/decision/HeldoutSpendHead.v2.schema.json +46 -0
  197. package/schemas/decision/HeldoutSummary.v1.schema.json +101 -0
  198. package/schemas/decision/OpaDecisionLogExport.v1.schema.json +65 -0
  199. package/schemas/decision/PreprocessedEvidence.v1.schema.json +306 -0
  200. package/schemas/decision/RulesetResult.v1alpha2.schema.json +175 -0
  201. package/schemas/decision/SdlcEvidenceScreening.v1.schema.json +499 -0
  202. package/schemas/decision/SdlcScreeningPreregistration.v1.schema.json +132 -0
  203. package/schemas/decision/SdlcScreeningPreregistration.v2.schema.json +138 -0
  204. package/schemas/decision/SdlcScreeningRelease.v1.schema.json +654 -0
  205. package/schemas/decision/SdlcScreeningRelease.v2.schema.json +654 -0
  206. package/tools/agents/deploy-agents.mjs +1 -1
  207. package/tools/agents/providers/base.mjs +26 -7
  208. package/tools/agents/providers/factory.mjs +10 -2
  209. package/tools/agents/providers/muse-hooks.mjs +1 -29
  210. 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