@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.
Files changed (209) hide show
  1. package/agentic/code/providers/capability-matrix.yaml +2 -1
  2. package/dist/src/artifacts/discovery-shadow-evaluator.js +177 -0
  3. package/dist/src/artifacts/discovery-shadow.js +195 -0
  4. package/dist/src/artifacts/index-builder.js +47 -9
  5. package/dist/src/artifacts/query-engine.js +94 -1
  6. package/dist/src/artifacts/types.js +1 -0
  7. package/dist/src/cli/handlers/decision.js +177 -0
  8. package/dist/src/cli/handlers/gates.js +154 -0
  9. package/dist/src/cli/handlers/index.js +5 -1
  10. package/dist/src/cli/handlers/sessions.js +10 -7
  11. package/dist/src/cli/handlers/utilities.js +20 -0
  12. package/dist/src/config/aiwg-config.js +15 -2
  13. package/dist/src/decision/acceptance.js +25 -0
  14. package/dist/src/decision/adapters/jev.js +29 -3
  15. package/dist/src/decision/ask.js +352 -0
  16. package/dist/src/decision/calibration/registry.js +9 -0
  17. package/dist/src/decision/compose.js +74 -15
  18. package/dist/src/decision/context-live-promotion.js +344 -0
  19. package/dist/src/decision/context-live-qualification.js +591 -0
  20. package/dist/src/decision/context-pruning.js +847 -0
  21. package/dist/src/decision/driver.js +432 -0
  22. package/dist/src/decision/egress-live-qualification.js +874 -0
  23. package/dist/src/decision/ensemble/contract.js +64 -1
  24. package/dist/src/decision/ensemble/index.js +1 -0
  25. package/dist/src/decision/ensemble/report.js +8 -42
  26. package/dist/src/decision/ensemble/runtime.js +571 -0
  27. package/dist/src/decision/ensemble-study/artifacts.js +85 -0
  28. package/dist/src/decision/ensemble-study/calibration.js +443 -0
  29. package/dist/src/decision/ensemble-study/corpus.js +229 -0
  30. package/dist/src/decision/ensemble-study/multifact-artifacts.js +23 -0
  31. package/dist/src/decision/ensemble-study/multifact-study.js +596 -0
  32. package/dist/src/decision/ensemble-study/multifact.js +241 -0
  33. package/dist/src/decision/ensemble-study/protocol.js +77 -0
  34. package/dist/src/decision/ensemble-study/score.js +462 -0
  35. package/dist/src/decision/ensemble-study/staged.js +87 -0
  36. package/dist/src/decision/ensemble-study/statistics.js +84 -0
  37. package/dist/src/decision/evaluate.js +227 -14
  38. package/dist/src/decision/export.js +4 -0
  39. package/dist/src/decision/feature-export.js +1074 -0
  40. package/dist/src/decision/graph-index.js +16 -0
  41. package/dist/src/decision/graph-live-qualification.js +1041 -0
  42. package/dist/src/decision/graph-live-workload.js +245 -0
  43. package/dist/src/decision/graph-skill-bridge.js +21 -3
  44. package/dist/src/decision/heldout/calibration.js +140 -0
  45. package/dist/src/decision/heldout/collector.js +430 -0
  46. package/dist/src/decision/heldout/contract.js +309 -0
  47. package/dist/src/decision/heldout/d29-generator-ids.js +12 -0
  48. package/dist/src/decision/heldout/d29-passage-baseline-v2.js +93 -0
  49. package/dist/src/decision/heldout/d29-passage-baseline-v3.js +100 -0
  50. package/dist/src/decision/heldout/d29-passage-baseline.js +66 -0
  51. package/dist/src/decision/heldout/d29-pools-v8.js +575 -0
  52. package/dist/src/decision/heldout/d29-pools.js +288 -0
  53. package/dist/src/decision/heldout/d29-v6.js +169 -0
  54. package/dist/src/decision/heldout/d29-v7.js +202 -0
  55. package/dist/src/decision/heldout/d29-v8.js +586 -0
  56. package/dist/src/decision/heldout/generator-registry.js +67 -0
  57. package/dist/src/decision/heldout/generators.js +696 -0
  58. package/dist/src/decision/heldout/index.js +8 -0
  59. package/dist/src/decision/heldout/journal.js +346 -0
  60. package/dist/src/decision/heldout/study-generators.js +64 -0
  61. package/dist/src/decision/heldout/types.js +2 -0
  62. package/dist/src/decision/host-policy.js +61 -0
  63. package/dist/src/decision/index.js +13 -0
  64. package/dist/src/decision/interop-profile.v1.json +112 -0
  65. package/dist/src/decision/interop.js +653 -0
  66. package/dist/src/decision/issue-triage/index.js +3 -0
  67. package/dist/src/decision/issue-triage/runtime.js +1069 -0
  68. package/dist/src/decision/issue-triage/types.js +2 -0
  69. package/dist/src/decision/jev-credentials.js +121 -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/quality.js +57 -49
  77. package/dist/src/decision/qualification/release.js +76 -3
  78. package/dist/src/decision/qualification/runner.js +5 -2
  79. package/dist/src/decision/routing/contract.js +175 -0
  80. package/dist/src/decision/routing/index.js +5 -0
  81. package/dist/src/decision/routing/report.js +216 -0
  82. package/dist/src/decision/routing/runtime.js +685 -0
  83. package/dist/src/decision/routing/types.js +2 -0
  84. package/dist/src/decision/sdlc-screening.js +1157 -0
  85. package/dist/src/decision/sensitivity/comparative.js +154 -0
  86. package/dist/src/decision/sensitivity/contract.js +218 -0
  87. package/dist/src/decision/sensitivity/index.js +5 -0
  88. package/dist/src/decision/sensitivity/runtime.js +912 -0
  89. package/dist/src/decision/sensitivity/types.js +2 -0
  90. package/dist/src/decision/validate.js +26 -0
  91. package/dist/src/extensions/commands/definitions.js +38 -0
  92. package/dist/src/extensions/manifest.js +44 -0
  93. package/dist/src/gates/discovery.js +315 -0
  94. package/dist/src/gates/driver.js +388 -0
  95. package/dist/src/gates/evaluate.js +719 -0
  96. package/dist/src/gates/floors.js +255 -0
  97. package/dist/src/gates/index.js +17 -0
  98. package/dist/src/gates/providers/evidence.js +38 -0
  99. package/dist/src/gates/providers/index.js +21 -0
  100. package/dist/src/gates/providers/isolated-child-source.js +446 -0
  101. package/dist/src/gates/providers/loader.js +1069 -0
  102. package/dist/src/gates/providers/paired.js +52 -0
  103. package/dist/src/gates/providers/proportion.js +60 -0
  104. package/dist/src/gates/providers/registry.js +40 -0
  105. package/dist/src/gates/providers/scalar.js +41 -0
  106. package/dist/src/gates/providers/screening.js +53 -0
  107. package/dist/src/gates/providers/types.js +25 -0
  108. package/dist/src/gates/registry.js +1003 -0
  109. package/dist/src/gates/report.js +102 -0
  110. package/dist/src/gates/schema.js +56 -0
  111. package/dist/src/gates/stats/binomial.js +26 -0
  112. package/dist/src/gates/stats/bootstrap.js +62 -0
  113. package/dist/src/gates/stats/clopper-pearson.js +95 -0
  114. package/dist/src/gates/stats/digest.js +26 -0
  115. package/dist/src/gates/stats/error.js +5 -0
  116. package/dist/src/gates/stats/index.js +9 -0
  117. package/dist/src/gates/stats/normal.js +35 -0
  118. package/dist/src/gates/stats/paired.js +120 -0
  119. package/dist/src/gates/stats/splits.js +30 -0
  120. package/dist/src/gates/types.js +8 -0
  121. package/dist/src/governance/redaction.js +14 -4
  122. package/dist/src/mcp/muse-native-config.mjs +123 -0
  123. package/dist/src/mcp/tools/decision.mjs +228 -0
  124. package/dist/src/mcp/tools/subsystems.mjs +2 -0
  125. package/dist/src/providers/capability-matrix.yaml +2 -1
  126. package/dist/src/providers/provider-definitions.js +2 -1
  127. package/dist/src/sessions/adapters/muse.js +336 -39
  128. package/dist/src/sessions/batch-import.js +7 -0
  129. package/dist/src/sessions/workspace-discovery.js +13 -2
  130. package/package.json +1 -1
  131. package/schemas/decision/ConformalFrozenOpenData.v2.schema.json +371 -0
  132. package/schemas/decision/ConformalOpenDataReport.v2.schema.json +421 -0
  133. package/schemas/decision/ConformalPreregistration.v2.schema.json +529 -0
  134. package/schemas/decision/ContextPruningCandidate.v1.schema.json +47 -0
  135. package/schemas/decision/ContextPruningEvaluationReport.v1.schema.json +758 -0
  136. package/schemas/decision/ContextPruningPreregistration.v1.schema.json +175 -0
  137. package/schemas/decision/ContextPruningReceipt.v1.schema.json +72 -0
  138. package/schemas/decision/D17Multifact.v1.schema.json +1851 -0
  139. package/schemas/decision/D17StudyAnalysis.v1.schema.json +42 -0
  140. package/schemas/decision/D17StudyAnalysis.v2.schema.json +51 -0
  141. package/schemas/decision/D17StudyCalibration.v1.schema.json +819 -0
  142. package/schemas/decision/D17StudyDryRun.v1.schema.json +169 -0
  143. package/schemas/decision/D17StudyDryRun.v2.schema.json +239 -0
  144. package/schemas/decision/D17StudyGold.v1.schema.json +108 -0
  145. package/schemas/decision/D17StudyGuide.v1.schema.json +63 -0
  146. package/schemas/decision/D17StudyNativeTemplates.v1.schema.json +619 -0
  147. package/schemas/decision/D17StudyProtocol.v1.schema.json +241 -0
  148. package/schemas/decision/D17StudyReport.v1.schema.json +902 -0
  149. package/schemas/decision/D17StudyReport.v2.schema.json +1319 -0
  150. package/schemas/decision/D17StudyReview.v1.schema.json +175 -0
  151. package/schemas/decision/D17StudySplits.v1.schema.json +217 -0
  152. package/schemas/decision/D29Study.v1.schema.json +1903 -0
  153. package/schemas/decision/D29Study.v2.schema.json +1344 -0
  154. package/schemas/decision/D29Study.v3.schema.json +609 -0
  155. package/schemas/decision/D29Study.v4.schema.json +1133 -0
  156. package/schemas/decision/D29Study.v6.schema.json +1205 -0
  157. package/schemas/decision/D29Study.v7.schema.json +1471 -0
  158. package/schemas/decision/D29Study.v8.schema.json +671 -0
  159. package/schemas/decision/D29Study.v9.schema.json +778 -0
  160. package/schemas/decision/DecisionComparativeReplayAuditSample.v1.schema.json +137 -0
  161. package/schemas/decision/DecisionComparativeReplayCorpus.v1.schema.json +258 -0
  162. package/schemas/decision/DecisionComparativeReplayFreeze.v1.schema.json +74 -0
  163. package/schemas/decision/DecisionComparativeReplayGold.v1.schema.json +50 -0
  164. package/schemas/decision/DecisionComparativeReplayGoldAsset.v1.schema.json +37 -0
  165. package/schemas/decision/DecisionComparativeReplayIntegrity.v1.schema.json +81 -0
  166. package/schemas/decision/DecisionComparativeReplayMembers.v1.schema.json +52 -0
  167. package/schemas/decision/DecisionComparativeReplayPreregistration.v1.schema.json +113 -0
  168. package/schemas/decision/DecisionComparativeReplayReport.v1.schema.json +407 -0
  169. package/schemas/decision/DecisionComparativeReplayReviewPackets.v1.schema.json +260 -0
  170. package/schemas/decision/DecisionComparativeReplaySplit.v1.schema.json +84 -0
  171. package/schemas/decision/DecisionFeatureObservation.v1.schema.json +564 -0
  172. package/schemas/decision/DecisionFeatureSet.v1.schema.json +155 -0
  173. package/schemas/decision/DecisionInteropMapping.v1.schema.json +85 -0
  174. package/schemas/decision/DecisionIssueTriageEvaluationManifest.v1.schema.json +174 -0
  175. package/schemas/decision/DecisionIssueTriageEvaluationReport.v1.schema.json +280 -0
  176. package/schemas/decision/DecisionIssueTriagePilotPack.v1.schema.json +114 -0
  177. package/schemas/decision/DecisionRouteReceipt.v1.schema.json +155 -0
  178. package/schemas/decision/DecisionRoutingPolicy.v1.schema.json +132 -0
  179. package/schemas/decision/DecisionRoutingShadowReport.v1.schema.json +170 -0
  180. package/schemas/decision/DecisionRoutingTask.v1.schema.json +49 -0
  181. package/schemas/decision/DecisionRuleset.schema.json +8 -2
  182. package/schemas/decision/DecisionRuleset.v1alpha2.schema.json +8 -2
  183. package/schemas/decision/DecisionSensitivityPlan.v1.schema.json +191 -0
  184. package/schemas/decision/DecisionSensitivityReport.v1.schema.json +163 -0
  185. package/schemas/decision/HeldoutApproval.v1.schema.json +312 -0
  186. package/schemas/decision/HeldoutAttempt.v1.schema.json +211 -0
  187. package/schemas/decision/HeldoutBaseline.v1.schema.json +90 -0
  188. package/schemas/decision/HeldoutCalibrationPhase.v1.schema.json +87 -0
  189. package/schemas/decision/HeldoutCorpus.v1.schema.json +167 -0
  190. package/schemas/decision/HeldoutEvent.v1.schema.json +41 -0
  191. package/schemas/decision/HeldoutFrozen.v1.schema.json +142 -0
  192. package/schemas/decision/HeldoutPreregistration.v1.schema.json +222 -0
  193. package/schemas/decision/HeldoutSpendEvent.v1.schema.json +122 -0
  194. package/schemas/decision/HeldoutSpendHead.v1.schema.json +25 -0
  195. package/schemas/decision/HeldoutSpendHead.v2.schema.json +46 -0
  196. package/schemas/decision/HeldoutSummary.v1.schema.json +101 -0
  197. package/schemas/decision/OpaDecisionLogExport.v1.schema.json +65 -0
  198. package/schemas/decision/PreprocessedEvidence.v1.schema.json +306 -0
  199. package/schemas/decision/RulesetResult.v1alpha2.schema.json +175 -0
  200. package/schemas/decision/SdlcEvidenceScreening.v1.schema.json +499 -0
  201. package/schemas/decision/SdlcScreeningPreregistration.v1.schema.json +132 -0
  202. package/schemas/decision/SdlcScreeningPreregistration.v2.schema.json +138 -0
  203. package/schemas/decision/SdlcScreeningRelease.v1.schema.json +654 -0
  204. package/schemas/decision/SdlcScreeningRelease.v2.schema.json +654 -0
  205. package/tools/agents/deploy-agents.mjs +1 -1
  206. package/tools/agents/providers/base.mjs +40 -18
  207. package/tools/agents/providers/factory.mjs +10 -2
  208. package/tools/agents/providers/muse-hooks.mjs +1 -29
  209. package/tools/agents/providers/muse.mjs +6 -3
