@ai-sdlc/orchestrator 0.10.0 → 0.13.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 (156) hide show
  1. package/dist/adapters.d.ts +42 -3
  2. package/dist/adapters.js +133 -3
  3. package/dist/admission-composite.d.ts +112 -1
  4. package/dist/admission-composite.js +85 -4
  5. package/dist/admission-enrichment.d.ts +12 -3
  6. package/dist/admission-enrichment.js +64 -13
  7. package/dist/admission-score.d.ts +30 -0
  8. package/dist/admission-score.js +4 -1
  9. package/dist/backlog-adapter.d.ts +45 -0
  10. package/dist/backlog-adapter.js +145 -1
  11. package/dist/calibration.d.ts +81 -0
  12. package/dist/calibration.js +76 -0
  13. package/dist/cli/commands/init-features.d.ts +301 -2
  14. package/dist/cli/commands/init-features.js +634 -7
  15. package/dist/cli/commands/init-templates.d.ts +198 -1
  16. package/dist/cli/commands/init-templates.js +943 -1
  17. package/dist/cli/commands/init.d.ts +45 -0
  18. package/dist/cli/commands/init.js +147 -5
  19. package/dist/cli/commands/run.js +9 -1
  20. package/dist/cli/index.d.ts +11 -0
  21. package/dist/cli/index.js +42 -8
  22. package/dist/compliance/composer.d.ts +79 -0
  23. package/dist/compliance/composer.js +258 -0
  24. package/dist/compliance/errors.d.ts +64 -0
  25. package/dist/compliance/errors.js +85 -0
  26. package/dist/compliance/loader.d.ts +52 -0
  27. package/dist/compliance/loader.js +124 -0
  28. package/dist/compliance/types.d.ts +184 -0
  29. package/dist/compliance/types.js +41 -0
  30. package/dist/compliance-clearance.d.ts +269 -0
  31. package/dist/compliance-clearance.js +269 -0
  32. package/dist/config.js +17 -0
  33. package/dist/cost-tracker.d.ts +22 -0
  34. package/dist/cost-tracker.js +41 -0
  35. package/dist/database/adapters/external.js +5 -1
  36. package/dist/embedding/adapters/openai-text-embedding-3-small.d.ts +71 -0
  37. package/dist/embedding/adapters/openai-text-embedding-3-small.js +190 -0
  38. package/dist/embedding/consumers/tessellation-drift.d.ts +74 -0
  39. package/dist/embedding/consumers/tessellation-drift.js +76 -0
  40. package/dist/embedding/cross-provider.d.ts +78 -0
  41. package/dist/embedding/cross-provider.js +75 -0
  42. package/dist/embedding/deprecation.d.ts +151 -0
  43. package/dist/embedding/deprecation.js +229 -0
  44. package/dist/embedding/errors.d.ts +90 -0
  45. package/dist/embedding/errors.js +150 -0
  46. package/dist/embedding/index.d.ts +29 -0
  47. package/dist/embedding/index.js +24 -0
  48. package/dist/embedding/pipeline-load.d.ts +146 -0
  49. package/dist/embedding/pipeline-load.js +178 -0
  50. package/dist/embedding/registry.d.ts +45 -0
  51. package/dist/embedding/registry.js +61 -0
  52. package/dist/embedding/stale-vector.d.ts +110 -0
  53. package/dist/embedding/stale-vector.js +92 -0
  54. package/dist/embedding/storage/index.d.ts +51 -0
  55. package/dist/embedding/storage/index.js +43 -0
  56. package/dist/embedding/storage/jsonl-backend.d.ts +150 -0
  57. package/dist/embedding/storage/jsonl-backend.js +332 -0
  58. package/dist/embedding/storage/types.d.ts +135 -0
  59. package/dist/embedding/storage/types.js +13 -0
  60. package/dist/embedding/types.d.ts +180 -0
  61. package/dist/embedding/types.js +10 -0
  62. package/dist/execute.d.ts +29 -2
  63. package/dist/execute.js +171 -30
  64. package/dist/index.d.ts +14 -2
  65. package/dist/index.js +19 -2
  66. package/dist/journey/inheritance-validator.d.ts +396 -0
  67. package/dist/journey/inheritance-validator.js +370 -0
  68. package/dist/journey/state-id-drift-rule.d.ts +137 -0
  69. package/dist/journey/state-id-drift-rule.js +245 -0
  70. package/dist/journey-sa2-router.d.ts +395 -0
  71. package/dist/journey-sa2-router.js +308 -0
  72. package/dist/runners/review-agent.js +6 -2
  73. package/dist/runners/runner-registry.d.ts +36 -0
  74. package/dist/runners/runner-registry.js +90 -0
  75. package/dist/runtime/attestations.d.ts +173 -13
  76. package/dist/runtime/attestations.js +252 -40
  77. package/dist/runtime/index.d.ts +1 -1
  78. package/dist/runtime/index.js +1 -1
  79. package/dist/sa-scoring/layer3-llm.js +6 -1
  80. package/dist/sa-scoring/revision-proposal-config.d.ts +178 -0
  81. package/dist/sa-scoring/revision-proposal-config.js +198 -0
  82. package/dist/sa-scoring/revision-proposal.d.ts +285 -0
  83. package/dist/sa-scoring/revision-proposal.js +417 -0
  84. package/dist/signal-ingestion/adapters/community-thread.d.ts +43 -0
  85. package/dist/signal-ingestion/adapters/community-thread.js +55 -0
  86. package/dist/signal-ingestion/adapters/in-app-feedback.d.ts +67 -0
  87. package/dist/signal-ingestion/adapters/in-app-feedback.js +51 -0
  88. package/dist/signal-ingestion/adapters/manual.d.ts +78 -0
  89. package/dist/signal-ingestion/adapters/manual.js +112 -0
  90. package/dist/signal-ingestion/adapters/support-ticket.d.ts +47 -0
  91. package/dist/signal-ingestion/adapters/support-ticket.js +51 -0
  92. package/dist/signal-ingestion/classifier.d.ts +205 -0
  93. package/dist/signal-ingestion/classifier.js +494 -0
  94. package/dist/signal-ingestion/clustering-types.d.ts +36 -0
  95. package/dist/signal-ingestion/clustering-types.js +14 -0
  96. package/dist/signal-ingestion/clustering.d.ts +200 -0
  97. package/dist/signal-ingestion/clustering.js +413 -0
  98. package/dist/signal-ingestion/config.d.ts +351 -0
  99. package/dist/signal-ingestion/config.js +587 -0
  100. package/dist/signal-ingestion/d1.d.ts +252 -0
  101. package/dist/signal-ingestion/d1.js +235 -0
  102. package/dist/signal-ingestion/errors.d.ts +73 -0
  103. package/dist/signal-ingestion/errors.js +108 -0
  104. package/dist/signal-ingestion/governance-events.d.ts +181 -0
  105. package/dist/signal-ingestion/governance-events.js +189 -0
  106. package/dist/signal-ingestion/index.d.ts +35 -0
  107. package/dist/signal-ingestion/index.js +53 -0
  108. package/dist/signal-ingestion/manual-share-metric.d.ts +93 -0
  109. package/dist/signal-ingestion/manual-share-metric.js +106 -0
  110. package/dist/signal-ingestion/registry.d.ts +40 -0
  111. package/dist/signal-ingestion/registry.js +137 -0
  112. package/dist/signal-ingestion/residency.d.ts +227 -0
  113. package/dist/signal-ingestion/residency.js +238 -0
  114. package/dist/signal-ingestion/significance.d.ts +554 -0
  115. package/dist/signal-ingestion/significance.js +555 -0
  116. package/dist/signal-ingestion/types.d.ts +191 -0
  117. package/dist/signal-ingestion/types.js +8 -0
  118. package/dist/substrate/drift-composition.d.ts +270 -0
  119. package/dist/substrate/drift-composition.js +306 -0
  120. package/dist/substrate/drift-tui-surface.d.ts +61 -0
  121. package/dist/substrate/drift-tui-surface.js +102 -0
  122. package/dist/substrate/identity-class.d.ts +176 -0
  123. package/dist/substrate/identity-class.js +201 -0
  124. package/dist/tessellation/cross-soul-provenance-rule.d.ts +133 -0
  125. package/dist/tessellation/cross-soul-provenance-rule.js +171 -0
  126. package/dist/tessellation/inter-soul-embedding-distance-rule.d.ts +61 -0
  127. package/dist/tessellation/inter-soul-embedding-distance-rule.js +67 -0
  128. package/dist/tessellation/rule-registry.d.ts +269 -0
  129. package/dist/tessellation/rule-registry.js +92 -0
  130. package/dist/tessellation/soul-slug-ast-scan-rule.d.ts +90 -0
  131. package/dist/tessellation/soul-slug-ast-scan-rule.js +158 -0
  132. package/dist/tessellation-admission.d.ts +162 -0
  133. package/dist/tessellation-admission.js +146 -0
  134. package/dist/tessellation-drift.d.ts +246 -0
  135. package/dist/tessellation-drift.js +250 -0
  136. package/dist/validate-config.js +13 -0
  137. package/dist/validate-issue.js +2 -2
  138. package/dist/variant/cardinality-activation.d.ts +126 -0
  139. package/dist/variant/cardinality-activation.js +101 -0
  140. package/dist/variant/deprecation-lifecycle.d.ts +184 -0
  141. package/dist/variant/deprecation-lifecycle.js +208 -0
  142. package/dist/variant/drift-extension.d.ts +136 -0
  143. package/dist/variant/drift-extension.js +164 -0
  144. package/dist/variant/engineering-review.d.ts +185 -0
  145. package/dist/variant/engineering-review.js +142 -0
  146. package/dist/variant/index.d.ts +32 -0
  147. package/dist/variant/index.js +32 -0
  148. package/dist/variant/inheritance-validator.d.ts +165 -0
  149. package/dist/variant/inheritance-validator.js +139 -0
  150. package/dist/variant/internal-adopter/index.d.ts +11 -0
  151. package/dist/variant/internal-adopter/index.js +10 -0
  152. package/dist/variant/internal-adopter/products.d.ts +156 -0
  153. package/dist/variant/internal-adopter/products.js +366 -0
  154. package/dist/variant-admission.d.ts +316 -0
  155. package/dist/variant-admission.js +247 -0
  156. package/package.json +10 -8
