@ai-sdlc/orchestrator 0.10.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/dist/adapters.d.ts +42 -3
  2. package/dist/adapters.js +133 -3
  3. package/dist/admission-composite.d.ts +112 -1
  4. package/dist/admission-composite.js +85 -4
  5. package/dist/admission-enrichment.d.ts +12 -3
  6. package/dist/admission-enrichment.js +64 -13
  7. package/dist/admission-score.d.ts +30 -0
  8. package/dist/admission-score.js +4 -1
  9. package/dist/backlog-adapter.d.ts +45 -0
  10. package/dist/backlog-adapter.js +145 -1
  11. package/dist/calibration.d.ts +81 -0
  12. package/dist/calibration.js +76 -0
  13. package/dist/cli/commands/init-features.d.ts +301 -2
  14. package/dist/cli/commands/init-features.js +634 -7
  15. package/dist/cli/commands/init-templates.d.ts +198 -1
  16. package/dist/cli/commands/init-templates.js +943 -1
  17. package/dist/cli/commands/init.d.ts +45 -0
  18. package/dist/cli/commands/init.js +147 -5
  19. package/dist/cli/commands/run.js +9 -1
  20. package/dist/cli/index.d.ts +11 -0
  21. package/dist/cli/index.js +42 -8
  22. package/dist/compliance/composer.d.ts +79 -0
  23. package/dist/compliance/composer.js +258 -0
  24. package/dist/compliance/errors.d.ts +64 -0
  25. package/dist/compliance/errors.js +85 -0
  26. package/dist/compliance/loader.d.ts +52 -0
  27. package/dist/compliance/loader.js +124 -0
  28. package/dist/compliance/types.d.ts +184 -0
  29. package/dist/compliance/types.js +41 -0
  30. package/dist/compliance-clearance.d.ts +269 -0
  31. package/dist/compliance-clearance.js +269 -0
  32. package/dist/config.js +17 -0
  33. package/dist/cost-tracker.d.ts +22 -0
  34. package/dist/cost-tracker.js +41 -0
  35. package/dist/database/adapters/external.js +5 -1
  36. package/dist/embedding/adapters/openai-text-embedding-3-small.d.ts +71 -0
  37. package/dist/embedding/adapters/openai-text-embedding-3-small.js +190 -0
  38. package/dist/embedding/consumers/tessellation-drift.d.ts +74 -0
  39. package/dist/embedding/consumers/tessellation-drift.js +76 -0
  40. package/dist/embedding/cross-provider.d.ts +78 -0
  41. package/dist/embedding/cross-provider.js +75 -0
  42. package/dist/embedding/deprecation.d.ts +151 -0
  43. package/dist/embedding/deprecation.js +229 -0
  44. package/dist/embedding/errors.d.ts +90 -0
  45. package/dist/embedding/errors.js +150 -0
  46. package/dist/embedding/index.d.ts +29 -0
  47. package/dist/embedding/index.js +24 -0
  48. package/dist/embedding/pipeline-load.d.ts +146 -0
  49. package/dist/embedding/pipeline-load.js +178 -0
  50. package/dist/embedding/registry.d.ts +45 -0
  51. package/dist/embedding/registry.js +61 -0
  52. package/dist/embedding/stale-vector.d.ts +110 -0
  53. package/dist/embedding/stale-vector.js +92 -0
  54. package/dist/embedding/storage/index.d.ts +51 -0
  55. package/dist/embedding/storage/index.js +43 -0
  56. package/dist/embedding/storage/jsonl-backend.d.ts +150 -0
  57. package/dist/embedding/storage/jsonl-backend.js +332 -0
  58. package/dist/embedding/storage/types.d.ts +135 -0
  59. package/dist/embedding/storage/types.js +13 -0
  60. package/dist/embedding/types.d.ts +180 -0
  61. package/dist/embedding/types.js +10 -0
  62. package/dist/execute.d.ts +29 -2
  63. package/dist/execute.js +171 -30
  64. package/dist/index.d.ts +14 -2
  65. package/dist/index.js +19 -2
  66. package/dist/journey/inheritance-validator.d.ts +396 -0
  67. package/dist/journey/inheritance-validator.js +370 -0
  68. package/dist/journey/state-id-drift-rule.d.ts +137 -0
  69. package/dist/journey/state-id-drift-rule.js +245 -0
  70. package/dist/journey-sa2-router.d.ts +395 -0
  71. package/dist/journey-sa2-router.js +308 -0
  72. package/dist/runners/review-agent.js +6 -2
  73. package/dist/runners/runner-registry.d.ts +36 -0
  74. package/dist/runners/runner-registry.js +90 -0
  75. package/dist/runtime/attestations.d.ts +173 -13
  76. package/dist/runtime/attestations.js +252 -40
  77. package/dist/runtime/index.d.ts +1 -1
  78. package/dist/runtime/index.js +1 -1
  79. package/dist/sa-scoring/layer3-llm.js +6 -1
  80. package/dist/sa-scoring/revision-proposal-config.d.ts +178 -0
  81. package/dist/sa-scoring/revision-proposal-config.js +198 -0
  82. package/dist/sa-scoring/revision-proposal.d.ts +285 -0
  83. package/dist/sa-scoring/revision-proposal.js +417 -0
  84. package/dist/signal-ingestion/adapters/community-thread.d.ts +43 -0
  85. package/dist/signal-ingestion/adapters/community-thread.js +55 -0
  86. package/dist/signal-ingestion/adapters/in-app-feedback.d.ts +67 -0
  87. package/dist/signal-ingestion/adapters/in-app-feedback.js +51 -0
  88. package/dist/signal-ingestion/adapters/manual.d.ts +78 -0
  89. package/dist/signal-ingestion/adapters/manual.js +112 -0
  90. package/dist/signal-ingestion/adapters/support-ticket.d.ts +47 -0
  91. package/dist/signal-ingestion/adapters/support-ticket.js +51 -0
  92. package/dist/signal-ingestion/classifier.d.ts +205 -0
  93. package/dist/signal-ingestion/classifier.js +494 -0
  94. package/dist/signal-ingestion/clustering-types.d.ts +36 -0
  95. package/dist/signal-ingestion/clustering-types.js +14 -0
  96. package/dist/signal-ingestion/clustering.d.ts +200 -0
  97. package/dist/signal-ingestion/clustering.js +413 -0
  98. package/dist/signal-ingestion/config.d.ts +351 -0
  99. package/dist/signal-ingestion/config.js +587 -0
  100. package/dist/signal-ingestion/d1.d.ts +252 -0
  101. package/dist/signal-ingestion/d1.js +235 -0
  102. package/dist/signal-ingestion/errors.d.ts +73 -0
  103. package/dist/signal-ingestion/errors.js +108 -0
  104. package/dist/signal-ingestion/governance-events.d.ts +181 -0
  105. package/dist/signal-ingestion/governance-events.js +189 -0
  106. package/dist/signal-ingestion/index.d.ts +35 -0
  107. package/dist/signal-ingestion/index.js +53 -0
  108. package/dist/signal-ingestion/manual-share-metric.d.ts +93 -0
  109. package/dist/signal-ingestion/manual-share-metric.js +106 -0
  110. package/dist/signal-ingestion/registry.d.ts +40 -0
  111. package/dist/signal-ingestion/registry.js +137 -0
  112. package/dist/signal-ingestion/residency.d.ts +227 -0
  113. package/dist/signal-ingestion/residency.js +238 -0
  114. package/dist/signal-ingestion/significance.d.ts +554 -0
  115. package/dist/signal-ingestion/significance.js +555 -0
  116. package/dist/signal-ingestion/types.d.ts +191 -0
  117. package/dist/signal-ingestion/types.js +8 -0
  118. package/dist/substrate/drift-composition.d.ts +270 -0
  119. package/dist/substrate/drift-composition.js +306 -0
  120. package/dist/substrate/drift-tui-surface.d.ts +61 -0
  121. package/dist/substrate/drift-tui-surface.js +102 -0
  122. package/dist/substrate/identity-class.d.ts +176 -0
  123. package/dist/substrate/identity-class.js +201 -0
  124. package/dist/tessellation/cross-soul-provenance-rule.d.ts +133 -0
  125. package/dist/tessellation/cross-soul-provenance-rule.js +171 -0
  126. package/dist/tessellation/inter-soul-embedding-distance-rule.d.ts +61 -0
  127. package/dist/tessellation/inter-soul-embedding-distance-rule.js +67 -0
  128. package/dist/tessellation/rule-registry.d.ts +269 -0
  129. package/dist/tessellation/rule-registry.js +92 -0
  130. package/dist/tessellation/soul-slug-ast-scan-rule.d.ts +90 -0
  131. package/dist/tessellation/soul-slug-ast-scan-rule.js +158 -0
  132. package/dist/tessellation-admission.d.ts +162 -0
  133. package/dist/tessellation-admission.js +146 -0
  134. package/dist/tessellation-drift.d.ts +246 -0
  135. package/dist/tessellation-drift.js +250 -0
  136. package/dist/validate-config.js +13 -0
  137. package/dist/validate-issue.js +2 -2
  138. package/dist/variant/cardinality-activation.d.ts +126 -0
  139. package/dist/variant/cardinality-activation.js +101 -0
  140. package/dist/variant/deprecation-lifecycle.d.ts +184 -0
  141. package/dist/variant/deprecation-lifecycle.js +208 -0
  142. package/dist/variant/drift-extension.d.ts +136 -0
  143. package/dist/variant/drift-extension.js +164 -0
  144. package/dist/variant/engineering-review.d.ts +185 -0
  145. package/dist/variant/engineering-review.js +142 -0
  146. package/dist/variant/index.d.ts +32 -0
  147. package/dist/variant/index.js +32 -0
  148. package/dist/variant/inheritance-validator.d.ts +165 -0
  149. package/dist/variant/inheritance-validator.js +139 -0
  150. package/dist/variant/internal-adopter/index.d.ts +11 -0
  151. package/dist/variant/internal-adopter/index.js +10 -0
  152. package/dist/variant/internal-adopter/products.d.ts +156 -0
  153. package/dist/variant/internal-adopter/products.js +366 -0
  154. package/dist/variant-admission.d.ts +316 -0
  155. package/dist/variant-admission.js +247 -0
  156. package/package.json +10 -8
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Pipeline-load wiring for RFC-0019 §10.1 / Phase 4 (AISDLC-340).
3
+ *
4
+ * Resolves `Pipeline.spec.embedding` → adapter (via registry) + storage
5
+ * backend (via factory). This is the single entry point pipeline loaders
6
+ * call when constructing the embedding substrate for a pipeline run.
7
+ *
8
+ * Feature-flag semantics:
9
+ * AI_SDLC_EMBEDDING_PROVIDER=on → load per spec
10
+ * anything else / unset → return null (framework disabled)
11
+ *
12
+ * When the flag is off AND a spec is present, callers SHOULD log a
13
+ * warning so misconfiguration is visible — done here via the optional
14
+ * `onFlagOffWithSpec` callback so the orchestrator can route the
15
+ * warning through its own logging surface (events.jsonl, console, etc.).
16
+ *
17
+ * Errors:
18
+ * - Unknown adapter name → `UnknownEmbeddingProvider`
19
+ * - Unknown storage backend → bare `Error` from the storage factory
20
+ * - Adapter is deprecated/removed → re-thrown from the deprecation
21
+ * gate; pipeline-load aborts so operators see the failure at load
22
+ * time, not at first embed().
23
+ *
24
+ * Tests: `pipeline-load.test.ts`
25
+ */
26
+ import { getEmbeddingAdapter } from './registry.js';
27
+ import { createEmbeddingStorageBackend } from './storage/index.js';
28
+ import { EmbeddingModelDeprecated, EmbeddingModelDeprecating, EmbeddingModelRemoved, } from './errors.js';
29
+ /** Default values applied when fields are omitted from the spec. */
30
+ export const EMBEDDING_DEFAULTS = {
31
+ storageBackend: 'jsonl',
32
+ staleVectorPolicy: 'lazy-re-embed',
33
+ autoEmbedOnWrite: true,
34
+ maxBatchSize: 2048,
35
+ /** Framework default; adapter MAY declare a different defaultGracePeriodDays. */
36
+ gracePeriodDays: 90,
37
+ };
38
+ /**
39
+ * `AI_SDLC_EMBEDDING_PROVIDER` flag parser. Mirrors the
40
+ * `AI_SDLC_DEPS_COMPOSITION` and `AI_SDLC_AUTONOMOUS_ORCHESTRATOR` patterns:
41
+ * truthy = `1|true|yes|on` (case-insensitive); anything else (including
42
+ * unset) is OFF.
43
+ */
44
+ export function isEmbeddingFrameworkEnabled(env = process.env) {
45
+ const raw = env.AI_SDLC_EMBEDDING_PROVIDER;
46
+ if (!raw)
47
+ return false;
48
+ return ['1', 'true', 'yes', 'on'].includes(raw.toLowerCase());
49
+ }
50
+ /**
51
+ * Resolve `(adapter, storage, policy)` from a pipeline spec.
52
+ *
53
+ * Returns `null` when the framework is disabled — by feature flag OR by
54
+ * absent spec. Callers SHOULD treat null as "no embedding substrate
55
+ * available" and let consumers emit `EmbeddingProviderNotConfigured`.
56
+ *
57
+ * Throws on:
58
+ * - unknown adapter (`UnknownEmbeddingProvider`)
59
+ * - unknown storage backend (bare `Error`)
60
+ * - adapter past `removedAt` (`EmbeddingModelRemoved`)
61
+ * - adapter past `deprecatedAt` in strict mode (`EmbeddingModelDeprecated`)
62
+ *
63
+ * @example
64
+ * const substrate = loadEmbeddingFromPipelineSpec(
65
+ * pipeline.spec.embedding,
66
+ * { artifactsDir: '/repo/.ai-sdlc/artifacts' },
67
+ * );
68
+ * if (substrate) {
69
+ * const vec = await substrate.adapter.embed('hello', 'rfc-0009-tessellation-drift');
70
+ * await substrate.storage.write({ ... });
71
+ * }
72
+ */
73
+ export function loadEmbeddingFromPipelineSpec(spec, options = {}) {
74
+ if (!spec) {
75
+ return null;
76
+ }
77
+ if (!isEmbeddingFrameworkEnabled()) {
78
+ options.onFlagOffWithSpec?.(spec);
79
+ return null;
80
+ }
81
+ const adapter = getEmbeddingAdapter(spec.provider);
82
+ // Deprecation gate. Strict mode FAILs at deprecatedAt; default mode
83
+ // continues to warn until removedAt (RFC-0019 OQ-4 re-walkthrough).
84
+ const now = options.now ?? new Date();
85
+ enforceDeprecationGate(adapter, spec, now, options.onDeprecationWarning);
86
+ // Resolve fallback (when distinct). Fallback failures don't block
87
+ // load — they surface at runtime when the primary is unavailable.
88
+ let fallbackAdapter;
89
+ if (spec.fallback && spec.fallback !== spec.provider) {
90
+ fallbackAdapter = getEmbeddingAdapter(spec.fallback);
91
+ }
92
+ const artifactsDir = options.artifactsDir ?? process.env.ARTIFACTS_DIR ?? '.ai-sdlc/artifacts';
93
+ const storage = createEmbeddingStorageBackend(spec.storageBackend ?? EMBEDDING_DEFAULTS.storageBackend, artifactsDir);
94
+ return {
95
+ adapter,
96
+ fallbackAdapter,
97
+ storage,
98
+ staleVectorPolicy: spec.staleVectorPolicy ?? EMBEDDING_DEFAULTS.staleVectorPolicy,
99
+ autoEmbedOnWrite: spec.autoEmbedOnWrite ?? EMBEDDING_DEFAULTS.autoEmbedOnWrite,
100
+ maxBatchSize: spec.maxBatchSize ?? EMBEDDING_DEFAULTS.maxBatchSize,
101
+ };
102
+ }
103
+ /**
104
+ * Three-layer precedence per OQ-4 re-walkthrough:
105
+ * framework default (90d) → adapter.defaultGracePeriodDays → per-org override
106
+ *
107
+ * Returned value is the effective grace period in days for THIS load.
108
+ */
109
+ export function resolveEffectiveGracePeriodDays(adapter, spec) {
110
+ const perOrg = spec.deprecationOverrides?.gracePeriodDays;
111
+ if (typeof perOrg === 'number' && perOrg > 0)
112
+ return perOrg;
113
+ // Adapter-declared default lives on `capabilities` per OQ-4; we read it
114
+ // through a duck-typed lookup so adapters that don't declare it still
115
+ // type-check. (`EmbeddingCapabilities` is intentionally not extended
116
+ // here — the field is OPTIONAL and only known adapters set it.)
117
+ const adapterDeclared = adapter.capabilities
118
+ .defaultGracePeriodDays;
119
+ if (typeof adapterDeclared === 'number' && adapterDeclared > 0)
120
+ return adapterDeclared;
121
+ return EMBEDDING_DEFAULTS.gracePeriodDays;
122
+ }
123
+ /**
124
+ * Deprecation gate. Behaviour per OQ-4 re-walkthrough:
125
+ * - past removedAt → throw EmbeddingModelRemoved
126
+ * - past deprecatedAt + strict → throw EmbeddingModelDeprecated
127
+ * - past deprecatedAt + default → emit warning event (continue load)
128
+ * - inside grace window → emit warning event (continue load)
129
+ *
130
+ * Catalog dedup (milestone counter at 89/60/30/7/1d before deprecatedAt) is
131
+ * the CALLER's responsibility — the loader emits one warning event per load;
132
+ * the orchestrator's Decision-catalog writer deduplicates by Decision key.
133
+ */
134
+ function enforceDeprecationGate(adapter, spec, now, onDeprecationWarning) {
135
+ if (adapter.removedAt) {
136
+ const removedAt = new Date(adapter.removedAt);
137
+ if (now >= removedAt) {
138
+ throw new EmbeddingModelRemoved(adapter.name, adapter.removedAt, adapter.replacementAlias);
139
+ }
140
+ }
141
+ if (!adapter.deprecatedAt)
142
+ return;
143
+ const deprecatedAt = new Date(adapter.deprecatedAt);
144
+ const msPerDay = 24 * 60 * 60 * 1000;
145
+ const daysUntilDeprecated = Math.ceil((deprecatedAt.getTime() - now.getTime()) / msPerDay);
146
+ if (now >= deprecatedAt) {
147
+ if (spec.deprecationOverrides?.strictModeAtDeprecatedAt) {
148
+ throw new EmbeddingModelDeprecated(adapter.name, adapter.deprecatedAt, adapter.replacementAlias);
149
+ }
150
+ // Default mode: continue + emit warning (operators see the signal,
151
+ // pipeline keeps running until removedAt — per OQ-4 re-walkthrough).
152
+ onDeprecationWarning?.({
153
+ adapterName: adapter.name,
154
+ deprecatedAt: adapter.deprecatedAt,
155
+ removedAt: adapter.removedAt,
156
+ replacementAlias: adapter.replacementAlias,
157
+ daysUntilDeprecated,
158
+ effectiveGracePeriodDays: resolveEffectiveGracePeriodDays(adapter, spec),
159
+ });
160
+ // Surface the deprecating type as a side-effect-free reminder. We
161
+ // throw nothing here — load proceeds — but instantiate the error
162
+ // class so its shape stays in scope for diagnostic logging consumers.
163
+ void new EmbeddingModelDeprecating(adapter.name, adapter.deprecatedAt, adapter.replacementAlias);
164
+ return;
165
+ }
166
+ const effectiveGrace = resolveEffectiveGracePeriodDays(adapter, spec);
167
+ if (daysUntilDeprecated <= effectiveGrace) {
168
+ onDeprecationWarning?.({
169
+ adapterName: adapter.name,
170
+ deprecatedAt: adapter.deprecatedAt,
171
+ removedAt: adapter.removedAt,
172
+ replacementAlias: adapter.replacementAlias,
173
+ daysUntilDeprecated,
174
+ effectiveGracePeriodDays: effectiveGrace,
175
+ });
176
+ }
177
+ }
178
+ //# sourceMappingURL=pipeline-load.js.map
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Embedding adapter registry per RFC-0019 §6.1.
3
+ *
4
+ * Mirrors the HarnessRegistry pattern from orchestrator/src/harness/registry.ts.
5
+ * Pipeline-load calls getEmbeddingAdapter(name) to resolve the configured provider;
6
+ * fails fast with UnknownEmbeddingProvider when the name is not registered.
7
+ *
8
+ * The singleton EMBEDDING_ADAPTERS map is the registry. Adopters who need to
9
+ * register custom adapters should call registerEmbeddingAdapter() before
10
+ * pipeline-load resolves the embedding section.
11
+ */
12
+ import type { EmbeddingAdapter } from './types.js';
13
+ /**
14
+ * Resolve an embedding adapter by its canonical name.
15
+ *
16
+ * Throws UnknownEmbeddingProvider when the name is not in the registry.
17
+ * Pipeline-load MUST fail with this error so operator typos are caught
18
+ * at load time, not silently at the first embed() call site.
19
+ *
20
+ * @param name - Canonical adapter alias (e.g., 'openai-text-embedding-3-small').
21
+ */
22
+ export declare function getEmbeddingAdapter(name: string): EmbeddingAdapter;
23
+ /**
24
+ * Register a custom embedding adapter. Adopters call this before pipeline-load
25
+ * to extend the built-in registry with their own adapter implementations.
26
+ *
27
+ * Overwrites any existing adapter with the same name — intentional to support
28
+ * adopter forks that want to replace the default OpenAI adapter.
29
+ *
30
+ * @param adapter - Adapter instance implementing EmbeddingAdapter.
31
+ */
32
+ export declare function registerEmbeddingAdapter(adapter: EmbeddingAdapter): void;
33
+ /**
34
+ * Check whether a named adapter is registered (without throwing).
35
+ * Useful for conditional feature-flag checks at pipeline-load.
36
+ *
37
+ * @param name - Canonical adapter alias.
38
+ */
39
+ export declare function hasEmbeddingAdapter(name: string): boolean;
40
+ /**
41
+ * List all registered adapter names.
42
+ * Used in error messages and capability introspection.
43
+ */
44
+ export declare function listEmbeddingAdapters(): string[];
45
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Embedding adapter registry per RFC-0019 §6.1.
3
+ *
4
+ * Mirrors the HarnessRegistry pattern from orchestrator/src/harness/registry.ts.
5
+ * Pipeline-load calls getEmbeddingAdapter(name) to resolve the configured provider;
6
+ * fails fast with UnknownEmbeddingProvider when the name is not registered.
7
+ *
8
+ * The singleton EMBEDDING_ADAPTERS map is the registry. Adopters who need to
9
+ * register custom adapters should call registerEmbeddingAdapter() before
10
+ * pipeline-load resolves the embedding section.
11
+ */
12
+ import { UnknownEmbeddingProvider } from './errors.js';
13
+ import { OpenAITextEmbedding3Small } from './adapters/openai-text-embedding-3-small.js';
14
+ const EMBEDDING_ADAPTERS = new Map([
15
+ ['openai-text-embedding-3-small', new OpenAITextEmbedding3Small()],
16
+ ]);
17
+ /**
18
+ * Resolve an embedding adapter by its canonical name.
19
+ *
20
+ * Throws UnknownEmbeddingProvider when the name is not in the registry.
21
+ * Pipeline-load MUST fail with this error so operator typos are caught
22
+ * at load time, not silently at the first embed() call site.
23
+ *
24
+ * @param name - Canonical adapter alias (e.g., 'openai-text-embedding-3-small').
25
+ */
26
+ export function getEmbeddingAdapter(name) {
27
+ const adapter = EMBEDDING_ADAPTERS.get(name);
28
+ if (!adapter) {
29
+ throw new UnknownEmbeddingProvider(name, [...EMBEDDING_ADAPTERS.keys()]);
30
+ }
31
+ return adapter;
32
+ }
33
+ /**
34
+ * Register a custom embedding adapter. Adopters call this before pipeline-load
35
+ * to extend the built-in registry with their own adapter implementations.
36
+ *
37
+ * Overwrites any existing adapter with the same name — intentional to support
38
+ * adopter forks that want to replace the default OpenAI adapter.
39
+ *
40
+ * @param adapter - Adapter instance implementing EmbeddingAdapter.
41
+ */
42
+ export function registerEmbeddingAdapter(adapter) {
43
+ EMBEDDING_ADAPTERS.set(adapter.name, adapter);
44
+ }
45
+ /**
46
+ * Check whether a named adapter is registered (without throwing).
47
+ * Useful for conditional feature-flag checks at pipeline-load.
48
+ *
49
+ * @param name - Canonical adapter alias.
50
+ */
51
+ export function hasEmbeddingAdapter(name) {
52
+ return EMBEDDING_ADAPTERS.has(name);
53
+ }
54
+ /**
55
+ * List all registered adapter names.
56
+ * Used in error messages and capability introspection.
57
+ */
58
+ export function listEmbeddingAdapters() {
59
+ return [...EMBEDDING_ADAPTERS.keys()];
60
+ }
61
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Stale-vector policy resolution per RFC-0019 §9.3 + OQ-2 re-walkthrough.
3
+ *
4
+ * When a read encounters a vector whose (embeddingProvider, embeddingModelVersion)
5
+ * does not match the currently configured adapter, the read path follows one
6
+ * of three policies:
7
+ *
8
+ * - `lazy` — re-embed the source text with the current adapter and return
9
+ * the new vector. The framework default; favours operator
10
+ * convenience over strict provenance.
11
+ * - `fail-loud` — refuse the comparison and throw `StaleVectorEncountered`.
12
+ * Used by consumers like RFC-0009 Eτ_tessellation_drift where
13
+ * silently overwriting a historical vector destroys time-series
14
+ * signal.
15
+ * - `inherit` — defer to the org-level default (and ultimately the framework
16
+ * default of `lazy`). Per-consumer call sites typically pass
17
+ * `inherit` when they have no opinion.
18
+ *
19
+ * The OQ-2 re-walkthrough resolution added an explicit per-consumer override
20
+ * API parameter on top of the org default. RFC-0009 drift pins `fail-loud` at
21
+ * its call sites; common-case consumers (PPA similarity, DoR dedup, classifier
22
+ * embeddings) leave the default. This module implements the three-layer
23
+ * inheritance chain (per-call → org default → framework default).
24
+ *
25
+ * Cross-cutting framing per RFC-0035 G0: a stale-vector encounter ALWAYS
26
+ * produces a `Decision: stale-vector-encountered` event, regardless of policy.
27
+ * Under `lazy` the event is informational (low severity). Under `fail-loud`
28
+ * the event is HIGH severity and surfaced in the operator batch review.
29
+ *
30
+ * @module embedding/stale-vector
31
+ */
32
+ import { EmbeddingError } from './errors.js';
33
+ /**
34
+ * Resolved policy that the read path actually applies.
35
+ * Distinct from `StaleVectorPolicyInput` because `inherit` is never the
36
+ * effective policy — it always resolves to either `lazy` or `fail-loud`.
37
+ */
38
+ export type StaleVectorPolicy = 'lazy' | 'fail-loud';
39
+ /**
40
+ * Policy value callers may pass at the API site.
41
+ * `inherit` means "use the org default (which falls back to framework default)".
42
+ */
43
+ export type StaleVectorPolicyInput = StaleVectorPolicy | 'inherit';
44
+ /**
45
+ * Framework-level default. Per OQ-2 re-walkthrough: `lazy` because the common
46
+ * case (issue dedup, clarification matching) is operator-interactive daily,
47
+ * while strict-provenance use cases (drift trajectory) are once-a-week
48
+ * analyses. Asymmetric impact warrants asymmetric default.
49
+ */
50
+ export declare const FRAMEWORK_DEFAULT_STALE_VECTOR_POLICY: StaleVectorPolicy;
51
+ /**
52
+ * Resolve the effective stale-vector policy from the three-layer chain.
53
+ *
54
+ * Precedence (highest to lowest):
55
+ * 1. `perCallOverride` — the value passed at the embed() / read() call site
56
+ * (e.g., RFC-0009 drift pins `fail-loud`). `inherit` defers to layer 2.
57
+ * 2. `orgDefault` — per-org configuration (`embedding-config.yaml`
58
+ * `staleVectorPolicy.default`). Undefined defers to layer 3.
59
+ * 3. Framework default — `FRAMEWORK_DEFAULT_STALE_VECTOR_POLICY` (= `lazy`).
60
+ *
61
+ * @param perCallOverride - Optional per-call override. `inherit` defers up.
62
+ * @param orgDefault - Optional org-level default. Undefined defers to framework.
63
+ * @returns The effective policy: `lazy` or `fail-loud`.
64
+ */
65
+ export declare function resolveStaleVectorPolicy(perCallOverride: StaleVectorPolicyInput | undefined, orgDefault: StaleVectorPolicy | undefined): StaleVectorPolicy;
66
+ /**
67
+ * Severity used for the `Decision: stale-vector-encountered` catalog event.
68
+ * Mirrors the operator-impact surface — `lazy` runs as a silent informational
69
+ * decision; `fail-loud` is escalated for batch review.
70
+ */
71
+ export type StaleVectorDecisionSeverity = 'info' | 'high';
72
+ /**
73
+ * Map a resolved policy to the catalog Decision severity per OQ-2 re-walkthrough.
74
+ */
75
+ export declare function severityForPolicy(policy: StaleVectorPolicy): StaleVectorDecisionSeverity;
76
+ /**
77
+ * Inputs describing a single stale-vector encounter.
78
+ */
79
+ export interface StaleVectorContext {
80
+ /** Provider on the stored entry (e.g., 'openai-text-embedding-ada-002'). */
81
+ storedProvider: string;
82
+ /** Model version on the stored entry. */
83
+ storedModelVersion: string;
84
+ /** Adapter the caller is currently configured to use. */
85
+ currentProvider: string;
86
+ /** Model version on the current adapter. */
87
+ currentModelVersion: string;
88
+ /** SHA-256 of the source text — the lookup key that surfaced the stale entry. */
89
+ textHash: string;
90
+ /**
91
+ * Optional consumer label so the catalog event can be attributed back to
92
+ * the calling subsystem (e.g., 'rfc-0009-tessellation-drift').
93
+ */
94
+ consumerLabel?: string;
95
+ }
96
+ /**
97
+ * Thrown by the read path when the resolved policy is `fail-loud`.
98
+ * Carries the full context so callers can build a useful operator message.
99
+ */
100
+ export declare class StaleVectorEncountered extends EmbeddingError {
101
+ readonly context: StaleVectorContext;
102
+ constructor(context: StaleVectorContext);
103
+ }
104
+ /**
105
+ * Whether a stored entry's provenance matches the current adapter.
106
+ * Returns `true` when both provider and modelVersion match — i.e., the entry
107
+ * is NOT stale and no policy enforcement is needed.
108
+ */
109
+ export declare function isCurrentVector(storedProvider: string, storedModelVersion: string, currentProvider: string, currentModelVersion: string): boolean;
110
+ //# sourceMappingURL=stale-vector.d.ts.map
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Stale-vector policy resolution per RFC-0019 §9.3 + OQ-2 re-walkthrough.
3
+ *
4
+ * When a read encounters a vector whose (embeddingProvider, embeddingModelVersion)
5
+ * does not match the currently configured adapter, the read path follows one
6
+ * of three policies:
7
+ *
8
+ * - `lazy` — re-embed the source text with the current adapter and return
9
+ * the new vector. The framework default; favours operator
10
+ * convenience over strict provenance.
11
+ * - `fail-loud` — refuse the comparison and throw `StaleVectorEncountered`.
12
+ * Used by consumers like RFC-0009 Eτ_tessellation_drift where
13
+ * silently overwriting a historical vector destroys time-series
14
+ * signal.
15
+ * - `inherit` — defer to the org-level default (and ultimately the framework
16
+ * default of `lazy`). Per-consumer call sites typically pass
17
+ * `inherit` when they have no opinion.
18
+ *
19
+ * The OQ-2 re-walkthrough resolution added an explicit per-consumer override
20
+ * API parameter on top of the org default. RFC-0009 drift pins `fail-loud` at
21
+ * its call sites; common-case consumers (PPA similarity, DoR dedup, classifier
22
+ * embeddings) leave the default. This module implements the three-layer
23
+ * inheritance chain (per-call → org default → framework default).
24
+ *
25
+ * Cross-cutting framing per RFC-0035 G0: a stale-vector encounter ALWAYS
26
+ * produces a `Decision: stale-vector-encountered` event, regardless of policy.
27
+ * Under `lazy` the event is informational (low severity). Under `fail-loud`
28
+ * the event is HIGH severity and surfaced in the operator batch review.
29
+ *
30
+ * @module embedding/stale-vector
31
+ */
32
+ import { EmbeddingError } from './errors.js';
33
+ /**
34
+ * Framework-level default. Per OQ-2 re-walkthrough: `lazy` because the common
35
+ * case (issue dedup, clarification matching) is operator-interactive daily,
36
+ * while strict-provenance use cases (drift trajectory) are once-a-week
37
+ * analyses. Asymmetric impact warrants asymmetric default.
38
+ */
39
+ export const FRAMEWORK_DEFAULT_STALE_VECTOR_POLICY = 'lazy';
40
+ /**
41
+ * Resolve the effective stale-vector policy from the three-layer chain.
42
+ *
43
+ * Precedence (highest to lowest):
44
+ * 1. `perCallOverride` — the value passed at the embed() / read() call site
45
+ * (e.g., RFC-0009 drift pins `fail-loud`). `inherit` defers to layer 2.
46
+ * 2. `orgDefault` — per-org configuration (`embedding-config.yaml`
47
+ * `staleVectorPolicy.default`). Undefined defers to layer 3.
48
+ * 3. Framework default — `FRAMEWORK_DEFAULT_STALE_VECTOR_POLICY` (= `lazy`).
49
+ *
50
+ * @param perCallOverride - Optional per-call override. `inherit` defers up.
51
+ * @param orgDefault - Optional org-level default. Undefined defers to framework.
52
+ * @returns The effective policy: `lazy` or `fail-loud`.
53
+ */
54
+ export function resolveStaleVectorPolicy(perCallOverride, orgDefault) {
55
+ if (perCallOverride && perCallOverride !== 'inherit') {
56
+ return perCallOverride;
57
+ }
58
+ if (orgDefault) {
59
+ return orgDefault;
60
+ }
61
+ return FRAMEWORK_DEFAULT_STALE_VECTOR_POLICY;
62
+ }
63
+ /**
64
+ * Map a resolved policy to the catalog Decision severity per OQ-2 re-walkthrough.
65
+ */
66
+ export function severityForPolicy(policy) {
67
+ return policy === 'fail-loud' ? 'high' : 'info';
68
+ }
69
+ /**
70
+ * Thrown by the read path when the resolved policy is `fail-loud`.
71
+ * Carries the full context so callers can build a useful operator message.
72
+ */
73
+ export class StaleVectorEncountered extends EmbeddingError {
74
+ context;
75
+ constructor(context) {
76
+ super(`Stale embedding vector encountered: stored ${context.storedProvider}@${context.storedModelVersion}, ` +
77
+ `current ${context.currentProvider}@${context.currentModelVersion}. ` +
78
+ `Policy 'fail-loud' refuses the comparison. ` +
79
+ `Migrate via: cli-embedding-bump --to ${context.currentProvider}`);
80
+ this.context = context;
81
+ this.name = 'StaleVectorEncountered';
82
+ }
83
+ }
84
+ /**
85
+ * Whether a stored entry's provenance matches the current adapter.
86
+ * Returns `true` when both provider and modelVersion match — i.e., the entry
87
+ * is NOT stale and no policy enforcement is needed.
88
+ */
89
+ export function isCurrentVector(storedProvider, storedModelVersion, currentProvider, currentModelVersion) {
90
+ return storedProvider === currentProvider && storedModelVersion === currentModelVersion;
91
+ }
92
+ //# sourceMappingURL=stale-vector.js.map
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Embedding storage backend factory per RFC-0019 §8.3 + Phase 2.
3
+ *
4
+ * Factory is keyed on `Pipeline.spec.embedding.storageBackend` (the
5
+ * 'storageBackend' string from pipeline config). Currently supports:
6
+ * - 'jsonl' (default): JSONL append-only backend at <artifactsDir>/_embeddings/
7
+ *
8
+ * Future backends ('sqlite', 'pgvector', 'qdrant', etc.) implement the
9
+ * EmbeddingStorageBackend interface and register themselves here.
10
+ *
11
+ * Usage:
12
+ * const backend = createEmbeddingStorageBackend('jsonl', '/path/to/artifacts');
13
+ */
14
+ export type { EmbeddingStorageBackend, VectorStoreEntry, VectorStoreFilter } from './types.js';
15
+ export { JsonlEmbeddingStorageBackend, SCALE_ESCALATION_MAX_ENTRIES, SCALE_ESCALATION_P95_READ_MS, } from './jsonl-backend.js';
16
+ export type { ScaleEscalationSignal } from './jsonl-backend.js';
17
+ import type { EmbeddingStorageBackend } from './types.js';
18
+ import type { ScaleEscalationSignal } from './jsonl-backend.js';
19
+ /**
20
+ * Known storage backend names.
21
+ * Extend this union when adding new backends.
22
+ */
23
+ export type StorageBackendName = 'jsonl' | (string & Record<never, never>);
24
+ /**
25
+ * Options passed to the backend factory.
26
+ */
27
+ export interface StorageBackendOptions {
28
+ /**
29
+ * Optional scale-escalation callback. Called when the backend detects
30
+ * that it is approaching operational limits (>100K entries OR p95 read >250ms).
31
+ * Wire to your telemetry layer; defaults to console.warn inside the backend.
32
+ */
33
+ onScaleEscalation?: (signal: ScaleEscalationSignal) => void;
34
+ }
35
+ /**
36
+ * Create an EmbeddingStorageBackend from a backend name + artifacts directory.
37
+ *
38
+ * @param backendName - Backend identifier from Pipeline.spec.embedding.storageBackend.
39
+ * Defaults to 'jsonl' when omitted or undefined.
40
+ * @param artifactsDir - Path to the artifacts directory. The backend creates its
41
+ * subdirectory (e.g., `_embeddings/`) under this path.
42
+ * @param options - Optional factory options.
43
+ *
44
+ * @throws {Error} When `backendName` is not a known backend.
45
+ *
46
+ * @example
47
+ * const backend = createEmbeddingStorageBackend('jsonl', process.env.ARTIFACTS_DIR ?? '.ai-sdlc');
48
+ * await backend.write({ ... });
49
+ */
50
+ export declare function createEmbeddingStorageBackend(backendName: StorageBackendName | undefined, artifactsDir: string, options?: StorageBackendOptions): EmbeddingStorageBackend;
51
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Embedding storage backend factory per RFC-0019 §8.3 + Phase 2.
3
+ *
4
+ * Factory is keyed on `Pipeline.spec.embedding.storageBackend` (the
5
+ * 'storageBackend' string from pipeline config). Currently supports:
6
+ * - 'jsonl' (default): JSONL append-only backend at <artifactsDir>/_embeddings/
7
+ *
8
+ * Future backends ('sqlite', 'pgvector', 'qdrant', etc.) implement the
9
+ * EmbeddingStorageBackend interface and register themselves here.
10
+ *
11
+ * Usage:
12
+ * const backend = createEmbeddingStorageBackend('jsonl', '/path/to/artifacts');
13
+ */
14
+ export { JsonlEmbeddingStorageBackend, SCALE_ESCALATION_MAX_ENTRIES, SCALE_ESCALATION_P95_READ_MS, } from './jsonl-backend.js';
15
+ import { JsonlEmbeddingStorageBackend } from './jsonl-backend.js';
16
+ /**
17
+ * Create an EmbeddingStorageBackend from a backend name + artifacts directory.
18
+ *
19
+ * @param backendName - Backend identifier from Pipeline.spec.embedding.storageBackend.
20
+ * Defaults to 'jsonl' when omitted or undefined.
21
+ * @param artifactsDir - Path to the artifacts directory. The backend creates its
22
+ * subdirectory (e.g., `_embeddings/`) under this path.
23
+ * @param options - Optional factory options.
24
+ *
25
+ * @throws {Error} When `backendName` is not a known backend.
26
+ *
27
+ * @example
28
+ * const backend = createEmbeddingStorageBackend('jsonl', process.env.ARTIFACTS_DIR ?? '.ai-sdlc');
29
+ * await backend.write({ ... });
30
+ */
31
+ export function createEmbeddingStorageBackend(backendName = 'jsonl', artifactsDir, options) {
32
+ switch (backendName) {
33
+ case 'jsonl':
34
+ return new JsonlEmbeddingStorageBackend(artifactsDir, {
35
+ onScaleEscalation: options?.onScaleEscalation,
36
+ });
37
+ default:
38
+ throw new Error(`Unknown embedding storage backend '${backendName}'. ` +
39
+ `Known backends: ['jsonl']. ` +
40
+ `To add a custom backend, implement EmbeddingStorageBackend and add a case here.`);
41
+ }
42
+ }
43
+ //# sourceMappingURL=index.js.map