@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,184 @@
1
+ /**
2
+ * RFC-0017 Phase 3 — Variant deprecation lifecycle (OQ-3 resolution).
3
+ *
4
+ * Implements the three catalog-routed lifecycle states:
5
+ *
6
+ * 1. **Deprecation declared** → emits `Decision: variant-deprecation-declared`
7
+ * (log to catalog; no operator interrupt — per RFC-0035 G0 non-blocking contract).
8
+ *
9
+ * 2. **Approaching removal** (default 7d before removalDate; per-org configurable)
10
+ * → emits `Decision: variant-deprecation-approaching`
11
+ * → operator batch review surface.
12
+ *
13
+ * 3. **At removal date with consumers still referencing**
14
+ * → emits `Decision: variant-removal-consumers-pending`
15
+ * → auto-action: keep variant in degraded mode (don't break consumers)
16
+ * + emit migration tasks to consumer owners
17
+ * + surface to operator.
18
+ *
19
+ * All transitions route through RFC-0035 G0 (non-blocking pipeline contract).
20
+ * Pipeline NEVER halts on any lifecycle transition (AC #3).
21
+ *
22
+ * 30-day default deprecation window; per-Soul `deprecationWindowDays` override
23
+ * via `variant-config.yaml` (OQ-3 resolution, RFC-0017 §10.1).
24
+ *
25
+ * @see spec/rfcs/RFC-0017-in-soul-variant-pattern.md §6.3 + OQ-3
26
+ * @see spec/rfcs/RFC-0035-decision-catalog-operator-routing.md G0
27
+ */
28
+ /** Default deprecation window in days (OQ-3 resolution: internal-config cadence). */
29
+ export declare const DEFAULT_DEPRECATION_WINDOW_DAYS = 30;
30
+ /**
31
+ * Default approaching-removal window in days. Alerts fire when the remaining
32
+ * time to `removalDate` drops below this threshold (per-org configurable).
33
+ */
34
+ export declare const DEFAULT_APPROACHING_WINDOW_DAYS = 7;
35
+ /**
36
+ * The three deprecation lifecycle states for a declared variant.
37
+ *
38
+ * - `'declared'` — Deprecation has been declared; pipeline continues unchanged.
39
+ * - `'approaching'` — Within the approaching-removal window (default 7d).
40
+ * - `'removal-pending'` — At (or past) removalDate with active consumers still referencing.
41
+ * Variant enters degraded mode; migration tasks emitted.
42
+ * - `'removed'` — No active consumers remain; variant safe to remove.
43
+ */
44
+ export type VariantDeprecationState = 'declared' | 'approaching' | 'removal-pending' | 'removed';
45
+ /**
46
+ * Decision summary keys emitted to the RFC-0035 Decision Catalog.
47
+ * These are the catalog-routed keys per OQ-3 resolution (2026-05-18).
48
+ */
49
+ export type VariantDeprecationDecisionKind = 'variant-deprecation-declared' | 'variant-deprecation-approaching' | 'variant-removal-consumers-pending';
50
+ /**
51
+ * Per-org / per-Soul lifecycle configuration (RFC-0017 §10.1 `variant.lifecycle`).
52
+ * Loaded from `.ai-sdlc/variant-config.yaml` with per-Soul overrides.
53
+ */
54
+ export interface VariantLifecycleConfig {
55
+ /** Default deprecation window in days. Defaults to {@link DEFAULT_DEPRECATION_WINDOW_DAYS}. */
56
+ deprecationWindowDays?: number;
57
+ /** Days before removalDate when approaching-removal Decision fires. Defaults to {@link DEFAULT_APPROACHING_WINDOW_DAYS}. */
58
+ approachingWindowDays?: number;
59
+ }
60
+ /**
61
+ * A single deprecated-variant declaration as loaded from a Soul DID or
62
+ * deprecation-manifest. Callers populate from the Soul DID's `spec.variants[]`
63
+ * entries whose `cardinality === 'experimental'` or that carry a deprecation
64
+ * annotation, OR from an explicit per-org deprecation manifest.
65
+ */
66
+ export interface DeprecatedVariantDeclaration {
67
+ /** Soul identifier (kebab-case). */
68
+ soulId: string;
69
+ /** Variant identifier (kebab-case). */
70
+ variantId: string;
71
+ /**
72
+ * ISO 8601 date the deprecation was declared. Used to compute the default
73
+ * `removalDate` when none is explicit.
74
+ */
75
+ deprecationDeclaredAt: string;
76
+ /**
77
+ * ISO 8601 date at or after which the variant may be removed. Optional —
78
+ * when absent the lifecycle engine computes:
79
+ * `removalDate = deprecationDeclaredAt + deprecationWindowDays`.
80
+ */
81
+ removalDate?: string;
82
+ /**
83
+ * Work-item IDs (e.g. `AISDLC-313`) or consumer references that still
84
+ * reference this variant. When non-empty and `removalDate` is past, the
85
+ * variant enters `'removal-pending'` state (degraded mode + migration tasks).
86
+ */
87
+ activeConsumers?: string[];
88
+ }
89
+ /**
90
+ * One lifecycle transition event emitted by the deprecation engine.
91
+ * These are logged to the RFC-0035 Decision Catalog via the caller-supplied
92
+ * `emitDecision` callback (catalog write is the caller's responsibility so
93
+ * the engine stays pure/testable).
94
+ */
95
+ export interface VariantDeprecationEvent {
96
+ kind: VariantDeprecationDecisionKind;
97
+ soulId: string;
98
+ variantId: string;
99
+ /** The lifecycle state this event transitions the variant into. */
100
+ state: VariantDeprecationState;
101
+ /** RFC-3339 UTC timestamp at transition detection time. */
102
+ timestamp: string;
103
+ /**
104
+ * RFC-0035 Decision Catalog routing metadata per G0.
105
+ * `blocking: false` is the invariant — pipeline NEVER halts on lifecycle transitions.
106
+ */
107
+ routing: {
108
+ blocking: false;
109
+ batchReview: boolean;
110
+ /** Emitted for `removal-pending` transitions. */
111
+ migrationTasksEmitted?: boolean;
112
+ degradedMode?: boolean;
113
+ };
114
+ /** Human-readable summary; safe for operator surfaces (TUI, Slack). */
115
+ message: string;
116
+ /** Active consumers still referencing the variant (for removal-pending). */
117
+ activeConsumers?: string[];
118
+ }
119
+ /**
120
+ * One migration task emitted for each consumer still referencing a variant
121
+ * past its removal date. Callers surface these to the consumer owners
122
+ * (routing via the RFC-0035 actor model).
123
+ */
124
+ export interface VariantMigrationTask {
125
+ soulId: string;
126
+ variantId: string;
127
+ /** Consumer work-item ID that references the deprecated variant. */
128
+ consumerId: string;
129
+ /** Human-readable migration guidance. */
130
+ message: string;
131
+ timestamp: string;
132
+ }
133
+ /**
134
+ * Full result of one deprecation lifecycle evaluation run.
135
+ */
136
+ export interface VariantDeprecationResult {
137
+ /** Lifecycle events emitted (one per transitioned variant). */
138
+ events: VariantDeprecationEvent[];
139
+ /**
140
+ * Migration tasks emitted for consumers blocked on `removal-pending` variants.
141
+ * Non-empty only when at least one variant is in `removal-pending` state.
142
+ */
143
+ migrationTasks: VariantMigrationTask[];
144
+ /**
145
+ * Variants that are now in degraded mode (at or past removal date with
146
+ * active consumers). The pipeline continues operating with these variants
147
+ * in read-only / degraded-service mode — per G0, no halt.
148
+ */
149
+ degradedVariants: Array<{
150
+ soulId: string;
151
+ variantId: string;
152
+ }>;
153
+ }
154
+ /**
155
+ * Resolve the current lifecycle state for a deprecated variant given the
156
+ * current wall-clock time.
157
+ *
158
+ * State resolution logic:
159
+ * - If now ≥ removalDate AND activeConsumers.length > 0 → `'removal-pending'`
160
+ * - If now ≥ removalDate AND activeConsumers.length === 0 → `'removed'`
161
+ * - If now ≥ (removalDate − approachingWindowDays) → `'approaching'`
162
+ * - Otherwise → `'declared'`
163
+ */
164
+ export declare function resolveDeprecationState(declaration: DeprecatedVariantDeclaration, config: VariantLifecycleConfig, now: Date): VariantDeprecationState;
165
+ /**
166
+ * Evaluate deprecation lifecycle for a set of deprecated variant declarations.
167
+ *
168
+ * Per RFC-0035 G0: this function is ALWAYS non-blocking. It emits Decision
169
+ * Catalog entries via the optional `emitDecision` callback; callers wire this
170
+ * to `appendDecisionEvent()` from `pipeline-cli/src/decisions/event-log.ts`.
171
+ *
172
+ * **Pipeline never halts on lifecycle transitions** (AC #3). Even variants in
173
+ * `removal-pending` state continue operating in degraded mode — the framework
174
+ * emits migration tasks and surfaces to the operator, but does NOT block
175
+ * admission, tick, or dispatch.
176
+ *
177
+ * @param declarations - Deprecated variant declarations to evaluate.
178
+ * @param config - Per-Soul / per-org lifecycle configuration.
179
+ * @param now - The current wall-clock instant (injectable for tests).
180
+ * @param emitDecision - Optional callback called once per emitted Decision event.
181
+ * Errors from this callback propagate to the caller.
182
+ */
183
+ export declare function evaluateDeprecationLifecycle(declarations: DeprecatedVariantDeclaration[], config?: VariantLifecycleConfig, now?: Date, emitDecision?: (event: VariantDeprecationEvent) => void): VariantDeprecationResult;
184
+ //# sourceMappingURL=deprecation-lifecycle.d.ts.map
@@ -0,0 +1,208 @@
1
+ /**
2
+ * RFC-0017 Phase 3 — Variant deprecation lifecycle (OQ-3 resolution).
3
+ *
4
+ * Implements the three catalog-routed lifecycle states:
5
+ *
6
+ * 1. **Deprecation declared** → emits `Decision: variant-deprecation-declared`
7
+ * (log to catalog; no operator interrupt — per RFC-0035 G0 non-blocking contract).
8
+ *
9
+ * 2. **Approaching removal** (default 7d before removalDate; per-org configurable)
10
+ * → emits `Decision: variant-deprecation-approaching`
11
+ * → operator batch review surface.
12
+ *
13
+ * 3. **At removal date with consumers still referencing**
14
+ * → emits `Decision: variant-removal-consumers-pending`
15
+ * → auto-action: keep variant in degraded mode (don't break consumers)
16
+ * + emit migration tasks to consumer owners
17
+ * + surface to operator.
18
+ *
19
+ * All transitions route through RFC-0035 G0 (non-blocking pipeline contract).
20
+ * Pipeline NEVER halts on any lifecycle transition (AC #3).
21
+ *
22
+ * 30-day default deprecation window; per-Soul `deprecationWindowDays` override
23
+ * via `variant-config.yaml` (OQ-3 resolution, RFC-0017 §10.1).
24
+ *
25
+ * @see spec/rfcs/RFC-0017-in-soul-variant-pattern.md §6.3 + OQ-3
26
+ * @see spec/rfcs/RFC-0035-decision-catalog-operator-routing.md G0
27
+ */
28
+ // ── Constants ─────────────────────────────────────────────────────────────────
29
+ /** Default deprecation window in days (OQ-3 resolution: internal-config cadence). */
30
+ export const DEFAULT_DEPRECATION_WINDOW_DAYS = 30;
31
+ /**
32
+ * Default approaching-removal window in days. Alerts fire when the remaining
33
+ * time to `removalDate` drops below this threshold (per-org configurable).
34
+ */
35
+ export const DEFAULT_APPROACHING_WINDOW_DAYS = 7;
36
+ // ── Date arithmetic helpers ───────────────────────────────────────────────────
37
+ /**
38
+ * Parse an ISO 8601 date string (YYYY-MM-DD or full ISO 8601) to a Date.
39
+ * Throws if unparseable.
40
+ */
41
+ function parseDate(iso) {
42
+ const d = new Date(iso);
43
+ if (isNaN(d.getTime()))
44
+ throw new Error(`[variant-deprecation] invalid date: '${iso}'`);
45
+ return d;
46
+ }
47
+ /**
48
+ * Add `days` to a Date (calendar days; no DST adjustment).
49
+ */
50
+ function addDays(date, days) {
51
+ const result = new Date(date.getTime());
52
+ result.setUTCDate(result.getUTCDate() + days);
53
+ return result;
54
+ }
55
+ /**
56
+ * Compute the effective `removalDate` for a declaration.
57
+ * When `declaration.removalDate` is explicit, use it; otherwise compute from
58
+ * `deprecationDeclaredAt + deprecationWindowDays`.
59
+ */
60
+ function effectiveRemovalDate(declaration, config) {
61
+ if (declaration.removalDate)
62
+ return parseDate(declaration.removalDate);
63
+ const declaredAt = parseDate(declaration.deprecationDeclaredAt);
64
+ const windowDays = config.deprecationWindowDays ?? DEFAULT_DEPRECATION_WINDOW_DAYS;
65
+ return addDays(declaredAt, windowDays);
66
+ }
67
+ // ── Lifecycle state resolver ──────────────────────────────────────────────────
68
+ /**
69
+ * Resolve the current lifecycle state for a deprecated variant given the
70
+ * current wall-clock time.
71
+ *
72
+ * State resolution logic:
73
+ * - If now ≥ removalDate AND activeConsumers.length > 0 → `'removal-pending'`
74
+ * - If now ≥ removalDate AND activeConsumers.length === 0 → `'removed'`
75
+ * - If now ≥ (removalDate − approachingWindowDays) → `'approaching'`
76
+ * - Otherwise → `'declared'`
77
+ */
78
+ export function resolveDeprecationState(declaration, config, now) {
79
+ const removalDate = effectiveRemovalDate(declaration, config);
80
+ const approachingWindowDays = config.approachingWindowDays ?? DEFAULT_APPROACHING_WINDOW_DAYS;
81
+ const approachingThreshold = addDays(removalDate, -approachingWindowDays);
82
+ const consumers = declaration.activeConsumers ?? [];
83
+ if (now >= removalDate) {
84
+ return consumers.length > 0 ? 'removal-pending' : 'removed';
85
+ }
86
+ if (now >= approachingThreshold) {
87
+ return 'approaching';
88
+ }
89
+ return 'declared';
90
+ }
91
+ // ── Event factories ───────────────────────────────────────────────────────────
92
+ function makeDeclaredEvent(declaration, now) {
93
+ return {
94
+ kind: 'variant-deprecation-declared',
95
+ soulId: declaration.soulId,
96
+ variantId: declaration.variantId,
97
+ state: 'declared',
98
+ timestamp: now,
99
+ routing: { blocking: false, batchReview: false },
100
+ message: `Variant '${declaration.variantId}' on soul '${declaration.soulId}' has been marked ` +
101
+ `deprecated. Decision: variant-deprecation-declared (catalog log; no operator interrupt ` +
102
+ `per RFC-0035 G0).`,
103
+ };
104
+ }
105
+ function makeApproachingEvent(declaration, removalDateStr, now) {
106
+ return {
107
+ kind: 'variant-deprecation-approaching',
108
+ soulId: declaration.soulId,
109
+ variantId: declaration.variantId,
110
+ state: 'approaching',
111
+ timestamp: now,
112
+ routing: { blocking: false, batchReview: true },
113
+ message: `Variant '${declaration.variantId}' on soul '${declaration.soulId}' is approaching ` +
114
+ `removal (scheduled: ${removalDateStr}). Decision: variant-deprecation-approaching ` +
115
+ `→ operator batch review surface (RFC-0035 G0 — non-blocking).`,
116
+ activeConsumers: declaration.activeConsumers,
117
+ };
118
+ }
119
+ function makeRemovalPendingEvent(declaration, now) {
120
+ const consumers = declaration.activeConsumers ?? [];
121
+ return {
122
+ kind: 'variant-removal-consumers-pending',
123
+ soulId: declaration.soulId,
124
+ variantId: declaration.variantId,
125
+ state: 'removal-pending',
126
+ timestamp: now,
127
+ routing: {
128
+ blocking: false,
129
+ batchReview: true,
130
+ migrationTasksEmitted: true,
131
+ degradedMode: true,
132
+ },
133
+ message: `Variant '${declaration.variantId}' on soul '${declaration.soulId}' is at/past removal ` +
134
+ `date with ${consumers.length} active consumer(s). Auto-action: degraded mode enabled ` +
135
+ `(consumers continue working); migration tasks emitted per consumer. ` +
136
+ `Decision: variant-removal-consumers-pending (RFC-0035 G0 — pipeline continues).`,
137
+ activeConsumers: consumers,
138
+ };
139
+ }
140
+ function makeMigrationTask(soulId, variantId, consumerId, now) {
141
+ return {
142
+ soulId,
143
+ variantId,
144
+ consumerId,
145
+ message: `Consumer '${consumerId}' references deprecated variant '${variantId}' on soul ` +
146
+ `'${soulId}' which is past its removal date. Migrate to a supported variant or ` +
147
+ `soul-scope target before the degraded-mode window closes.`,
148
+ timestamp: now,
149
+ };
150
+ }
151
+ // ── Main evaluation function ──────────────────────────────────────────────────
152
+ /**
153
+ * Evaluate deprecation lifecycle for a set of deprecated variant declarations.
154
+ *
155
+ * Per RFC-0035 G0: this function is ALWAYS non-blocking. It emits Decision
156
+ * Catalog entries via the optional `emitDecision` callback; callers wire this
157
+ * to `appendDecisionEvent()` from `pipeline-cli/src/decisions/event-log.ts`.
158
+ *
159
+ * **Pipeline never halts on lifecycle transitions** (AC #3). Even variants in
160
+ * `removal-pending` state continue operating in degraded mode — the framework
161
+ * emits migration tasks and surfaces to the operator, but does NOT block
162
+ * admission, tick, or dispatch.
163
+ *
164
+ * @param declarations - Deprecated variant declarations to evaluate.
165
+ * @param config - Per-Soul / per-org lifecycle configuration.
166
+ * @param now - The current wall-clock instant (injectable for tests).
167
+ * @param emitDecision - Optional callback called once per emitted Decision event.
168
+ * Errors from this callback propagate to the caller.
169
+ */
170
+ export function evaluateDeprecationLifecycle(declarations, config = {}, now = new Date(), emitDecision) {
171
+ const nowStr = now.toISOString();
172
+ const events = [];
173
+ const migrationTasks = [];
174
+ const degradedVariants = [];
175
+ for (const declaration of declarations) {
176
+ const state = resolveDeprecationState(declaration, config, now);
177
+ const removalDate = effectiveRemovalDate(declaration, config);
178
+ const removalDateStr = removalDate.toISOString().split('T')[0];
179
+ let event;
180
+ switch (state) {
181
+ case 'declared':
182
+ event = makeDeclaredEvent(declaration, nowStr);
183
+ break;
184
+ case 'approaching':
185
+ event = makeApproachingEvent(declaration, removalDateStr, nowStr);
186
+ break;
187
+ case 'removal-pending': {
188
+ event = makeRemovalPendingEvent(declaration, nowStr);
189
+ degradedVariants.push({ soulId: declaration.soulId, variantId: declaration.variantId });
190
+ // Emit one migration task per consumer
191
+ for (const consumerId of declaration.activeConsumers ?? []) {
192
+ migrationTasks.push(makeMigrationTask(declaration.soulId, declaration.variantId, consumerId, nowStr));
193
+ }
194
+ break;
195
+ }
196
+ case 'removed':
197
+ // 'removed' state: no active consumers + past removal date — no event emitted.
198
+ // The variant can be safely pruned; this is a clean terminal state.
199
+ continue;
200
+ }
201
+ events.push(event);
202
+ if (emitDecision) {
203
+ emitDecision(event);
204
+ }
205
+ }
206
+ return { events, migrationTasks, degradedVariants };
207
+ }
208
+ //# sourceMappingURL=deprecation-lifecycle.js.map
@@ -0,0 +1,136 @@
1
+ /**
2
+ * RFC-0017 Phase 3 — Eτ_tessellation_drift extension for variant-scoped scans.
3
+ *
4
+ * Composes with RFC-0009 Phase 4.2 / AISDLC-317 (`orchestrator/src/tessellation-drift.ts`)
5
+ * to extend drift detection with variant-scoped design intent scans per RFC-0017 §6.2:
6
+ *
7
+ * "when a variant is added/removed/modified, the Eτ_tessellation_drift detector
8
+ * MUST scan substrate code for variant-specific identifiers (parallel to per-soul
9
+ * scan). Substrate code referring to specific variant IDs is a drift signal."
10
+ *
11
+ * Emits `Decision: variant-design-intent-drift` events catalog-routed per
12
+ * RFC-0035 Stage A/B/C (non-blocking per G0 contract).
13
+ *
14
+ * **Composition model:**
15
+ * This extension runs AFTER the base `detectTessellationDrift` (soul-scope detector).
16
+ * It adds a variant-scoped Rule #1a: scan substrate files for variant-slug leakage,
17
+ * parallel to how the base detector scans for soul-slug leakage. The rationale is
18
+ * identical: variant IDs in shared substrate code are a drift signal — they indicate
19
+ * variant-specific logic has leaked into non-variant-scoped files, which complicates
20
+ * future variant removal and creates implicit coupling.
21
+ *
22
+ * @see spec/rfcs/RFC-0017-in-soul-variant-pattern.md §6.2 Behavioral changes
23
+ * @see orchestrator/src/tessellation-drift.ts — base RFC-0009 Phase 4.2 detector
24
+ * @see spec/rfcs/RFC-0035-decision-catalog-operator-routing.md G0
25
+ */
26
+ import type { SubstrateFile } from '../tessellation-drift.js';
27
+ import type { VariantOverlay } from '../variant-admission.js';
28
+ /**
29
+ * Single finding from the variant-scoped substrate scan.
30
+ * Parallel to `AstScanFinding` in tessellation-drift.ts.
31
+ */
32
+ export interface VariantDriftFinding {
33
+ /** Path of the substrate file that contained the variant-slug reference. */
34
+ filePath: string;
35
+ /** Soul slug the leaking variant belongs to. */
36
+ soulSlug: string;
37
+ /** Variant slug that appeared in shared substrate. */
38
+ variantSlug: string;
39
+ /** 1-based line number in `filePath`. */
40
+ line: number;
41
+ /**
42
+ * Discriminator for which pattern triggered:
43
+ * - `'string-literal'` — bare `'<variant-slug>'` in substrate
44
+ * - `'variant-conditional'` — conditional branching on variant slug
45
+ */
46
+ pattern: 'string-literal' | 'variant-conditional';
47
+ /** The raw matching substring (trimmed, max 200 chars). */
48
+ excerpt: string;
49
+ }
50
+ /**
51
+ * Decision Catalog event emitted when variant-scoped drift is detected.
52
+ * Catalog-routed per RFC-0035 Stage A/B/C (G0 non-blocking).
53
+ */
54
+ export interface VariantDesignIntentDriftEvent {
55
+ type: 'VariantDesignIntentDriftDetected';
56
+ /** RFC-3339 UTC timestamp at detection time. */
57
+ timestamp: string;
58
+ /** Tessellated DID URI this scan ran against. */
59
+ tessellatedDid: string;
60
+ /** Soul IDs whose variants were implicated. */
61
+ involvedSouls: string[];
62
+ /** Variant IDs that appeared in shared substrate (per soul). */
63
+ involvedVariants: Record<string, string[]>;
64
+ severity: 'warning';
65
+ /** Human-readable one-line summary; safe for operator surfaces. */
66
+ message: string;
67
+ /** Catalog decision kind per OQ-7 routing. */
68
+ decisionKind: 'variant-design-intent-drift';
69
+ /**
70
+ * RFC-0035 routing metadata — always non-blocking per G0.
71
+ */
72
+ routing: {
73
+ blocking: false;
74
+ catalogStage: 'A' | 'B' | 'C';
75
+ };
76
+ details: {
77
+ findings: VariantDriftFinding[];
78
+ };
79
+ }
80
+ /**
81
+ * Configuration for the variant-scoped drift extension.
82
+ * Composes with `TessellationDriftConfig` in tessellation-drift.ts.
83
+ */
84
+ export interface VariantDriftExtensionConfig {
85
+ /**
86
+ * Master opt-in switch. Follows RFC-0009 §10 Phase 4 "adopter opt-in" convention.
87
+ * Default `false` — the detector short-circuits and emits nothing when disabled.
88
+ */
89
+ enabled?: boolean;
90
+ /**
91
+ * RFC-0035 Stage assignment for emitted `variant-design-intent-drift` Decisions.
92
+ * Default `'A'` (deterministic check — regex scan against substrate files).
93
+ */
94
+ catalogStage?: 'A' | 'B' | 'C';
95
+ }
96
+ export interface VariantDriftExtensionInput {
97
+ /** The Tessellated DID URI (for event provenance). */
98
+ tessellatedDid: string;
99
+ /**
100
+ * Variant overlays keyed by soulId. Source of truth for which variant slugs
101
+ * to scan for in substrate files. Parallel to `tessellation.souls` in the
102
+ * base detector.
103
+ */
104
+ variantsBySoul: Record<string, VariantOverlay[]>;
105
+ /**
106
+ * Substrate files to scan. Same file set as passed to `detectTessellationDrift`
107
+ * (shared substrate, not soul-scoped or variant-scoped files).
108
+ */
109
+ substrateFiles?: SubstrateFile[];
110
+ }
111
+ export interface VariantDriftExtensionResult {
112
+ /** Events emitted (zero or one — the detector aggregates all findings into one event). */
113
+ events: VariantDesignIntentDriftEvent[];
114
+ /** True when the detector short-circuited because `enabled === false`. */
115
+ optedOut: boolean;
116
+ }
117
+ /**
118
+ * Detect variant-scoped design intent drift in shared substrate files.
119
+ *
120
+ * Composes with `detectTessellationDrift` (RFC-0009 Phase 4.2) by adding a
121
+ * variant-scope parallel to its Rule #1 (soul-slug scan). Substrate code that
122
+ * mentions specific variant slugs is a drift signal — variant-specific logic
123
+ * should be isolated behind variant-aware routing, not hardcoded in shared code.
124
+ *
125
+ * Emits `Decision: variant-design-intent-drift` (catalog-routed, G0 non-blocking).
126
+ *
127
+ * When `config.enabled !== true` the detector short-circuits immediately and
128
+ * returns `{ events: [], optedOut: true }` — honoring the RFC-0009 §10
129
+ * "adopter opt-in initially" convention.
130
+ *
131
+ * @param input Detection inputs.
132
+ * @param config Detector configuration.
133
+ * @param emit Optional callback called once per emitted event. Errors propagate.
134
+ */
135
+ export declare function detectVariantDrift(input: VariantDriftExtensionInput, config?: VariantDriftExtensionConfig, emit?: (event: VariantDesignIntentDriftEvent) => Promise<void> | void): Promise<VariantDriftExtensionResult>;
136
+ //# sourceMappingURL=drift-extension.d.ts.map