@@ -0,0 +1,366 @@
1
+ /**
2
+ * RFC-0017 Phase 4 — InternalAdopter three-product reference implementation
3
+ * (AISDLC-437).
4
+ *
5
+ * Ships ProductA / ProductB / ProductC as canonical fixtures that demonstrate
6
+ * the In-Soul Variant Pattern against real-world adopter constraints. Each
7
+ * product is a distinct Soul on shared substrate; each declares three variants
8
+ * with audience-segment / form-factor / role-based specialization.
9
+ *
10
+ * **ProductD is INTENTIONALLY OMITTED** — per RFC-0017 §11 v0.4 (2026-05-26
11
+ * Design Authority editorial pass), ProductD's proposed variants
12
+ * (`annual-test`, `repair-event`, `regulatory-audit-mode`) are temporal-context-
13
+ * bound operational modes activated by *when* and *why* a user is in the
14
+ * system. Same user, different operational moment = Journey shape (RFC-0018),
15
+ * not Variant shape. ProductD's validation is deferred to RFC-0018 §11 as a
16
+ * Variant/Journey boundary validation case for the companion RFC.
17
+ *
18
+ * Variant constraints validated by `products.test.ts`:
19
+ * - Every variant has ≤ 5 `designImperatives` strings (closed-enum discipline)
20
+ * - Every variant's `designOverrides` uses only framework-owned enum fields
21
+ * (`colorPaletteOverlay`, `densityProfile`, `typographyScale`,
22
+ * `motionProfile`, `radiusProfile` per §6.1 OQ-5 2026-05-26 revisit)
23
+ * - All variants of a given product share the same compliance + substrate
24
+ * (substrate-shared check, AC #7)
25
+ * - All variants pass `validateVariantDeclarations()` (no inheritance
26
+ * violations, no nested variants, under the soft-warn / hard-limit caps)
27
+ *
28
+ * @see spec/rfcs/RFC-0017-in-soul-variant-pattern.md §11 (practitioner validation)
29
+ * @see ./products.test.ts — substrate-shared + closed-enum + inheritance checks
30
+ * @see ./admission-spotcheck.test.ts — variant-routed vs soul-aggregate scoring
31
+ * @see ./deprecation-lifecycle.test.ts — end-to-end lifecycle on ProductA variant
32
+ */
33
+ /**
34
+ * Canonical shared substrate for the InternalAdopter product suite.
35
+ * Every ProductA/B/C variant inherits this identical block — substrate
36
+ * sharing is enforced at the fixture level (AC #7).
37
+ */
38
+ export const INTERNAL_ADOPTER_SUBSTRATE = {
39
+ complianceRegimes: ['WCAG-2.1-AA'],
40
+ substrateInvariants: {
41
+ eventBus: 'internal-adopter-kafka-v1',
42
+ schemaRegistry: 'internal-adopter-schema-registry-v1',
43
+ tenantModel: 'multi-tenant-row-isolation',
44
+ },
45
+ performanceBudgets: {
46
+ initialLoadMs: 2500,
47
+ interactionResponseMs: 100,
48
+ },
49
+ observabilityRequirements: ['otel-traces', 'structured-logs', 'rum-vitals'],
50
+ };
51
+ // ── ProductA — small-utility / enterprise / county-regional ──────────────────
52
+ //
53
+ // Validates audience-segment specialization across the v0.4 visual-token
54
+ // surface. The three variants serve dramatically different audience sizes
55
+ // + cognitive-load profiles on a shared substrate.
56
+ const PRODUCT_A = {
57
+ soulId: 'product-a',
58
+ description: 'Utility-operations management for water + electricity service providers. ' +
59
+ 'Validates audience-segment specialization (small ↔ enterprise ↔ county).',
60
+ validationAxis: 'audience-segment specialization (RFC-0017 §11)',
61
+ substrate: INTERNAL_ADOPTER_SUBSTRATE,
62
+ soulDesignImperatives: ['compliance-first-information-architecture', 'audit-trail-visibility'],
63
+ variants: [
64
+ {
65
+ id: 'small-utility',
66
+ audienceCharacteristics: {
67
+ segments: ['municipal-small', 'water-district-small'],
68
+ sizeRange: { minStaff: 1, maxStaff: 50 },
69
+ },
70
+ designOverrides: {
71
+ colorPaletteOverlay: 'small-utility-warm',
72
+ densityProfile: 'comfortable',
73
+ typographyScale: 'large-print',
74
+ motionProfile: 'reduced',
75
+ radiusProfile: 'rounded',
76
+ },
77
+ designImperatives: [
78
+ 'low-tech-fluency-tolerance',
79
+ 'single-task-focus-per-screen',
80
+ 'forgiving-error-recovery',
81
+ 'minimal-jargon',
82
+ ],
83
+ },
84
+ {
85
+ id: 'enterprise',
86
+ audienceCharacteristics: {
87
+ segments: ['municipal-large', 'regional-utility'],
88
+ sizeRange: { minStaff: 51, maxStaff: 5000 },
89
+ },
90
+ designOverrides: {
91
+ colorPaletteOverlay: 'enterprise-cool',
92
+ densityProfile: 'compact',
93
+ typographyScale: 'default',
94
+ motionProfile: 'full',
95
+ radiusProfile: 'default',
96
+ },
97
+ designImperatives: [
98
+ 'bulk-operation-efficiency',
99
+ 'multi-tab-workflow-tolerance',
100
+ 'keyboard-first-power-user-shortcuts',
101
+ 'dashboard-density-tolerance',
102
+ ],
103
+ },
104
+ {
105
+ id: 'county-regional',
106
+ audienceCharacteristics: {
107
+ segments: ['county-government', 'regional-coordinator'],
108
+ sizeRange: { minStaff: 20, maxStaff: 200 },
109
+ },
110
+ designOverrides: {
111
+ colorPaletteOverlay: 'county-civic',
112
+ densityProfile: 'comfortable',
113
+ typographyScale: 'default',
114
+ motionProfile: 'reduced',
115
+ radiusProfile: 'sharp',
116
+ },
117
+ designImperatives: [
118
+ 'cross-jurisdiction-reconciliation-clarity',
119
+ 'inter-agency-handoff-explicit',
120
+ 'official-record-defensibility',
121
+ ],
122
+ },
123
+ ],
124
+ };
125
+ // ── ProductB — field-tech-on-truck / field-tech-handheld / supervisor-tablet ─
126
+ //
127
+ // Validates density profile + form-factor specialization. Same role (field
128
+ // operations) at different form-factors / contexts of use — density profile
129
+ // + motion + radius differ sharply across the three.
130
+ const PRODUCT_B = {
131
+ soulId: 'product-b',
132
+ description: 'Field-operations dispatch + workflow execution for utility field crews. ' +
133
+ 'Validates density profile + form-factor specialization.',
134
+ validationAxis: 'density profile + form-factor specialization (RFC-0017 §11)',
135
+ substrate: INTERNAL_ADOPTER_SUBSTRATE,
136
+ soulDesignImperatives: ['offline-first-resilience', 'one-handed-operation-where-possible'],
137
+ variants: [
138
+ {
139
+ id: 'field-tech-on-truck',
140
+ audienceCharacteristics: {
141
+ segments: ['field-crew-mounted', 'service-truck-operator'],
142
+ sizeRange: { minStaff: 1, maxStaff: 4 },
143
+ },
144
+ designOverrides: {
145
+ colorPaletteOverlay: 'high-contrast-outdoor',
146
+ densityProfile: 'spacious',
147
+ typographyScale: 'large-print',
148
+ motionProfile: 'reduced',
149
+ radiusProfile: 'rounded',
150
+ },
151
+ designImperatives: [
152
+ 'glanceable-from-driving-position',
153
+ 'glove-friendly-tap-targets',
154
+ 'sun-glare-readable-contrast',
155
+ 'cellular-degraded-graceful',
156
+ ],
157
+ },
158
+ {
159
+ id: 'field-tech-handheld',
160
+ audienceCharacteristics: {
161
+ segments: ['field-crew-handheld', 'meter-reader'],
162
+ sizeRange: { minStaff: 1, maxStaff: 1 },
163
+ },
164
+ designOverrides: {
165
+ colorPaletteOverlay: 'high-contrast-outdoor',
166
+ densityProfile: 'comfortable',
167
+ typographyScale: 'large-print',
168
+ motionProfile: 'reduced',
169
+ radiusProfile: 'rounded',
170
+ },
171
+ designImperatives: [
172
+ 'thumb-zone-reachability',
173
+ 'single-hand-operation',
174
+ 'rugged-conditions-tolerance',
175
+ 'barcode-scan-prominent',
176
+ ],
177
+ },
178
+ {
179
+ id: 'supervisor-tablet',
180
+ audienceCharacteristics: {
181
+ segments: ['field-supervisor', 'crew-dispatch-coordinator'],
182
+ sizeRange: { minStaff: 1, maxStaff: 10 },
183
+ },
184
+ designOverrides: {
185
+ colorPaletteOverlay: 'supervisor-default',
186
+ densityProfile: 'compact',
187
+ typographyScale: 'data-dense',
188
+ motionProfile: 'full',
189
+ radiusProfile: 'default',
190
+ },
191
+ designImperatives: [
192
+ 'multi-crew-overview-at-a-glance',
193
+ 'rapid-reassignment-workflow',
194
+ 'cross-crew-comparative-metrics',
195
+ 'two-handed-tablet-grip-affordance',
196
+ ],
197
+ },
198
+ ],
199
+ };
200
+ // ── ProductC — billing-clerk / customer-portal / csr-dashboard ───────────────
201
+ //
202
+ // Validates role-based audience + workflow-density specialization. Same
203
+ // domain (billing) but radically different roles (internal staff vs end
204
+ // customer vs CSR) on shared substrate.
205
+ const PRODUCT_C = {
206
+ soulId: 'product-c',
207
+ description: 'Billing + customer-account management spanning internal staff, end customers, ' +
208
+ 'and customer-service representatives. Validates role-based audience + ' +
209
+ 'workflow-density specialization.',
210
+ validationAxis: 'role-based audience + workflow-density specialization (RFC-0017 §11)',
211
+ substrate: INTERNAL_ADOPTER_SUBSTRATE,
212
+ soulDesignImperatives: ['financial-accuracy-first', 'data-provenance-traceable'],
213
+ variants: [
214
+ {
215
+ id: 'billing-clerk',
216
+ audienceCharacteristics: {
217
+ segments: ['billing-staff', 'accounts-receivable'],
218
+ sizeRange: { minStaff: 1, maxStaff: 20 },
219
+ },
220
+ designOverrides: {
221
+ colorPaletteOverlay: 'billing-staff-neutral',
222
+ densityProfile: 'compact',
223
+ typographyScale: 'data-dense',
224
+ motionProfile: 'reduced',
225
+ radiusProfile: 'sharp',
226
+ },
227
+ designImperatives: [
228
+ 'bulk-edit-efficiency',
229
+ 'keyboard-numpad-optimized',
230
+ 'audit-log-always-visible',
231
+ 'reconciliation-discrepancy-prominent',
232
+ ],
233
+ },
234
+ {
235
+ id: 'customer-portal',
236
+ audienceCharacteristics: {
237
+ segments: ['end-customer', 'self-service-billpayer'],
238
+ sizeRange: { minStaff: 1, maxStaff: 1 },
239
+ },
240
+ designOverrides: {
241
+ colorPaletteOverlay: 'customer-portal-friendly',
242
+ densityProfile: 'spacious',
243
+ typographyScale: 'default',
244
+ motionProfile: 'full',
245
+ radiusProfile: 'rounded',
246
+ },
247
+ designImperatives: [
248
+ 'plain-language-no-jargon',
249
+ 'self-service-task-completion-clarity',
250
+ 'mobile-first-responsive',
251
+ 'trust-signal-prominent',
252
+ ],
253
+ },
254
+ {
255
+ id: 'csr-dashboard',
256
+ audienceCharacteristics: {
257
+ segments: ['customer-service-representative', 'call-center-agent'],
258
+ sizeRange: { minStaff: 5, maxStaff: 500 },
259
+ },
260
+ designOverrides: {
261
+ colorPaletteOverlay: 'csr-action-oriented',
262
+ densityProfile: 'compact',
263
+ typographyScale: 'data-dense',
264
+ motionProfile: 'full',
265
+ radiusProfile: 'default',
266
+ },
267
+ designImperatives: [
268
+ 'caller-context-instantly-loaded',
269
+ 'quick-resolution-workflow',
270
+ 'sentiment-aware-prompts',
271
+ 'screen-pop-integration',
272
+ ],
273
+ },
274
+ ],
275
+ };
276
+ // ── Exports ──────────────────────────────────────────────────────────────────
277
+ /**
278
+ * The three InternalAdopter products — ProductA / ProductB / ProductC.
279
+ * ProductD is intentionally omitted per RFC-0017 §11 v0.4 (deferred to
280
+ * RFC-0018 §11 — temporal-context-bound modes are Journey shape, not Variant).
281
+ */
282
+ export const INTERNAL_ADOPTER_PRODUCTS = [
283
+ PRODUCT_A,
284
+ PRODUCT_B,
285
+ PRODUCT_C,
286
+ ];
287
+ /** Individual product accessors for direct consumption by tests / tooling. */
288
+ export const productA = PRODUCT_A;
289
+ export const productB = PRODUCT_B;
290
+ export const productC = PRODUCT_C;
291
+ /**
292
+ * Build a `variantsBySoul` map suitable for `VariantContext`, derived from
293
+ * the three product declarations. Test helper + the canonical shape callers
294
+ * use to wire the reference impl into the admission composite.
295
+ */
296
+ export function buildVariantsBySoul() {
297
+ const out = {};
298
+ for (const product of INTERNAL_ADOPTER_PRODUCTS) {
299
+ out[product.soulId] = product.variants.map((v) => ({ ...v }));
300
+ }
301
+ return out;
302
+ }
303
+ /**
304
+ * Build a representative `variantScores` map for spot-check admission scoring.
305
+ *
306
+ * Score shape: each variant gets `sa1` and `sa2` numbers in [0, 1].
307
+ * Per-variant scores are chosen to demonstrate that **variant-routed scoring
308
+ * differs from soul-aggregate scoring on a representative work item** (AC #6):
309
+ *
310
+ * - The "well-aligned" variant for a given work item scores HIGH (sa1=0.92,
311
+ * sa2=0.88).
312
+ * - The "misaligned" variants score LOW (sa1=0.30-0.40, sa2=0.35-0.45).
313
+ *
314
+ * If the same work item were scored at soul-aggregate scope, the average of
315
+ * its variants would compress to a middling value (sa1≈0.54, sa2≈0.56) —
316
+ * the variant-routed score for the well-aligned variant is meaningfully
317
+ * different (≈ +70% on sa1, +57% on sa2). This is the failure mode RFC-0017
318
+ * §2 documents: soul-aggregate scoring underweights variant-specific intent.
319
+ *
320
+ * The spot-check test in `admission-spotcheck.test.ts` exercises this against
321
+ * a representative ProductA work item ("small-utility onboarding improvement").
322
+ */
323
+ export function buildVariantScores() {
324
+ return {
325
+ 'product-a': {
326
+ 'small-utility': { sa1: 0.92, sa2: 0.88 },
327
+ enterprise: { sa1: 0.35, sa2: 0.4 },
328
+ 'county-regional': { sa1: 0.4, sa2: 0.45 },
329
+ },
330
+ 'product-b': {
331
+ 'field-tech-on-truck': { sa1: 0.9, sa2: 0.85 },
332
+ 'field-tech-handheld': { sa1: 0.6, sa2: 0.55 },
333
+ 'supervisor-tablet': { sa1: 0.3, sa2: 0.35 },
334
+ },
335
+ 'product-c': {
336
+ 'billing-clerk': { sa1: 0.88, sa2: 0.82 },
337
+ 'customer-portal': { sa1: 0.3, sa2: 0.35 },
338
+ 'csr-dashboard': { sa1: 0.55, sa2: 0.6 },
339
+ },
340
+ };
341
+ }
342
+ /**
343
+ * Soul-aggregate Sα₁ / Sα₂ baseline for a given Soul, computed by averaging
344
+ * the per-variant scores from `buildVariantScores()`. Used by the spot-check
345
+ * test to demonstrate that variant-routed scoring meaningfully deviates from
346
+ * the soul-aggregate baseline (AC #6).
347
+ *
348
+ * The aggregation rule used here is `mean` — chosen because the failure mode
349
+ * documented in RFC-0017 §2 is the SMOOTHING/AVERAGING effect of soul-aggregate
350
+ * Sα₂ scoring across heterogeneous variants. Comparing variant-routed to mean
351
+ * is what shows the misallocation pattern. (The admission composite itself
352
+ * uses `min` per OQ-4, but that's a different question — we're showing that
353
+ * the per-variant view is structurally different from any soul-level aggregate.)
354
+ */
355
+ export function computeSoulAggregateBaseline(soulId) {
356
+ const scores = buildVariantScores()[soulId];
357
+ if (!scores) {
358
+ throw new Error(`[internal-adopter] no variant scores for soul '${soulId}' — ` +
359
+ `known soulIds: ${INTERNAL_ADOPTER_PRODUCTS.map((p) => p.soulId).join(', ')}`);
360
+ }
361
+ const variants = Object.values(scores);
362
+ const sa1 = variants.reduce((s, v) => s + v.sa1, 0) / variants.length;
363
+ const sa2 = variants.reduce((s, v) => s + v.sa2, 0) / variants.length;
364
+ return { sa1, sa2 };
365
+ }
366
+ //# sourceMappingURL=products.js.map
@@ -0,0 +1,316 @@
1
+ /**
2
+ * RFC-0017 Phase 2 — In-Soul Variant Pattern admission scorer composition.
3
+ *
4
+ * Implements the variant-scope routing algorithm described in RFC-0017 §5.4
5
+ * and §9 (Phase 2):
6
+ *
7
+ * resolveTargetedVariants(w) = set of (soulId, variantId) pairs declared on
8
+ * the work item via `targetedVariants[]` (URI shape `<soul-id>/<variant-id>`).
9
+ *
10
+ * If no `targetedVariants` declared:
11
+ * Scoring proceeds at soul-aggregate scope (backward-compatible — unchanged
12
+ * from RFC-0009 baseline).
13
+ *
14
+ * Else if |targeted| == 1 (single-variant):
15
+ * Sα₁(w) = scoreSα₁(variant.audienceCharacteristics)
16
+ * Sα₂(w) = scoreSα₂(variant.designOverrides ∪ variant.designImperatives)
17
+ *
18
+ * Else (multi-variant):
19
+ * Per-variant Sα₁ + Sα₂ are aggregated via the Soul's
20
+ * `crossVariantAggregation` rule (per-Soul override; default `min` per
21
+ * RFC-0017 OQ-4 / RFC-0009 §7.2 consistency).
22
+ *
23
+ * This module mirrors the surface shape of `tessellation-admission.ts` so the
24
+ * composite reader can compose the two layers cleanly: tessellation routing
25
+ * picks the Soul scope; variant routing refines that to a variant scope when
26
+ * the work item declares targeted variants of one of the affected souls.
27
+ *
28
+ * **Schema dependency note (Phase 1 not yet shipped):**
29
+ * Phase 1 (AISDLC-352) ships the JSON Schema additions for `variants[]` on
30
+ * Soul DID and `targetedVariants[]` on Work Item, plus the inheritance
31
+ * validator. Phase 2 (this file) defines the in-memory shapes the admission
32
+ * composite needs and the pure routing algorithm. Phase 1 loaders will
33
+ * populate `VariantContext` from on-disk Soul DIDs once they exist. The
34
+ * shapes here parallel the schema layout in RFC-0017 §6.1.
35
+ *
36
+ * @see spec/rfcs/RFC-0017-in-soul-variant-pattern.md §5.4 + §9 + §10
37
+ * @see orchestrator/src/tessellation-admission.ts — sibling Soul-scope router
38
+ */
39
+ import type { Tessellation } from '@ai-sdlc/reference';
40
+ /**
41
+ * Framework-owned `designOverrides` enum fields per RFC-0017 §6.1 + OQ-5 revisit (2026-05-26).
42
+ *
43
+ * Design Authority editorial pass (Mo, 2026-05-26): `voiceRegister` cut — 6/6 leading design
44
+ * systems (Tailwind, Radix, Material, Carbon, Spectrum, Atlassian) converge on color, spacing,
45
+ * typography, motion, and radii as the core theming surface; none include content register at
46
+ * the visual token layer. `typographyScale`, `motionProfile`, and `radiusProfile` added.
47
+ *
48
+ * These are the only framework-owned field names. Adopters extend via vendor-prefix
49
+ * (see `designOverridesExt` below).
50
+ */
51
+ export interface VariantDesignOverridesFramework {
52
+ /** Variant-scoped color palette overlay (additive over soul palette). */
53
+ colorPaletteOverlay?: string;
54
+ /** Variant-scoped density profile. */
55
+ densityProfile?: 'compact' | 'comfortable' | 'spacious';
56
+ /** Variant-scoped typography scale. */
57
+ typographyScale?: 'default' | 'large-print' | 'data-dense';
58
+ /** Variant-scoped motion/animation profile. */
59
+ motionProfile?: 'full' | 'reduced' | 'none';
60
+ /** Variant-scoped corner-rounding character (shape, not border stroke weight). */
61
+ radiusProfile?: 'sharp' | 'default' | 'rounded';
62
+ }
63
+ /**
64
+ * Vendor-prefixed `designOverrides` extension map per RFC-0017 OQ-5.
65
+ * Keys MUST follow reverse-DNS prefix convention (e.g. `acme.com/accessibilityProfile`).
66
+ * Schema validation of the prefix is Phase 1's concern; Phase 2 simply consumes
67
+ * whatever keys are present and treats their truthy presence as a variant-scoped
68
+ * Sα₂ signal contribution.
69
+ */
70
+ export type VariantDesignOverridesExt = Record<string, string | number | boolean>;
71
+ /**
72
+ * In-memory representation of one variant declared on a Soul DID, parallel to
73
+ * the YAML/JSON schema fields in RFC-0017 §6.1. Phase 1 (AISDLC-352) ships the
74
+ * schema + loader; Phase 2 uses this shape as the contract between loader and
75
+ * the variant-scope router.
76
+ */
77
+ export interface VariantOverlay {
78
+ /** Variant identifier (kebab-case, unique within the parent Soul). */
79
+ id: string;
80
+ /**
81
+ * Variant-scoped audience characteristics. Feeds Sα₁ Problem/Audience
82
+ * Resonance scoring when the work item targets this variant (RFC-0017
83
+ * §5.4 + §6.1 `targetAudience`).
84
+ */
85
+ audienceCharacteristics?: {
86
+ segments?: string[];
87
+ sizeRange?: {
88
+ minStaff?: number;
89
+ maxStaff?: number;
90
+ };
91
+ /** Free-form adopter-defined audience fields — preserved as-is for Sα₁. */
92
+ [k: string]: unknown;
93
+ };
94
+ /**
95
+ * Framework-owned design override fields (closed enum per OQ-5).
96
+ */
97
+ designOverrides?: VariantDesignOverridesFramework;
98
+ /**
99
+ * Vendor-prefixed adopter extensions (OQ-5). Schema validates the prefix;
100
+ * any present key contributes to the variant-scoped Sα₂ surface.
101
+ */
102
+ designOverridesExt?: VariantDesignOverridesExt;
103
+ /**
104
+ * Variant-scoped Sα₂ design imperatives (layered on top of soul-level
105
+ * imperatives, variant wins on conflict per RFC-0017 §5.4).
106
+ */
107
+ designImperatives?: string[];
108
+ }
109
+ /**
110
+ * Per-variant Sα₁ + Sα₂ scores. One entry per variant of one Soul.
111
+ *
112
+ * Phase 1's loader OR a Phase 2/3 scorer populates this — Phase 2's router
113
+ * is agnostic to how the per-variant scores are produced (could be BM25
114
+ * against `audienceCharacteristics.segments`, embedding similarity against
115
+ * `designImperatives`, etc.). The router only knows how to ROUTE among them.
116
+ */
117
+ export interface VariantScores {
118
+ /** Variant-scoped Sα₁ Problem/Audience Resonance score, in [0, 1]. */
119
+ sa1: number;
120
+ /** Variant-scoped Sα₂ Vibe Coherence score, in [0, 1]. */
121
+ sa2: number;
122
+ }
123
+ /**
124
+ * Per-Soul `variantConfig` block, projected from the
125
+ * `.ai-sdlc/variant-config.yaml` (per-org defaults) + per-Soul overrides
126
+ * in `spec.variantConfig` (RFC-0017 §10.1).
127
+ *
128
+ * Currently surfaces only the OQ-4-resolved knob (cross-variant aggregation).
129
+ * Future Phase-1 phases add `limits`, `lifecycle`, etc.; this interface stays
130
+ * tightly scoped to what the admission router consumes.
131
+ */
132
+ export interface VariantConfig {
133
+ /**
134
+ * OQ-4 — cross-variant aggregation rule. Default `min` (matches RFC-0009
135
+ * §7.2 cross-soul default per the OQ-4 resolution). Per-Soul override
136
+ * accommodates adopters needing `max` for experimental-variant promotion
137
+ * or `mean` for blended audience studies.
138
+ */
139
+ crossVariantAggregation?: VariantAggregationRule;
140
+ }
141
+ /**
142
+ * Supported cross-variant aggregation rules. Subset of `Tessellation['crossSoulScoringRule']`
143
+ * — we expose `min`/`max`/`mean` since those are the variant-scope-meaningful options
144
+ * (the `weighted-*` variants are platform-scope-only per RFC-0009 §5.2).
145
+ */
146
+ export type VariantAggregationRule = 'min' | 'max' | 'mean';
147
+ /**
148
+ * One work item's `targetedVariants[]` declaration. Entries are URI-shaped
149
+ * `<soul-id>/<variant-id>` per RFC-0017 §6.1 (the URI pattern enforced by
150
+ * the schema; we accept the trimmed slug form here because the DID prefix
151
+ * `did:platform-x:soul:` is platform-scoped, not router-scoped).
152
+ *
153
+ * The `did:platform-x:soul:engage/variant:small-utility` URI form from
154
+ * OQ-6 reduces to `engage/small-utility` after the schema's URI parser
155
+ * extracts the soul-id + variant-id segments.
156
+ */
157
+ export interface WorkItemVariantTargeting {
158
+ /** Canonical work item ID (case-insensitive). E.g. "AISDLC-313". */
159
+ id: string;
160
+ /**
161
+ * Variant references in the schema-accepted form. Each entry MUST be the
162
+ * `<soul-id>/<variant-id>` slug pair (the schema's URI parser normalizes
163
+ * the full `did:...:variant:...` form down to this).
164
+ */
165
+ targetedVariants?: string[];
166
+ }
167
+ /**
168
+ * Variant-scope context for the admission composite — everything Phase 2's
169
+ * router needs to refine an already-soul-routed score into a variant-scope
170
+ * score. Built once per pipeline tick from:
171
+ *
172
+ * - The Soul DIDs of every active soul (their `variants[]` declarations)
173
+ * - Pre-computed per-variant Sα₁/Sα₂ scores (Phase 2/3 scorers populate)
174
+ * - The active backlog's work-item targeting (one entry per work item)
175
+ * - Per-Soul `variantConfig` overrides (resolved against per-org defaults)
176
+ *
177
+ * When `undefined` is passed to `computeVariantScopedScores`, the router
178
+ * preserves single-soul Sα₁/Sα₂ semantics unchanged (backward-compatible).
179
+ */
180
+ export interface VariantContext {
181
+ /**
182
+ * Variant overlays keyed by soulId. Source of truth for which variant IDs
183
+ * are valid per Soul + their `audienceCharacteristics` / `designOverrides`.
184
+ */
185
+ variantsBySoul: Record<string, VariantOverlay[]>;
186
+ /**
187
+ * Pre-computed per-variant scores, keyed first by soulId then by variantId.
188
+ * Missing entries fall back to the work item's soul-aggregate Sα₁/Sα₂.
189
+ */
190
+ variantScores: Record<string, Record<string, VariantScores>>;
191
+ /**
192
+ * Work-item targeting entries — one per work item in the active backlog.
193
+ * Missing entries (or empty `targetedVariants`) → backward-compat soul-scope.
194
+ */
195
+ workItemTargeting?: WorkItemVariantTargeting[];
196
+ /**
197
+ * Per-Soul `variantConfig` overrides (defaults to `{ crossVariantAggregation: 'min' }`
198
+ * when absent). Keyed by soulId.
199
+ */
200
+ configBySoul?: Record<string, VariantConfig>;
201
+ }
202
+ /**
203
+ * One parsed targeted-variant reference. Internal use; surfaced via the router
204
+ * for auditability.
205
+ */
206
+ export interface ParsedVariantRef {
207
+ soulId: string;
208
+ variantId: string;
209
+ /** The original schema-form string (for round-trip + error reporting). */
210
+ raw: string;
211
+ }
212
+ /**
213
+ * Parse a targeted-variant reference. Accepts both the schema's accepted forms:
214
+ *
215
+ * 1. Slug-pair: `engage/small-utility` (RFC-0017 §6.1 Work Item schema pattern)
216
+ * 2. Full DID: `did:platform-x:soul:engage/variant:small-utility` (OQ-6)
217
+ *
218
+ * Returns `undefined` for any malformed input — caller's responsibility to
219
+ * surface diagnostics. The schema-side validator is Phase 1's responsibility;
220
+ * the router treats any malformed entry as ignorable (silent skip + caller can
221
+ * count them via the returned `parsedTargets`/`malformedTargets` split if
222
+ * desired).
223
+ */
224
+ export declare function parseTargetedVariantRef(raw: string): ParsedVariantRef | undefined;
225
+ /**
226
+ * Resolve the set of targeted (soulId, variantId) pairs for a given work item.
227
+ *
228
+ * Algorithm:
229
+ * 1. Find the work item by case-insensitive ID match in `workItemTargeting`.
230
+ * 2. Parse each entry of `targetedVariants[]` via `parseTargetedVariantRef`.
231
+ * 3. Filter parsed refs against `variantsBySoul` — a (soulId, variantId) pair
232
+ * only survives if the soul exists AND the variantId is declared on it.
233
+ * 4. Return the validated intersection (empty = backward-compat soul-scope).
234
+ *
235
+ * Returns an empty array (NOT undefined) in all "no variant routing" cases
236
+ * — the caller distinguishes single-variant / multi-variant / soul-scope
237
+ * paths by checking `.length`.
238
+ */
239
+ export declare function resolveTargetedVariants(workItemId: string, variantCtx: VariantContext | undefined): ParsedVariantRef[];
240
+ /**
241
+ * Apply a per-Soul `crossVariantAggregation` rule over per-variant scores.
242
+ * Mirrors `applyCrossSoulRule` in `tessellation-admission.ts` but restricted
243
+ * to the three variant-scope-meaningful aggregations (`min` / `max` / `mean`).
244
+ *
245
+ * @param values - Per-variant score samples (one per targeted variant).
246
+ * @param rule - The aggregation rule (defaults to `min` per OQ-4).
247
+ * @param fallback - Returned when `values` is empty.
248
+ */
249
+ export declare function applyCrossVariantRule(values: number[], rule: VariantAggregationRule | undefined, fallback?: number): number;
250
+ /**
251
+ * Result of variant-scope resolution. Composed with `TessellatedSaResult` by
252
+ * the admission composite — variant routing only takes effect when the work
253
+ * item declares `targetedVariants` AND the variant context is wired in.
254
+ */
255
+ export interface VariantScopedSaResult {
256
+ /** Resolved Sα₁ value in [0, 1] (variant-scoped or fallback). */
257
+ sa1: number;
258
+ /** Resolved Sα₂ value in [0, 1] (variant-scoped or fallback). */
259
+ sa2: number;
260
+ /**
261
+ * Routing path taken (matches RFC-0017 §5.4 case labels).
262
+ *
263
+ * - `'no-variant-routing'` — no context or no targeted variants declared;
264
+ * fallback Sα₁/Sα₂ preserved (backward-compat).
265
+ * - `'single-variant'` — exactly one targeted variant; per-variant Sα₁/Sα₂ used.
266
+ * - `'multi-variant'` — multiple targeted variants; crossVariantAggregation applied.
267
+ */
268
+ routingPath: 'no-variant-routing' | 'single-variant' | 'multi-variant';
269
+ /** Targeted variant references that contributed to the aggregation. */
270
+ targetedVariants: ParsedVariantRef[];
271
+ /**
272
+ * The aggregation rule used when `routingPath === 'multi-variant'`. Undefined
273
+ * for `single-variant` and `no-variant-routing` paths. Exposed for audit.
274
+ */
275
+ aggregationRule?: VariantAggregationRule;
276
+ }
277
+ /**
278
+ * Compute the variant-scope-refined Sα₁ + Sα₂ for a work item.
279
+ *
280
+ * This runs AFTER tessellation soul-resolution: the caller has already routed
281
+ * the work item to its target Soul(s) and obtained the soul-aggregate Sα₁ /
282
+ * Sα₂ (the `fallbackSa1` / `fallbackSa2` arguments). Variant routing refines
283
+ * those values when the work item declares `targetedVariants` of one of the
284
+ * affected Souls (RFC-0017 §5.4).
285
+ *
286
+ * **Cross-soul + cross-variant interaction** (RFC-0017 §6.2 last bullet):
287
+ * "When a work item targets variants in MULTIPLE souls, the cross-soul
288
+ * aggregation rule applies at the soul level FIRST, then the cross-variant
289
+ * rule applies within each soul." Phase 2 implements the per-Soul-scope
290
+ * variant aggregation; the per-Soul `crossVariantAggregation` config picks
291
+ * which rule applies inside each Soul. When variants span multiple souls,
292
+ * each soul's per-variant scores are aggregated by THAT soul's config; the
293
+ * resulting per-soul scores are then aggregated by the cross-soul rule
294
+ * (handled by `tessellation-admission.ts`). At the variant-scope layer we
295
+ * therefore aggregate per-Soul, then aggregate per-Soul-results by `min`
296
+ * (the safest cross-soul aggregation default — matches RFC-0009 §7.2).
297
+ *
298
+ * @param workItemId - The canonical work item ID.
299
+ * @param fallbackSa1 - Soul-scope Sα₁ to use when no variant routing applies.
300
+ * @param fallbackSa2 - Soul-scope Sα₂ to use when no variant routing applies.
301
+ * @param variantCtx - Variant-scope context; undefined → backward-compat passthrough.
302
+ */
303
+ export declare function computeVariantScopedScores(workItemId: string, fallbackSa1: number, fallbackSa2: number, variantCtx: VariantContext | undefined): VariantScopedSaResult;
304
+ /**
305
+ * Helper for callers that already hold a `Tessellation` (sibling SoulScope router)
306
+ * and want to lift Soul-scope tessellation aggregation rule into the
307
+ * variant-scope cross-Soul layer. Currently the variant-scope cross-Soul
308
+ * layer always uses `min` (RFC-0017 §6.2 + RFC-0009 §7.2 safety-critical
309
+ * default). This helper is reserved for a future per-Soul override of the
310
+ * cross-Soul cross-variant layer; today it returns `min` unconditionally.
311
+ *
312
+ * Exported for documentation + so callers can `import` the boundary rather
313
+ * than hardcode `'min'` in two places.
314
+ */
315
+ export declare function defaultCrossSoulVariantRule(_tessellation?: Tessellation): VariantAggregationRule;
316
+ //# sourceMappingURL=variant-admission.d.ts.map