@ai-sdlc/orchestrator 0.9.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.
- package/dist/__test-helpers/git-env.d.ts +40 -0
- package/dist/__test-helpers/git-env.js +73 -0
- package/dist/adapters.d.ts +42 -3
- package/dist/adapters.js +133 -3
- package/dist/admission-composite.d.ts +134 -1
- package/dist/admission-composite.js +170 -6
- package/dist/admission-enrichment.d.ts +12 -3
- package/dist/admission-enrichment.js +71 -10
- package/dist/admission-hc.d.ts +20 -1
- package/dist/admission-hc.js +12 -1
- package/dist/admission-score.d.ts +44 -0
- package/dist/admission-score.js +11 -2
- package/dist/backlog-adapter.d.ts +45 -0
- package/dist/backlog-adapter.js +145 -1
- package/dist/calibration.d.ts +81 -0
- package/dist/calibration.js +76 -0
- package/dist/cli/commands/git-remote.d.ts +25 -0
- package/dist/cli/commands/git-remote.js +80 -1
- package/dist/cli/commands/init-features.d.ts +507 -0
- package/dist/cli/commands/init-features.js +1100 -0
- package/dist/cli/commands/init-templates.d.ts +301 -0
- package/dist/cli/commands/init-templates.js +1341 -0
- package/dist/cli/commands/init.d.ts +67 -0
- package/dist/cli/commands/init.js +301 -2
- package/dist/cli/commands/run.js +9 -1
- package/dist/cli/index.d.ts +11 -0
- package/dist/cli/index.js +42 -8
- package/dist/compliance/composer.d.ts +79 -0
- package/dist/compliance/composer.js +258 -0
- package/dist/compliance/errors.d.ts +64 -0
- package/dist/compliance/errors.js +85 -0
- package/dist/compliance/loader.d.ts +52 -0
- package/dist/compliance/loader.js +124 -0
- package/dist/compliance/types.d.ts +184 -0
- package/dist/compliance/types.js +41 -0
- package/dist/compliance-clearance.d.ts +269 -0
- package/dist/compliance-clearance.js +269 -0
- package/dist/config.js +17 -0
- package/dist/cost-tracker.d.ts +22 -0
- package/dist/cost-tracker.js +41 -0
- package/dist/database/adapters/external.js +5 -1
- package/dist/design-authority.d.ts +13 -0
- package/dist/design-authority.js +13 -0
- package/dist/embedding/adapters/openai-text-embedding-3-small.d.ts +71 -0
- package/dist/embedding/adapters/openai-text-embedding-3-small.js +190 -0
- package/dist/embedding/consumers/tessellation-drift.d.ts +74 -0
- package/dist/embedding/consumers/tessellation-drift.js +76 -0
- package/dist/embedding/cross-provider.d.ts +78 -0
- package/dist/embedding/cross-provider.js +75 -0
- package/dist/embedding/deprecation.d.ts +151 -0
- package/dist/embedding/deprecation.js +229 -0
- package/dist/embedding/errors.d.ts +90 -0
- package/dist/embedding/errors.js +150 -0
- package/dist/embedding/index.d.ts +29 -0
- package/dist/embedding/index.js +24 -0
- package/dist/embedding/pipeline-load.d.ts +146 -0
- package/dist/embedding/pipeline-load.js +178 -0
- package/dist/embedding/registry.d.ts +45 -0
- package/dist/embedding/registry.js +61 -0
- package/dist/embedding/stale-vector.d.ts +110 -0
- package/dist/embedding/stale-vector.js +92 -0
- package/dist/embedding/storage/index.d.ts +51 -0
- package/dist/embedding/storage/index.js +43 -0
- package/dist/embedding/storage/jsonl-backend.d.ts +150 -0
- package/dist/embedding/storage/jsonl-backend.js +332 -0
- package/dist/embedding/storage/types.d.ts +135 -0
- package/dist/embedding/storage/types.js +13 -0
- package/dist/embedding/types.d.ts +180 -0
- package/dist/embedding/types.js +10 -0
- package/dist/execute.d.ts +29 -2
- package/dist/execute.js +179 -35
- package/dist/index.d.ts +14 -2
- package/dist/index.js +19 -2
- package/dist/journey/inheritance-validator.d.ts +396 -0
- package/dist/journey/inheritance-validator.js +370 -0
- package/dist/journey/state-id-drift-rule.d.ts +137 -0
- package/dist/journey/state-id-drift-rule.js +245 -0
- package/dist/journey-sa2-router.d.ts +395 -0
- package/dist/journey-sa2-router.js +308 -0
- package/dist/models/classifier.d.ts +3 -1
- package/dist/models/classifier.js +61 -5
- package/dist/pillar-breakdown.d.ts +23 -1
- package/dist/pillar-breakdown.js +9 -0
- package/dist/runners/review-agent.js +6 -2
- package/dist/runners/runner-registry.d.ts +36 -0
- package/dist/runners/runner-registry.js +90 -0
- package/dist/runtime/attestations.d.ts +663 -11
- package/dist/runtime/attestations.js +971 -24
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/parallelism-flag.d.ts +21 -3
- package/dist/runtime/parallelism-flag.js +27 -6
- package/dist/runtime/port-allocator.d.ts +11 -0
- package/dist/runtime/port-allocator.js +30 -0
- package/dist/sa-scoring/layer3-llm.js +6 -1
- package/dist/sa-scoring/revision-proposal-config.d.ts +178 -0
- package/dist/sa-scoring/revision-proposal-config.js +198 -0
- package/dist/sa-scoring/revision-proposal.d.ts +285 -0
- package/dist/sa-scoring/revision-proposal.js +417 -0
- package/dist/signal-ingestion/adapters/community-thread.d.ts +43 -0
- package/dist/signal-ingestion/adapters/community-thread.js +55 -0
- package/dist/signal-ingestion/adapters/in-app-feedback.d.ts +67 -0
- package/dist/signal-ingestion/adapters/in-app-feedback.js +51 -0
- package/dist/signal-ingestion/adapters/manual.d.ts +78 -0
- package/dist/signal-ingestion/adapters/manual.js +112 -0
- package/dist/signal-ingestion/adapters/support-ticket.d.ts +47 -0
- package/dist/signal-ingestion/adapters/support-ticket.js +51 -0
- package/dist/signal-ingestion/classifier.d.ts +205 -0
- package/dist/signal-ingestion/classifier.js +494 -0
- package/dist/signal-ingestion/clustering-types.d.ts +36 -0
- package/dist/signal-ingestion/clustering-types.js +14 -0
- package/dist/signal-ingestion/clustering.d.ts +200 -0
- package/dist/signal-ingestion/clustering.js +413 -0
- package/dist/signal-ingestion/config.d.ts +351 -0
- package/dist/signal-ingestion/config.js +587 -0
- package/dist/signal-ingestion/d1.d.ts +252 -0
- package/dist/signal-ingestion/d1.js +235 -0
- package/dist/signal-ingestion/errors.d.ts +73 -0
- package/dist/signal-ingestion/errors.js +108 -0
- package/dist/signal-ingestion/governance-events.d.ts +181 -0
- package/dist/signal-ingestion/governance-events.js +189 -0
- package/dist/signal-ingestion/index.d.ts +35 -0
- package/dist/signal-ingestion/index.js +53 -0
- package/dist/signal-ingestion/manual-share-metric.d.ts +93 -0
- package/dist/signal-ingestion/manual-share-metric.js +106 -0
- package/dist/signal-ingestion/registry.d.ts +40 -0
- package/dist/signal-ingestion/registry.js +137 -0
- package/dist/signal-ingestion/residency.d.ts +227 -0
- package/dist/signal-ingestion/residency.js +238 -0
- package/dist/signal-ingestion/significance.d.ts +554 -0
- package/dist/signal-ingestion/significance.js +555 -0
- package/dist/signal-ingestion/types.d.ts +191 -0
- package/dist/signal-ingestion/types.js +8 -0
- package/dist/substrate/drift-composition.d.ts +270 -0
- package/dist/substrate/drift-composition.js +306 -0
- package/dist/substrate/drift-tui-surface.d.ts +61 -0
- package/dist/substrate/drift-tui-surface.js +102 -0
- package/dist/substrate/identity-class.d.ts +176 -0
- package/dist/substrate/identity-class.js +201 -0
- package/dist/tessellation/cross-soul-provenance-rule.d.ts +133 -0
- package/dist/tessellation/cross-soul-provenance-rule.js +171 -0
- package/dist/tessellation/inter-soul-embedding-distance-rule.d.ts +61 -0
- package/dist/tessellation/inter-soul-embedding-distance-rule.js +67 -0
- package/dist/tessellation/rule-registry.d.ts +269 -0
- package/dist/tessellation/rule-registry.js +92 -0
- package/dist/tessellation/soul-slug-ast-scan-rule.d.ts +90 -0
- package/dist/tessellation/soul-slug-ast-scan-rule.js +158 -0
- package/dist/tessellation-admission.d.ts +162 -0
- package/dist/tessellation-admission.js +146 -0
- package/dist/tessellation-drift.d.ts +246 -0
- package/dist/tessellation-drift.js +250 -0
- package/dist/validate-config.js +13 -0
- package/dist/validate-issue.js +2 -2
- package/dist/variant/cardinality-activation.d.ts +126 -0
- package/dist/variant/cardinality-activation.js +101 -0
- package/dist/variant/deprecation-lifecycle.d.ts +184 -0
- package/dist/variant/deprecation-lifecycle.js +208 -0
- package/dist/variant/drift-extension.d.ts +136 -0
- package/dist/variant/drift-extension.js +164 -0
- package/dist/variant/engineering-review.d.ts +185 -0
- package/dist/variant/engineering-review.js +142 -0
- package/dist/variant/index.d.ts +32 -0
- package/dist/variant/index.js +32 -0
- package/dist/variant/inheritance-validator.d.ts +165 -0
- package/dist/variant/inheritance-validator.js +139 -0
- package/dist/variant/internal-adopter/index.d.ts +11 -0
- package/dist/variant/internal-adopter/index.js +10 -0
- package/dist/variant/internal-adopter/products.d.ts +156 -0
- package/dist/variant/internal-adopter/products.js +366 -0
- package/dist/variant-admission.d.ts +316 -0
- package/dist/variant-admission.js +247 -0
- package/package.json +11 -8
|
@@ -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
|