@ai-sdlc/orchestrator 0.10.0 → 0.14.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 (168) 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/analysis/file-walker.js +5 -0
  10. package/dist/backlog-adapter.d.ts +45 -0
  11. package/dist/backlog-adapter.js +145 -1
  12. package/dist/calibration.d.ts +81 -0
  13. package/dist/calibration.js +76 -0
  14. package/dist/cli/commands/git-remote.js +1 -1
  15. package/dist/cli/commands/init-features.d.ts +301 -2
  16. package/dist/cli/commands/init-features.js +647 -7
  17. package/dist/cli/commands/init-templates.d.ts +198 -1
  18. package/dist/cli/commands/init-templates.js +943 -1
  19. package/dist/cli/commands/init.d.ts +45 -0
  20. package/dist/cli/commands/init.js +147 -5
  21. package/dist/cli/commands/run.js +9 -1
  22. package/dist/cli/index.d.ts +11 -0
  23. package/dist/cli/index.js +42 -8
  24. package/dist/compliance/composer.d.ts +79 -0
  25. package/dist/compliance/composer.js +258 -0
  26. package/dist/compliance/errors.d.ts +64 -0
  27. package/dist/compliance/errors.js +85 -0
  28. package/dist/compliance/loader.d.ts +52 -0
  29. package/dist/compliance/loader.js +124 -0
  30. package/dist/compliance/types.d.ts +184 -0
  31. package/dist/compliance/types.js +41 -0
  32. package/dist/compliance-clearance.d.ts +269 -0
  33. package/dist/compliance-clearance.js +269 -0
  34. package/dist/config.js +17 -0
  35. package/dist/cost-tracker.d.ts +22 -0
  36. package/dist/cost-tracker.js +41 -0
  37. package/dist/cycle-utils.js +14 -1
  38. package/dist/database/adapters/external.js +5 -1
  39. package/dist/embedding/adapters/openai-text-embedding-3-small.d.ts +71 -0
  40. package/dist/embedding/adapters/openai-text-embedding-3-small.js +190 -0
  41. package/dist/embedding/consumers/tessellation-drift.d.ts +74 -0
  42. package/dist/embedding/consumers/tessellation-drift.js +76 -0
  43. package/dist/embedding/cross-provider.d.ts +78 -0
  44. package/dist/embedding/cross-provider.js +75 -0
  45. package/dist/embedding/deprecation.d.ts +151 -0
  46. package/dist/embedding/deprecation.js +229 -0
  47. package/dist/embedding/errors.d.ts +90 -0
  48. package/dist/embedding/errors.js +150 -0
  49. package/dist/embedding/index.d.ts +29 -0
  50. package/dist/embedding/index.js +24 -0
  51. package/dist/embedding/pipeline-load.d.ts +146 -0
  52. package/dist/embedding/pipeline-load.js +178 -0
  53. package/dist/embedding/registry.d.ts +45 -0
  54. package/dist/embedding/registry.js +61 -0
  55. package/dist/embedding/stale-vector.d.ts +110 -0
  56. package/dist/embedding/stale-vector.js +92 -0
  57. package/dist/embedding/storage/index.d.ts +51 -0
  58. package/dist/embedding/storage/index.js +43 -0
  59. package/dist/embedding/storage/jsonl-backend.d.ts +150 -0
  60. package/dist/embedding/storage/jsonl-backend.js +332 -0
  61. package/dist/embedding/storage/types.d.ts +135 -0
  62. package/dist/embedding/storage/types.js +13 -0
  63. package/dist/embedding/types.d.ts +180 -0
  64. package/dist/embedding/types.js +10 -0
  65. package/dist/execute.d.ts +29 -2
  66. package/dist/execute.js +200 -38
  67. package/dist/fix-review.js +1 -1
  68. package/dist/index.d.ts +14 -2
  69. package/dist/index.js +19 -2
  70. package/dist/journey/inheritance-validator.d.ts +396 -0
  71. package/dist/journey/inheritance-validator.js +370 -0
  72. package/dist/journey/metric-snapshot.d.ts +403 -0
  73. package/dist/journey/metric-snapshot.js +370 -0
  74. package/dist/journey/state-id-drift-rule.d.ts +137 -0
  75. package/dist/journey/state-id-drift-rule.js +245 -0
  76. package/dist/journey-sa2-router.d.ts +395 -0
  77. package/dist/journey-sa2-router.js +308 -0
  78. package/dist/otel-exporter.js +0 -3
  79. package/dist/runners/claude-code.js +3 -3
  80. package/dist/runners/review-agent.js +6 -2
  81. package/dist/runners/runner-registry.d.ts +36 -0
  82. package/dist/runners/runner-registry.js +90 -0
  83. package/dist/runtime/attestations.d.ts +173 -13
  84. package/dist/runtime/attestations.js +265 -43
  85. package/dist/runtime/index.d.ts +1 -1
  86. package/dist/runtime/index.js +1 -1
  87. package/dist/sa-scoring/exemplar-bank.js +3 -1
  88. package/dist/sa-scoring/layer3-llm.js +6 -1
  89. package/dist/sa-scoring/revision-proposal-config.d.ts +178 -0
  90. package/dist/sa-scoring/revision-proposal-config.js +198 -0
  91. package/dist/sa-scoring/revision-proposal.d.ts +285 -0
  92. package/dist/sa-scoring/revision-proposal.js +417 -0
  93. package/dist/shared.d.ts +28 -0
  94. package/dist/shared.js +37 -0
  95. package/dist/signal-ingestion/adapters/community-thread.d.ts +43 -0
  96. package/dist/signal-ingestion/adapters/community-thread.js +55 -0
  97. package/dist/signal-ingestion/adapters/in-app-feedback.d.ts +67 -0
  98. package/dist/signal-ingestion/adapters/in-app-feedback.js +51 -0
  99. package/dist/signal-ingestion/adapters/manual.d.ts +78 -0
  100. package/dist/signal-ingestion/adapters/manual.js +112 -0
  101. package/dist/signal-ingestion/adapters/support-ticket.d.ts +47 -0
  102. package/dist/signal-ingestion/adapters/support-ticket.js +51 -0
  103. package/dist/signal-ingestion/classifier.d.ts +205 -0
  104. package/dist/signal-ingestion/classifier.js +494 -0
  105. package/dist/signal-ingestion/clustering-types.d.ts +36 -0
  106. package/dist/signal-ingestion/clustering-types.js +14 -0
  107. package/dist/signal-ingestion/clustering.d.ts +200 -0
  108. package/dist/signal-ingestion/clustering.js +413 -0
  109. package/dist/signal-ingestion/config.d.ts +351 -0
  110. package/dist/signal-ingestion/config.js +587 -0
  111. package/dist/signal-ingestion/d1.d.ts +252 -0
  112. package/dist/signal-ingestion/d1.js +235 -0
  113. package/dist/signal-ingestion/errors.d.ts +73 -0
  114. package/dist/signal-ingestion/errors.js +108 -0
  115. package/dist/signal-ingestion/governance-events.d.ts +181 -0
  116. package/dist/signal-ingestion/governance-events.js +189 -0
  117. package/dist/signal-ingestion/index.d.ts +35 -0
  118. package/dist/signal-ingestion/index.js +53 -0
  119. package/dist/signal-ingestion/manual-share-metric.d.ts +93 -0
  120. package/dist/signal-ingestion/manual-share-metric.js +106 -0
  121. package/dist/signal-ingestion/registry.d.ts +40 -0
  122. package/dist/signal-ingestion/registry.js +137 -0
  123. package/dist/signal-ingestion/residency.d.ts +227 -0
  124. package/dist/signal-ingestion/residency.js +238 -0
  125. package/dist/signal-ingestion/significance.d.ts +554 -0
  126. package/dist/signal-ingestion/significance.js +555 -0
  127. package/dist/signal-ingestion/types.d.ts +191 -0
  128. package/dist/signal-ingestion/types.js +8 -0
  129. package/dist/substrate/drift-composition.d.ts +270 -0
  130. package/dist/substrate/drift-composition.js +306 -0
  131. package/dist/substrate/drift-tui-surface.d.ts +61 -0
  132. package/dist/substrate/drift-tui-surface.js +102 -0
  133. package/dist/substrate/identity-class.d.ts +176 -0
  134. package/dist/substrate/identity-class.js +201 -0
  135. package/dist/tessellation/cross-soul-provenance-rule.d.ts +133 -0
  136. package/dist/tessellation/cross-soul-provenance-rule.js +171 -0
  137. package/dist/tessellation/inter-soul-embedding-distance-rule.d.ts +61 -0
  138. package/dist/tessellation/inter-soul-embedding-distance-rule.js +67 -0
  139. package/dist/tessellation/rule-registry.d.ts +269 -0
  140. package/dist/tessellation/rule-registry.js +92 -0
  141. package/dist/tessellation/soul-slug-ast-scan-rule.d.ts +90 -0
  142. package/dist/tessellation/soul-slug-ast-scan-rule.js +158 -0
  143. package/dist/tessellation-admission.d.ts +162 -0
  144. package/dist/tessellation-admission.js +146 -0
  145. package/dist/tessellation-drift.d.ts +246 -0
  146. package/dist/tessellation-drift.js +250 -0
  147. package/dist/validate-config.js +13 -0
  148. package/dist/validate-issue.js +2 -2
  149. package/dist/variant/cardinality-activation.d.ts +126 -0
  150. package/dist/variant/cardinality-activation.js +101 -0
  151. package/dist/variant/deprecation-lifecycle.d.ts +184 -0
  152. package/dist/variant/deprecation-lifecycle.js +208 -0
  153. package/dist/variant/drift-extension.d.ts +136 -0
  154. package/dist/variant/drift-extension.js +164 -0
  155. package/dist/variant/engineering-review.d.ts +185 -0
  156. package/dist/variant/engineering-review.js +142 -0
  157. package/dist/variant/index.d.ts +32 -0
  158. package/dist/variant/index.js +32 -0
  159. package/dist/variant/inheritance-validator.d.ts +165 -0
  160. package/dist/variant/inheritance-validator.js +139 -0
  161. package/dist/variant/internal-adopter/index.d.ts +11 -0
  162. package/dist/variant/internal-adopter/index.js +10 -0
  163. package/dist/variant/internal-adopter/products.d.ts +156 -0
  164. package/dist/variant/internal-adopter/products.js +366 -0
  165. package/dist/variant-admission.d.ts +316 -0
  166. package/dist/variant-admission.js +247 -0
  167. package/dist/webhook-manager.js +7 -1
  168. package/package.json +15 -12