@@ -0,0 +1,52 @@
1
+ import { providerSourceDigest, requireRecords } from './types.js';
2
+ /**
3
+ * Core paired provider: builds the 2x2 paired table per slice from candidate/baseline
4
+ * records. Powers `paired-difference` (newcombe, tango; non-inferiority, superiority) gates.
5
+ */
6
+ export const pairedProvider = {
7
+ id: 'test.paired/v1',
8
+ version: '1.0.0',
9
+ description: 'Per-slice paired candidate/baseline tables.',
10
+ metrics: {
11
+ 'contrast': { kind: 'paired', description: 'Paired 2x2 table per slice.' },
12
+ },
13
+ sourceDigest: providerSourceDigest({ id: 'test.paired/v1', version: '1.0.0',
14
+ metrics: { 'contrast': { kind: 'paired' } } }),
15
+ compute(records) {
16
+ const rows = requireRecords(records, 'paired');
17
+ const cells = {};
18
+ for (const row of rows) {
19
+ if (!row || typeof row.slice !== 'string' || !row.slice.trim()
20
+ || typeof row.candidate !== 'boolean' || typeof row.baseline !== 'boolean') {
21
+ throw new Error('paired records require a nonempty slice and boolean candidate/baseline');
22
+ }
23
+ const cell = cells[row.slice] ?? { both: 0, candidateOnly: 0, baselineOnly: 0, neither: 0 };
24
+ if (row.candidate && row.baseline)
25
+ cell.both++;
26
+ else if (row.candidate)
27
+ cell.candidateOnly++;
28
+ else if (row.baseline)
29
+ cell.baselineOnly++;
30
+ else
31
+ cell.neither++;
32
+ cells[row.slice] = cell;
33
+ }
34
+ const bySlice = {};
35
+ for (const [slice, cell] of Object.entries(cells)) {
36
+ bySlice[slice] = { n: cell.both + cell.candidateOnly + cell.baselineOnly + cell.neither, paired: { ...cell } };
37
+ }
38
+ const total = { both: 0, candidateOnly: 0, baselineOnly: 0, neither: 0 };
39
+ for (const cell of Object.values(cells)) {
40
+ total.both += cell.both;
41
+ total.candidateOnly += cell.candidateOnly;
42
+ total.baselineOnly += cell.baselineOnly;
43
+ total.neither += cell.neither;
44
+ }
45
+ const pooled = Object.keys(bySlice).length
46
+ ? { n: total.both + total.candidateOnly + total.baselineOnly + total.neither, paired: total }
47
+ : null;
48
+ return { version: '1.0.0', sourceDigest: pairedProvider.sourceDigest,
49
+ metrics: { 'contrast': { bySlice, pooled } } };
50
+ },
51
+ };
52
+ //# sourceMappingURL=paired.js.map
@@ -0,0 +1,60 @@
1
+ import { providerSourceDigest, requireRecords } from './types.js';
2
+ const VOCABULARY = {
3
+ 'false-ready': { kind: 'proportion', description: 'False-ready events per slice.' },
4
+ 'coverage': { kind: 'proportion', description: 'Accepted (advisory-ready) share per slice.' },
5
+ };
6
+ /**
7
+ * Tallies binary records per metric and slice. Records outside `allowed`
8
+ * throw: undeclared metric names fail closed at compute time.
9
+ */
10
+ export function tallyProportionRecords(rows, allowed, label) {
11
+ const tables = new Map();
12
+ for (const row of rows) {
13
+ if (!row || typeof row.slice !== 'string' || !row.slice.trim() || typeof row.event !== 'boolean'
14
+ || typeof row.metric !== 'string' || !allowed.has(row.metric)) {
15
+ throw new Error(`${label} records require a nonempty slice, a declared metric and a boolean event`);
16
+ }
17
+ const table = tables.get(row.metric) ?? new Map();
18
+ const current = table.get(row.slice) ?? { n: 0, events: 0 };
19
+ table.set(row.slice, { n: current.n + 1, events: current.events + (row.event ? 1 : 0) });
20
+ tables.set(row.metric, table);
21
+ }
22
+ return tables;
23
+ }
24
+ /** Builds one metric series per tally table, pooling slices into an overall observation. */
25
+ export function proportionSeries(tables, names) {
26
+ const series = (table) => {
27
+ const bySlice = {};
28
+ for (const [slice, counts] of table ?? [])
29
+ bySlice[slice] = { ...counts };
30
+ const pooled = Object.values(bySlice).reduce((sum, observation) => ({
31
+ n: (sum?.n ?? 0) + observation.n,
32
+ events: (sum?.events ?? 0) + observation.events,
33
+ }), Object.keys(bySlice).length ? { n: 0, events: 0 } : null);
34
+ return { bySlice, pooled };
35
+ };
36
+ return Object.fromEntries(names.map(name => [name, series(tables.get(name))]));
37
+ }
38
+ /**
39
+ * Core proportion provider with a fixed metric vocabulary: each record names
40
+ * its metric, and undeclared metric names fail closed at compute time. Powers
41
+ * `interval-bound` (wilson, clopper-pearson), `count-max` / `count-min` and
42
+ * `minimum-n` gates.
43
+ */
44
+ export const proportionProvider = {
45
+ id: 'test.proportion/v1',
46
+ version: '1.0.0',
47
+ description: 'Per-slice event counts from binary records with a fixed vocabulary.',
48
+ metrics: {
49
+ 'false-ready': { ...VOCABULARY['false-ready'] },
50
+ 'coverage': { ...VOCABULARY.coverage },
51
+ },
52
+ sourceDigest: providerSourceDigest({ id: 'test.proportion/v1', version: '1.0.0', metrics: VOCABULARY }),
53
+ compute(records) {
54
+ const rows = requireRecords(records, 'proportion');
55
+ const tables = tallyProportionRecords(rows, new Set(['false-ready', 'coverage']), 'proportion');
56
+ return { version: '1.0.0', sourceDigest: proportionProvider.sourceDigest,
57
+ metrics: proportionSeries(tables, ['false-ready', 'coverage']) };
58
+ },
59
+ };
60
+ //# sourceMappingURL=proportion.js.map
@@ -0,0 +1,40 @@
1
+ import { isLoaderIssuedProvider } from './loader.js';
2
+ /** Registry of metric providers. Unknown or duplicate ids fail at load; nothing resolves by default. */
3
+ export class MetricProviderRegistry {
4
+ providers = new Map();
5
+ register(provider) {
6
+ if (!provider || typeof provider.id !== 'string' || !provider.id.trim()
7
+ || typeof provider.version !== 'string' || !provider.version.trim()
8
+ || typeof provider.sourceDigest !== 'string' || !/^sha256:[0-9a-f]{64}$/.test(provider.sourceDigest)
9
+ || !provider.metrics || typeof provider.metrics !== 'object'
10
+ || typeof provider.compute !== 'function') {
11
+ throw new Error('metric provider registration requires id, version, sourceDigest, metrics and compute');
12
+ }
13
+ if (provider.codeDigest !== undefined
14
+ && (typeof provider.codeDigest !== 'string' || !/^sha256:[0-9a-f]{64}$/.test(provider.codeDigest))) {
15
+ throw new Error(`metric provider ${provider.id} code digest is unknown`);
16
+ }
17
+ // C3: a code-digest (bundle) provider registers only as the exact frozen
18
+ // object the bundle loader issued after its allowlist check. Copies and
19
+ // hand-made objects carrying the same fields cannot bypass the allowlist.
20
+ if (provider.codeDigest !== undefined && !isLoaderIssuedProvider(provider)) {
21
+ throw new Error(`metric provider ${provider.id} carries a code digest but was not issued by the bundle loader: refusing registration`);
22
+ }
23
+ if (this.providers.has(provider.id))
24
+ throw new Error(`duplicate metric provider: ${provider.id}`);
25
+ this.providers.set(provider.id, provider);
26
+ }
27
+ get(id) {
28
+ const provider = typeof id === 'string' ? this.providers.get(id) : undefined;
29
+ if (!provider)
30
+ throw new Error(`unknown metric provider: ${String(id)}`);
31
+ return provider;
32
+ }
33
+ has(id) {
34
+ return typeof id === 'string' && this.providers.has(id);
35
+ }
36
+ ids() {
37
+ return [...this.providers.keys()].sort();
38
+ }
39
+ }
40
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1,41 @@
1
+ import { providerSourceDigest, requireRecords } from './types.js';
2
+ /**
3
+ * Core scalar provider: per-slice mean, extrema and raw differences from numeric records.
4
+ * Powers `value-threshold` gates (mean) and `bootstrap-bound` gates (differences).
5
+ */
6
+ export const scalarProvider = {
7
+ id: 'test.scalar/v1',
8
+ version: '1.0.0',
9
+ description: 'Per-slice mean and raw values from numeric records.',
10
+ metrics: {
11
+ 'measurement': { kind: 'scalar', description: 'Mean value per slice.' },
12
+ 'delta': { kind: 'differences', description: 'Raw per-record values per slice.' },
13
+ },
14
+ sourceDigest: providerSourceDigest({ id: 'test.scalar/v1', version: '1.0.0',
15
+ metrics: { 'measurement': { kind: 'scalar' }, 'delta': { kind: 'differences' } } }),
16
+ compute(records) {
17
+ const rows = requireRecords(records, 'scalar');
18
+ const groups = new Map();
19
+ for (const row of rows) {
20
+ if (!row || typeof row.slice !== 'string' || !row.slice.trim()
21
+ || typeof row.value !== 'number' || !Number.isFinite(row.value)) {
22
+ throw new Error('scalar records require a nonempty slice and a finite value');
23
+ }
24
+ groups.set(row.slice, [...(groups.get(row.slice) ?? []), row.value]);
25
+ }
26
+ const measurement = {};
27
+ const delta = {};
28
+ for (const [slice, values] of groups) {
29
+ measurement[slice] = { n: values.length, value: values.reduce((sum, value) => sum + value, 0) / values.length };
30
+ delta[slice] = { n: values.length, differences: [...values] };
31
+ }
32
+ const all = [...groups.values()].flat();
33
+ const mean = (values) => values.length
34
+ ? { n: values.length, value: values.reduce((sum, value) => sum + value, 0) / values.length } : null;
35
+ return { version: '1.0.0', sourceDigest: scalarProvider.sourceDigest, metrics: {
36
+ 'measurement': { bySlice: measurement, pooled: mean(all) },
37
+ 'delta': { bySlice: delta, pooled: all.length ? { n: all.length, differences: all } : null },
38
+ } };
39
+ },
40
+ };
41
+ //# sourceMappingURL=scalar.js.map
@@ -0,0 +1,53 @@
1
+ import { providerSourceDigest, requireRecords } from './types.js';
2
+ import { collectAttestations } from './evidence.js';
3
+ import { proportionSeries, tallyProportionRecords } from './proportion.js';
4
+ const PROPORTIONS = ['false-ready', 'false-support', 'coverage', 'accuracy'];
5
+ const VOCABULARY = {
6
+ 'false-ready': { kind: 'proportion', description: 'False-ready events per slice: advisory-ready with non-ready gold.' },
7
+ 'false-support': { kind: 'proportion', description: 'False-support events per citation slice: accepted support with non-support gold.' },
8
+ 'coverage': { kind: 'proportion', description: 'Advisory-ready share per slice; the always-review reference rate is 0.' },
9
+ 'accuracy': { kind: 'proportion', description: 'Joint candidate correctness per slice: route matches gold readiness and support.' },
10
+ 'calibration': { kind: 'evidence', description: 'Staged D09 calibration artifact binding for the scored phase.' },
11
+ };
12
+ const isRecord = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
13
+ /**
14
+ * Core screening provider behind the `aiwg:decision-engine/absolute-screening`
15
+ * pack. Binary records tally into per-slice proportion series; calibration
16
+ * attestations collect into the pooled evidence observation. Powers
17
+ * `interval-bound` (wilson), `count-max`, `minimum-n` and `evidence` gates.
18
+ */
19
+ export const screeningProvider = {
20
+ id: 'decision.screening/v1',
21
+ version: '1.0.0',
22
+ description: 'SDLC evidence-screening proportions with the staged-calibration attestation.',
23
+ metrics: {
24
+ 'false-ready': { ...VOCABULARY['false-ready'] },
25
+ 'false-support': { ...VOCABULARY['false-support'] },
26
+ 'coverage': { ...VOCABULARY.coverage },
27
+ 'accuracy': { ...VOCABULARY.accuracy },
28
+ 'calibration': { ...VOCABULARY.calibration },
29
+ },
30
+ sourceDigest: providerSourceDigest({ id: 'decision.screening/v1', version: '1.0.0', metrics: VOCABULARY }),
31
+ compute(records) {
32
+ const rows = requireRecords(records, 'screening');
33
+ const binary = [];
34
+ const attestations = [];
35
+ for (const row of rows) {
36
+ const hasMetric = isRecord(row) && typeof row.metric === 'string';
37
+ const hasId = isRecord(row) && typeof row.id === 'string';
38
+ if (hasMetric === hasId) {
39
+ throw new Error('screening records are either binary {slice, metric, event} or attestations {id, passed}');
40
+ }
41
+ if (hasMetric)
42
+ binary.push(row);
43
+ else
44
+ attestations.push(row);
45
+ }
46
+ const tables = tallyProportionRecords(binary, new Set(PROPORTIONS), 'screening');
47
+ const metrics = proportionSeries(tables, [...PROPORTIONS]);
48
+ const pooled = { available: collectAttestations(attestations, 'screening') };
49
+ return { version: '1.0.0', sourceDigest: screeningProvider.sourceDigest,
50
+ metrics: { ...metrics, 'calibration': { bySlice: {}, pooled } } };
51
+ },
52
+ };
53
+ //# sourceMappingURL=screening.js.map
@@ -0,0 +1,25 @@
1
+ import { artifactDigest } from '../../decision/validate.js';
2
+ export function providerSourceDigest(descriptor) {
3
+ return artifactDigest(descriptor);
4
+ }
5
+ /** Fail-closed record guard shared by core providers. */
6
+ export function requireRecords(records, label) {
7
+ if (!Array.isArray(records))
8
+ throw new Error(`${label} records must be an array`);
9
+ return records;
10
+ }
11
+ export function pooledFromSlices(slices) {
12
+ const observations = Object.values(slices);
13
+ if (!observations.length)
14
+ return null;
15
+ const ns = observations.map(observation => observation.n);
16
+ if (ns.some(n => n === null || n === undefined))
17
+ return null;
18
+ const total = ns.reduce((sum, n) => sum + n, 0);
19
+ const sum = (pick) => {
20
+ const values = observations.map(pick);
21
+ return values.every(value => typeof value === 'number') ? values.reduce((a, b) => a + b, 0) : null;
22
+ };
23
+ return { n: total, events: sum(observation => observation.events), value: null };
24
+ }
25
+ //# sourceMappingURL=types.js.map