@@ -0,0 +1,245 @@
1
+ /**
2
+ * RFC-0018 Phase 3 — JourneyStateIdDriftRule (RFC-0009 §13 Rule #4).
3
+ *
4
+ * Implements the 4th §13 drift-detection rule resolving RFC-0018 OQ-8 + OQ-10
5
+ * (2026-05-28, full rubric):
6
+ *
7
+ * OQ-8: "AST scan from v1, reusing RFC-0009 §13 Rule #1 infrastructure."
8
+ * The existing AST scan engine ALREADY EXISTS for soul-slug leakage
9
+ * detection — adding journey state-ID detection is extending the
10
+ * engine with one additional rule, not building from scratch.
11
+ *
12
+ * OQ-10: "4th rule in the same §13 engine + concrete registration mechanism
13
+ * spec'd: Tessellation§13RuleRegistry.register(rule)."
14
+ *
15
+ * ### Detection strategy
16
+ *
17
+ * The rule reuses the `scanSubstrateFile` textual-scan approach from the
18
+ * existing AST scan engine in `tessellation-drift.ts`. This is deliberately
19
+ * NOT a string match — it uses the same regex-based pattern matching that
20
+ * Rule #1 employs, consistent with the OQ-8 resolution:
21
+ *
22
+ * - Bare string literal: `'<state-id>'` or `"<state-id>"`
23
+ * - State-discriminating conditional: `state === '<state-id>'` / similar
24
+ *
25
+ * This matches the OQ-8 resolution that explicitly rejected the string-match
26
+ * path in favour of the existing AST scan infrastructure.
27
+ *
28
+ * ### Drift conditions
29
+ *
30
+ * Emits `Decision: journey-state-id-drift` when substrate code references:
31
+ * 1. A state ID that is NOT declared in any active journey.
32
+ * 2. A state ID from a journey that has been removed (lifecycle = 'removed').
33
+ *
34
+ * ### Composition with RFC-0028 OQ-7.2
35
+ *
36
+ * Structural drift (this rule at CI authoring time) slots into the structural
37
+ * side of the OQ-7.2 pairing:
38
+ * - `severity === 'high'` → BLOCKS PR via Decision severity HIGH.
39
+ * - `severity === 'medium'` (default) → SURFACES non-blocking via RFC-0035
40
+ * G0 catalog route for operator batch review.
41
+ *
42
+ * Default severity is `'medium'` per RFC-0018 §10.1 (per-org configurable
43
+ * via `journey-config.yaml driftDetection.severityOverride`).
44
+ *
45
+ * @see spec/rfcs/RFC-0018-in-soul-journey-pattern.md §6.2 + §10.1 OQ-8 + OQ-10
46
+ * @see spec/rfcs/RFC-0009-tessellated-design-intent-documents.md §13
47
+ * @see spec/rfcs/RFC-0028-engineering-axis-substrate-enforcement.md OQ-7.2
48
+ * @see orchestrator/src/tessellation-drift.ts (source of the AST-scan engine reused here)
49
+ */
50
+ // ── AST scan helpers ───────────────────────────────────────────────────
51
+ /**
52
+ * Validate a journey state ID. Valid state IDs are kebab-case: lowercase
53
+ * alphanumeric + dashes, 1-64 chars. Mirrors the soul-slug validator in
54
+ * `tessellation-drift.ts` but applied to journey state IDs.
55
+ */
56
+ function isValidStateId(id) {
57
+ return /^[a-z0-9][a-z0-9-]*$/.test(id) && id.length >= 1 && id.length <= 64;
58
+ }
59
+ /** Escape a string for safe use inside a RegExp pattern. */
60
+ function escapeRegex(s) {
61
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
62
+ }
63
+ /**
64
+ * Scan a single substrate file for references to a set of state IDs.
65
+ *
66
+ * Reuses the same regex-based textual-scan strategy as the soul-slug
67
+ * AST scan in `tessellation-drift.ts` (Rule #1). This is the OQ-8
68
+ * resolution's "reusing RFC-0009 §13 Rule #1 infrastructure" in action:
69
+ * same two patterns (string-literal + state-conditional), extended to
70
+ * match journey state-ID strings rather than soul slugs.
71
+ *
72
+ * Two patterns per state ID (line-by-line):
73
+ * 1. `'<state-id>'` or `"<state-id>"` — bare string literal.
74
+ * 2. `state === '<state-id>'` / similar — state-discriminating conditional.
75
+ * Permissive match on the identifier name: `state`, `stateId`, `state_id`,
76
+ * `journeyState`, etc.
77
+ */
78
+ function scanFileForStateIds(file, stateIds) {
79
+ const findings = [];
80
+ if (file.contents.length === 0 || stateIds.length === 0)
81
+ return findings;
82
+ const lines = file.contents.split('\n');
83
+ for (const stateId of stateIds) {
84
+ if (!isValidStateId(stateId))
85
+ continue;
86
+ const esc = escapeRegex(stateId);
87
+ // Pattern 1: bare string literal (single or double quote, exact match).
88
+ const literalRe = new RegExp(`(['"])${esc}\\1`);
89
+ // Pattern 2: state-discriminating conditional.
90
+ // Permissive on the state identifier name: catches `state`, `stateId`,
91
+ // `state_id`, `journeyState`, `currentState`, etc.
92
+ const condRe = new RegExp(`(?:state|stateId|state_id|journeyState|currentState|journeyStep|stepId)[A-Za-z_]*\\s*===\\s*(['"])${esc}\\1`);
93
+ for (let i = 0; i < lines.length; i++) {
94
+ const line = lines[i];
95
+ const condMatch = line.match(condRe);
96
+ if (condMatch) {
97
+ findings.push({
98
+ stateId,
99
+ line: i + 1,
100
+ pattern: 'state-conditional',
101
+ excerpt: line.trim().slice(0, 200),
102
+ });
103
+ // Don't double-report the same line as a bare literal.
104
+ continue;
105
+ }
106
+ if (literalRe.test(line)) {
107
+ findings.push({
108
+ stateId,
109
+ line: i + 1,
110
+ pattern: 'string-literal',
111
+ excerpt: line.trim().slice(0, 200),
112
+ });
113
+ }
114
+ }
115
+ }
116
+ return findings;
117
+ }
118
+ // ── Rule implementation ────────────────────────────────────────────────
119
+ /**
120
+ * JourneyStateIdDriftRule — RFC-0009 §13 Rule #4.
121
+ *
122
+ * Scans substrate code for references to journey-state-id strings using
123
+ * the existing AST scan engine from Rule #1 (OQ-8 resolution: NOT string
124
+ * match). Emits `Decision: journey-state-id-drift` when:
125
+ *
126
+ * - Referenced state ID is not declared in any active journey, OR
127
+ * - The journey itself has been removed (cross-references journey lifecycle /
128
+ * deprecation tooling).
129
+ *
130
+ * Severity is per-org configurable (default `'medium'`).
131
+ *
132
+ * ### Registration
133
+ *
134
+ * ```ts
135
+ * const registry = createTessellation13Registry();
136
+ * registry.register(new JourneyStateIdDriftRule());
137
+ * // With config override:
138
+ * registry.register(new JourneyStateIdDriftRule({ severityOverride: 'high' }));
139
+ * ```
140
+ */
141
+ export class JourneyStateIdDriftRule {
142
+ name = 'journey-state-id-drift';
143
+ description = 'Scans substrate code for references to journey state IDs that are not declared in any active journey or belong to a removed journey (RFC-0018 Phase 3, OQ-8 resolution)';
144
+ severity;
145
+ config;
146
+ constructor(config = {}) {
147
+ this.config = config;
148
+ this.severity = config.severityOverride ?? 'medium';
149
+ }
150
+ scan(target) {
151
+ const { substrateFiles, journeysBySoul, journeyStatus } = target;
152
+ // No-op when no substrate files or no journey declarations.
153
+ if (!substrateFiles || substrateFiles.length === 0)
154
+ return [];
155
+ if (!journeysBySoul || Object.keys(journeysBySoul).length === 0)
156
+ return [];
157
+ const now = new Date().toISOString();
158
+ const activeStateIds = new Set();
159
+ const removedStateIdEntries = [];
160
+ for (const [soulId, journeys] of Object.entries(journeysBySoul)) {
161
+ for (const journey of journeys) {
162
+ const statusKey = `${soulId}/${journey.id}`;
163
+ const status = journeyStatus?.[statusKey] ?? 'active';
164
+ for (const state of journey.states ?? []) {
165
+ if (!isValidStateId(state.id))
166
+ continue;
167
+ if (status === 'removed') {
168
+ removedStateIdEntries.push({
169
+ stateId: state.id,
170
+ journeyId: journey.id,
171
+ soulId,
172
+ });
173
+ }
174
+ else {
175
+ activeStateIds.add(state.id);
176
+ }
177
+ }
178
+ }
179
+ }
180
+ // ── Scan substrate files ───────────────────────────────────────────
181
+ const findings = [];
182
+ for (const file of substrateFiles) {
183
+ // ── Check for removed state IDs ──────────────────────────────
184
+ // Build the set of removed state IDs (may overlap with active if
185
+ // the same state ID exists in both an active and removed journey;
186
+ // in that case, active wins and we skip).
187
+ const removedStateIds = removedStateIdEntries
188
+ .map((e) => e.stateId)
189
+ .filter((id) => !activeStateIds.has(id));
190
+ if (removedStateIds.length > 0) {
191
+ const hits = scanFileForStateIds(file, removedStateIds);
192
+ for (const hit of hits) {
193
+ const entry = removedStateIdEntries.find((e) => e.stateId === hit.stateId && !activeStateIds.has(e.stateId));
194
+ findings.push({
195
+ kind: 'removed-journey-state-id',
196
+ stateId: hit.stateId,
197
+ journeyId: entry?.journeyId,
198
+ soulId: entry?.soulId,
199
+ filePath: file.path,
200
+ line: hit.line,
201
+ pattern: hit.pattern,
202
+ excerpt: hit.excerpt,
203
+ });
204
+ }
205
+ }
206
+ }
207
+ // ── Collect all active state IDs to check for undeclared refs ─────
208
+ // Build a map: stateId → [list of files where it was found]
209
+ // Then determine which found state IDs are NOT in activeStateIds.
210
+ //
211
+ // "Undeclared" means: the string appears in substrate code as a
212
+ // potential state-ID reference, but it is not declared in any
213
+ // active journey AND not in any removed journey.
214
+ //
215
+ // To avoid false positives from common short strings (single-char
216
+ // IDs etc.), we only scan for state IDs that are actually declared
217
+ // (active or removed). Strings that look like state IDs but match
218
+ // NOTHING in the journey manifest are not reported — we only report
219
+ // when a declared (but removed) state ID is found.
220
+ //
221
+ // NOTE: "undeclared state ID" in the RFC sense means a string in
222
+ // substrate code that LOOKS like a state-ID reference but refers to
223
+ // a state ID that has been removed AND is no longer in any active journey.
224
+ // The above removed-state-ID scan covers this case.
225
+ //
226
+ // If the caller wants to detect references to strings that were NEVER
227
+ // in any journey at all, they need to provide a corpus of all historical
228
+ // state IDs. For v1, we report only the "was declared, now removed" case
229
+ // (the RFC-0018 §6.2 drift condition).
230
+ if (findings.length === 0)
231
+ return [];
232
+ const event = {
233
+ rule: this.name,
234
+ timestamp: now,
235
+ message: `Journey state-ID drift: ${findings.length} reference(s) to removed or undeclared journey state IDs in substrate code`,
236
+ severity: this.severity,
237
+ details: {
238
+ rule: 'journey-state-id-drift',
239
+ findings,
240
+ },
241
+ };
242
+ return [event];
243
+ }
244
+ }
245
+ //# sourceMappingURL=state-id-drift-rule.js.map
@@ -0,0 +1,395 @@
1
+ /**
2
+ * RFC-0018 Phase 2 — In-Soul Journey Pattern admission scorer composition.
3
+ *
4
+ * Implements the journey-scope routing algorithm described in RFC-0018 §5.4
5
+ * and §10.1 (OQ-4 resolution):
6
+ *
7
+ * resolveTargetedJourneys(w) = set of (soulId, [variantId,] journeyId) triples
8
+ * declared on the work item via `targetedJourneys[]` (URI shapes
9
+ * `<soul-id>/<journey-id>` or `<soul-id>/<variant-id>/<journey-id>`).
10
+ *
11
+ * If no `targetedJourneys` declared:
12
+ * Scoring proceeds at soul/variant scope (backward-compatible — unchanged
13
+ * from RFC-0009 + RFC-0017 baseline).
14
+ *
15
+ * Else if |targeted| == 1 (single-journey):
16
+ * Sα₂(w) = scoreSα₂(journey.designImperatives UNION variant's UNION soul's;
17
+ * most-specific wins: journey > variant > soul)
18
+ * Cκ(w) = boosted when journey.successMetrics.completion-rate < alertBelow
19
+ * Eρ₅(w) = elevated when journey.accessibility.wcagLevel > soul/variant default
20
+ *
21
+ * Else (multi-journey):
22
+ * Per-journey scores aggregated via `crossJourneyAggregation` config
23
+ * (default `min` per RFC-0018 §5.4 + RFC-0017 OQ-4 cross-variant pattern).
24
+ *
25
+ * ### Completion-criteria closed enum (OQ-4 resolution)
26
+ *
27
+ * v1 allows only: `terminal-success-state` | `all-states-reached`
28
+ * `custom-predicate` is rejected at schema validation time.
29
+ * Future activation via `Decision: journey-custom-predicate-activation-request`
30
+ * (Stage A counter, auto-promote at ≥2 distinct adopter requests).
31
+ * Future language: CEL (Google Common Expression Language) per OQ-4 resolution.
32
+ *
33
+ * ### Backward compatibility
34
+ *
35
+ * Work items without `targetedJourneys` score against soul / variant (existing
36
+ * RFC-0017 behavior preserved). Soul DIDs without `journeys[]` behave identically.
37
+ *
38
+ * @see spec/rfcs/RFC-0018-in-soul-journey-pattern.md §5.4 + §10 + §10.1
39
+ * @see orchestrator/src/variant-admission.ts — sibling RFC-0017 Phase 2 router
40
+ * @see orchestrator/src/compliance-clearance.ts — Eρ₅ base scorer
41
+ */
42
+ /**
43
+ * v1 closed enum for completion-criteria `kind` per RFC-0018 OQ-4 resolution
44
+ * (2026-05-28, full rubric).
45
+ *
46
+ * `custom-predicate` is intentionally absent — schema validation MUST reject
47
+ * it. Future RFC will activate it via the Decision Catalog with CEL as the
48
+ * recommended expression language.
49
+ */
50
+ export type CompletionCriteriaKind = 'terminal-success-state' | 'all-states-reached';
51
+ /**
52
+ * The set of valid v1 completion-criteria kind values.
53
+ * Used by `validateCompletionCriteriaKind` for closed-enum rejection.
54
+ */
55
+ export declare const COMPLETION_CRITERIA_V1_KINDS: ReadonlySet<CompletionCriteriaKind>;
56
+ /**
57
+ * Decision kind for the `custom-predicate` activation request counter.
58
+ * Stage A counter per RFC-0035 G0 non-blocking contract.
59
+ * Auto-promotes at ≥2 distinct adopter requests (RFC-0018 OQ-4 resolution).
60
+ */
61
+ export declare const JOURNEY_CUSTOM_PREDICATE_DECISION_KIND: "journey-custom-predicate-activation-request";
62
+ /**
63
+ * Result of validating a completion-criteria `kind` value against the v1 closed enum.
64
+ */
65
+ export interface CompletionCriteriaValidationResult {
66
+ /** True when the kind value is in the v1 closed enum. */
67
+ valid: boolean;
68
+ /**
69
+ * When `valid === false`, the rejected kind string (e.g. `'custom-predicate'`).
70
+ * Used for diagnostics + Decision counter registration.
71
+ */
72
+ rejectedKind?: string;
73
+ /**
74
+ * When `valid === false` AND the rejected kind is `'custom-predicate'`,
75
+ * the Decision kind to emit to the catalog (Stage A counter).
76
+ */
77
+ decisionKind?: typeof JOURNEY_CUSTOM_PREDICATE_DECISION_KIND;
78
+ }
79
+ /**
80
+ * Validate a completion-criteria `kind` value against the v1 closed enum.
81
+ *
82
+ * Returns `{ valid: true }` for `terminal-success-state` and `all-states-reached`.
83
+ * Returns `{ valid: false, rejectedKind, decisionKind }` for `custom-predicate`
84
+ * (or any other unrecognized value). The caller is responsible for emitting the
85
+ * Decision event to the RFC-0035 catalog.
86
+ */
87
+ export declare function validateCompletionCriteriaKind(kind: string): CompletionCriteriaValidationResult;
88
+ /**
89
+ * In-memory Stage A counter for `journey-custom-predicate-activation-request`.
90
+ *
91
+ * Per RFC-0018 OQ-4 resolution: auto-promote to a decision walkthrough at ≥2
92
+ * distinct adopter requests. The counter tracks (adopter-id, feature-id) pairs
93
+ * to deduplicate requests from the same adopter — "2 distinct adopter requests"
94
+ * means 2 different adopter IDs, not 2 calls from the same adopter.
95
+ *
96
+ * In v1 this is an in-memory counter (reset per process). Phase 2 will persist
97
+ * it via the RFC-0035 Decision Catalog `cli-decisions` surface (AISDLC-463).
98
+ */
99
+ export interface DecisionCounter {
100
+ /** The RFC-0035 decision kind being counted. */
101
+ decisionKind: typeof JOURNEY_CUSTOM_PREDICATE_DECISION_KIND;
102
+ /**
103
+ * Deduplicated adopter IDs that have submitted a request.
104
+ * When `size >= 2`, the counter has crossed the auto-promote threshold.
105
+ */
106
+ distinctAdopterIds: Set<string>;
107
+ /** Total raw request count (including duplicates from same adopter). */
108
+ totalRequests: number;
109
+ /** Whether the auto-promote threshold (≥2 distinct adopters) has been crossed. */
110
+ shouldAutoPromote: boolean;
111
+ }
112
+ /**
113
+ * Increment the Stage A counter for a `journey-custom-predicate-activation-request`.
114
+ *
115
+ * @param counter - The counter to increment (mutated in-place).
116
+ * @param adopterId - Adopter ID submitting the request (for deduplication).
117
+ * Use `'__unknown__'` when adopter identity is unavailable.
118
+ */
119
+ export declare function incrementDecisionCounter(counter: DecisionCounter, adopterId: string): void;
120
+ /**
121
+ * Create a fresh Stage A counter for `journey-custom-predicate-activation-request`.
122
+ */
123
+ export declare function createCustomPredicateDecisionCounter(): DecisionCounter;
124
+ /**
125
+ * WCAG conformance levels in ascending strictness order.
126
+ * Used for journey-vs-soul WCAG comparison (Eρ₅ elevation).
127
+ */
128
+ export type WcagLevel = 'A' | 'AA' | 'AAA';
129
+ /**
130
+ * Returns true when `journeyLevel` is strictly ABOVE `soulDefault`.
131
+ * Journeys MAY raise the WCAG level above the parent; they MAY NOT lower it.
132
+ */
133
+ export declare function isWcagElevated(journeyLevel: WcagLevel, soulDefault: WcagLevel): boolean;
134
+ /**
135
+ * A single success metric declared on a Journey.
136
+ * Feeds Cκ (Capability Coverage) scoring at journey scope.
137
+ */
138
+ export interface JourneySuccessMetric {
139
+ /** Metric identifier (e.g. `'completion-rate'`, `'median-time-to-first-task-done'`). */
140
+ id: string;
141
+ /** Target value (e.g. `0.65` for 65% completion rate). */
142
+ target?: number;
143
+ /** Alert threshold: when current value drops below this, Cκ boost applies. */
144
+ alertBelow?: number;
145
+ /** Alert threshold: when current value rises above this, signal fires. */
146
+ alertAbove?: number;
147
+ /** Target seconds (for time-based metrics). */
148
+ targetSeconds?: number;
149
+ }
150
+ /**
151
+ * Accessibility requirements for a Journey (RFC-0018 §5.2).
152
+ * Journey WCAG level may be set HIGHER than the soul floor.
153
+ */
154
+ export interface JourneyAccessibility {
155
+ wcagLevel: WcagLevel;
156
+ wcagVersion: '2.0' | '2.1' | '2.2' | '3.0';
157
+ conformanceTarget: number;
158
+ auditCadence?: 'quarterly' | 'annually' | 'release-gated' | 'continuous';
159
+ }
160
+ /**
161
+ * Completion criteria for a Journey (v1 closed enum per OQ-4).
162
+ * `kind` MUST be `terminal-success-state` or `all-states-reached`.
163
+ * `custom-predicate` is rejected at schema validation; see `validateCompletionCriteriaKind`.
164
+ */
165
+ export interface JourneyCompletionCriteria {
166
+ kind: CompletionCriteriaKind;
167
+ /** Required when `kind === 'terminal-success-state'`. */
168
+ target?: string;
169
+ }
170
+ /**
171
+ * In-memory representation of one Journey declared on a Soul DID or Variant,
172
+ * parallel to the YAML/JSON schema fields in RFC-0018 §6.1.
173
+ *
174
+ * Phase 1 (AISDLC-465) ships the schema; Phase 2 (this file) defines the
175
+ * in-memory shape the admission composite needs for journey-scope routing.
176
+ */
177
+ export interface JourneyDeclaration {
178
+ /** Journey identifier (kebab-case, unique within parent scope). */
179
+ id: string;
180
+ /**
181
+ * Journey scope: applies to all variants (`'soul'`) or a specific variant
182
+ * (`'variant:<variant-id>'`).
183
+ */
184
+ scope: 'soul' | `variant:${string}`;
185
+ /** v1 closed-enum completion criteria. */
186
+ completionCriteria: JourneyCompletionCriteria;
187
+ /** Accessibility requirements; wcagLevel may exceed soul floor. */
188
+ accessibility: JourneyAccessibility;
189
+ /** Journey-scoped success metrics. Feeds Cκ scoring. */
190
+ successMetrics?: JourneySuccessMetric[];
191
+ /** Journey-scoped design imperatives. UNION with variant/soul; most-specific wins. */
192
+ designImperatives?: string[];
193
+ }
194
+ /**
195
+ * Pre-computed scores for a single Journey.
196
+ * The journey-scope router uses these when computing Sα₂ + Cκ + Eρ₅.
197
+ *
198
+ * In a production pipeline these are populated by loaders reading the soul's
199
+ * `journeys[]` declarations plus live metric snapshots.
200
+ */
201
+ export interface JourneyScores {
202
+ /**
203
+ * Journey-scoped Sα₂ (Vibe Coherence) in [0, 1].
204
+ * Derived from journey.designImperatives UNION variant's UNION soul's;
205
+ * most-specific wins (journey > variant > soul).
206
+ */
207
+ sa2: number;
208
+ /**
209
+ * Journey-scoped Cκ (Capability Coverage) in [0, 1].
210
+ * Boosted above the soul/variant baseline when `completion-rate < alertBelow`.
211
+ */
212
+ ck: number;
213
+ /**
214
+ * Whether journey accessibility requirements are elevated above soul floor.
215
+ * When true, Eρ₅ Compliance Clearance is checked at journey-elevated WCAG
216
+ * level rather than the soul-default. Categorical: `true` = elevation active.
217
+ */
218
+ er5Elevated: boolean;
219
+ }
220
+ /**
221
+ * Per-Soul / per-org cross-journey aggregation config.
222
+ * Default `min` per RFC-0018 §5.4 (matching RFC-0017 OQ-4 cross-variant pattern).
223
+ */
224
+ export type JourneyAggregationRule = 'min' | 'max' | 'mean';
225
+ /**
226
+ * Per-Soul journey configuration (subset of §10.1 journey-config.yaml schema).
227
+ */
228
+ export interface JourneyConfig {
229
+ /**
230
+ * Cross-journey aggregation rule for multi-journey work items.
231
+ * Default `min` per RFC-0018 §5.4. Per-Soul override via journey-config.yaml.
232
+ */
233
+ crossJourneyAggregation?: JourneyAggregationRule;
234
+ /**
235
+ * Soul-default WCAG level — used for Eρ₅ elevation comparison.
236
+ * When absent, `'AA'` is assumed (WCAG 2.1 AA is the industry-standard floor).
237
+ */
238
+ soulWcagDefault?: WcagLevel;
239
+ }
240
+ /**
241
+ * Work-item targeting entry for journey-scope routing.
242
+ * One entry per work item in the active backlog.
243
+ */
244
+ export interface WorkItemJourneyTargeting {
245
+ /** Canonical work item ID (case-insensitive match). */
246
+ id: string;
247
+ /**
248
+ * Journey references declared on the work item.
249
+ * URI shape: `<soul-id>/<journey-id>` OR `<soul-id>/<variant-id>/<journey-id>`
250
+ * per RFC-0018 §6.1 Work Item schema.
251
+ */
252
+ targetedJourneys?: string[];
253
+ }
254
+ /**
255
+ * All journey-scope context needed by the admission composite for RFC-0018 Phase 2.
256
+ *
257
+ * Callers build this once per pipeline tick and pass it to
258
+ * `computeJourneyScopedScores` via `AdmissionCompositeOptions.journeyContext`.
259
+ */
260
+ export interface JourneyContext {
261
+ /**
262
+ * Journey declarations keyed by soulId. Source of truth for which journey IDs
263
+ * are valid per Soul + their scoring configuration.
264
+ */
265
+ journeysBySoul: Record<string, JourneyDeclaration[]>;
266
+ /**
267
+ * Pre-computed per-journey scores, keyed first by soulId then by journeyId.
268
+ * Missing entries fall back to the work item's soul/variant Sα₂/Cκ/Eρ₅.
269
+ */
270
+ journeyScores: Record<string, Record<string, JourneyScores>>;
271
+ /**
272
+ * Work-item targeting entries — one per work item in the active backlog.
273
+ * Missing entries (or empty `targetedJourneys`) → backward-compat soul/variant scope.
274
+ */
275
+ workItemTargeting?: WorkItemJourneyTargeting[];
276
+ /**
277
+ * Per-Soul journey configuration overrides.
278
+ * Keyed by soulId. Absent → `{ crossJourneyAggregation: 'min' }` default.
279
+ */
280
+ configBySoul?: Record<string, JourneyConfig>;
281
+ }
282
+ /**
283
+ * One parsed targeted-journey reference. Internal use; surfaced via the router
284
+ * for auditability.
285
+ */
286
+ export interface ParsedJourneyRef {
287
+ soulId: string;
288
+ /** Present when the journey is variant-scoped (URI form: soul/variant/journey). */
289
+ variantId?: string;
290
+ journeyId: string;
291
+ /** The original URI string (for round-trip + error reporting). */
292
+ raw: string;
293
+ }
294
+ /**
295
+ * Parse a targeted-journey reference.
296
+ *
297
+ * Accepts two URI forms per RFC-0018 §6.1:
298
+ *
299
+ * 1. `<soul-id>/<journey-id>` — soul-scoped journey
300
+ * 2. `<soul-id>/<variant-id>/<journey-id>` — variant-scoped journey
301
+ *
302
+ * All slug segments must match `^[a-z][a-z0-9-]*$`.
303
+ * Returns `undefined` for malformed input (silent skip; schema-side validator
304
+ * is Phase 1's concern per RFC-0018 §6.1 pattern).
305
+ */
306
+ export declare function parseTargetedJourneyRef(raw: string): ParsedJourneyRef | undefined;
307
+ /**
308
+ * Resolve the set of targeted (soulId, [variantId,] journeyId) triples for a work item.
309
+ *
310
+ * Algorithm:
311
+ * 1. Find the work item by case-insensitive ID match in `workItemTargeting`.
312
+ * 2. Parse each entry of `targetedJourneys[]` via `parseTargetedJourneyRef`.
313
+ * 3. Filter parsed refs against `journeysBySoul` — a (soulId, journeyId) pair
314
+ * only survives if the soul exists AND the journeyId is declared on it.
315
+ * 4. Return the validated intersection (empty = backward-compat soul/variant scope).
316
+ */
317
+ export declare function resolveTargetedJourneys(workItemId: string, journeyCtx: JourneyContext | undefined): ParsedJourneyRef[];
318
+ /**
319
+ * Apply a per-Soul `crossJourneyAggregation` rule over per-journey scores.
320
+ * Mirrors `applyCrossVariantRule` in `variant-admission.ts` but for journey scope.
321
+ *
322
+ * @param values - Per-journey score samples (one per targeted journey).
323
+ * @param rule - The aggregation rule (defaults to `min` per RFC-0018 §5.4 + OQ-4).
324
+ * @param fallback - Returned when `values` is empty.
325
+ */
326
+ export declare function applyCrossJourneyRule(values: number[], rule: JourneyAggregationRule | undefined, fallback?: number): number;
327
+ /**
328
+ * Result of journey-scope resolution. Composed with variant-scope and
329
+ * tessellation results by the admission composite.
330
+ *
331
+ * Journey routing refines Sα₂, Cκ, and Eρ₅ when the work item declares
332
+ * `targetedJourneys` (RFC-0018 §5.4). Sα₁ and Dπ_n remain at soul/variant
333
+ * scope (journeys don't redefine audience or demand channels).
334
+ */
335
+ export interface JourneyScopedResult {
336
+ /** Resolved Sα₂ in [0, 1] (journey-scoped or fallback). */
337
+ sa2: number;
338
+ /** Resolved Cκ in [0, 1] (journey-scoped or fallback). */
339
+ ck: number;
340
+ /**
341
+ * Whether Eρ₅ should be evaluated at journey-elevated WCAG level.
342
+ * When `true`, the caller MUST apply Eρ₅ gating at the journey's WCAG
343
+ * level rather than the soul-default. `false` = soul-default applies.
344
+ */
345
+ er5Elevated: boolean;
346
+ /**
347
+ * Routing path taken (matches RFC-0018 §5.4 case labels).
348
+ *
349
+ * - `'no-journey-routing'` — no context or no targeted journeys declared;
350
+ * fallback Sα₂/Cκ/Eρ₅ preserved (backward-compat).
351
+ * - `'single-journey'` — exactly one targeted journey; per-journey scores used.
352
+ * - `'multi-journey'` — multiple targeted journeys; crossJourneyAggregation applied.
353
+ */
354
+ routingPath: 'no-journey-routing' | 'single-journey' | 'multi-journey';
355
+ /** Targeted journey references that contributed to the aggregation. */
356
+ targetedJourneys: ParsedJourneyRef[];
357
+ /**
358
+ * The aggregation rule used when `routingPath === 'multi-journey'`. Undefined
359
+ * for `single-journey` and `no-journey-routing` paths. Exposed for audit.
360
+ */
361
+ aggregationRule?: JourneyAggregationRule;
362
+ }
363
+ /**
364
+ * Compute the journey-scope-refined Sα₂ + Cκ + Eρ₅ for a work item.
365
+ *
366
+ * This runs AFTER variant-scope resolution: the caller has already routed the
367
+ * work item to its target Soul(s)/Variant(s) and obtained the soul/variant
368
+ * Sα₂ (the `fallbackSa2` argument) and Cκ (the `fallbackCk` argument).
369
+ * Journey routing refines those values when the work item declares
370
+ * `targetedJourneys` of one of the affected Souls (RFC-0018 §5.4).
371
+ *
372
+ * **Sα₂ Vibe Coherence** — journey's `designImperatives` UNION variant's UNION
373
+ * soul's; conflict resolution: most-specific wins (journey > variant > soul).
374
+ * The pre-computed `JourneyScores.sa2` in the context encodes this resolution.
375
+ *
376
+ * **Cκ Capability Coverage** — boosted when `completion-rate < alertBelow`.
377
+ * The pre-computed `JourneyScores.ck` encodes the boost; callers supply live
378
+ * metric snapshots to the loader that builds `journeyScores`.
379
+ *
380
+ * **Eρ₅ Compliance Clearance** — elevated when journey WCAG > soul-default.
381
+ * The pre-computed `JourneyScores.er5Elevated` flag captures this; the caller
382
+ * applies Eρ₅ gating at the journey's elevated level when `er5Elevated = true`.
383
+ *
384
+ * **Cross-journey aggregation** (work touches multiple journeys) — same `min`
385
+ * as RFC-0018 §5.4 / RFC-0009 §7.2 / RFC-0017 OQ-4 by default. Per-Soul
386
+ * override via `journeyConfig.crossJourneyAggregation`.
387
+ *
388
+ * @param workItemId - The canonical work item ID.
389
+ * @param fallbackSa2 - Soul/variant Sα₂ to use when no journey routing applies.
390
+ * @param fallbackCk - Soul/variant Cκ to use when no journey routing applies.
391
+ * @param fallbackEr5Elevated - Soul/variant Eρ₅ elevation flag (usually false).
392
+ * @param journeyCtx - Journey-scope context; undefined → backward-compat passthrough.
393
+ */
394
+ export declare function computeJourneyScopedScores(workItemId: string, fallbackSa2: number, fallbackCk: number, fallbackEr5Elevated: boolean, journeyCtx: JourneyContext | undefined): JourneyScopedResult;
395
+ //# sourceMappingURL=journey-sa2-router.d.ts.map