@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,554 @@
1
+ /**
2
+ * RFC-0030 Phase 4 — Tier 2 significance threshold, SA resonance filter,
3
+ * flooding detection (z-score on rolling per-source baseline), residency-
4
+ * violation gate.
5
+ *
6
+ * This module operates on Phase 3 `DemandCluster[]` output and produces:
7
+ *
8
+ * 1. **Tier 2 significance gate** (RFC-0030 §8): clusters must meet
9
+ * `minSignalCount` + `minUniqueSources` + `minTier1SignalCount` +
10
+ * `minClusterAgeDays` before they qualify for D1 scoring. Below-threshold
11
+ * clusters are marked `monitored` (not silently dropped — they remain
12
+ * visible for operator review).
13
+ *
14
+ * 2. **SA resonance filter** (RFC-0030 §9 + RFC-0029 Principle 4): clusters
15
+ * are bucketed by SA resonance score against the current Soul DID:
16
+ * - `>= fullWeight` → `full` (no D1 weight discount)
17
+ * - `>= discounted` → `discounted` (D1 weight × 0.7)
18
+ * - `>= excluded` (exclusive) → `low-sa-review` (D1 weight × 0.3 +
19
+ * Decision logged for Product Lead batch review per AC #3)
20
+ * - `<= excluded` (== 0.0) → `out-of-scope` (excluded from D1;
21
+ * logged as out-of-scope demand)
22
+ *
23
+ * 3. **OQ-13.5 flooding detection (AISDLC-433 v0.3 refinement)** — REPLACES
24
+ * the previous fixed-multiplier detector with z-score on the same
25
+ * per-source rolling baseline:
26
+ * - For every source in the detection window, compute its
27
+ * `windowCount` (signals in the last `windowMinutes`) and compare
28
+ * to the per-source baseline `{mean, stddev}` computed from the
29
+ * rolling `baselineDays`-day history.
30
+ * - Trigger condition (RFC-0030 §13.5):
31
+ * `windowCount > (mean + zScoreThreshold × stddev)`
32
+ * AND `uniqueSources_in_window < minUniqueSourcesForSuspicion`
33
+ * → emit `Decision: signal-flooding-detected`.
34
+ * - **Cold-start handling** (AC #4): when the rolling baseline has
35
+ * fewer than `baselineDays` of history, the detector returns the
36
+ * `calibrating` status and emits NO Decision — Tier 2 significance
37
+ * is the sole defense during the calibration window.
38
+ * - **Quarantine** (AC #6, #7): flooding signals are tagged
39
+ * `quarantined: true` with an `expiresAt` timestamp; quarantined
40
+ * signals do NOT feed D1 (D1 path filters them out). Default
41
+ * duration 24h; per-org `flooding.quarantineDurationHours`
42
+ * override. Auto-expiry releases signals back to D1 candidacy.
43
+ * - **Operator one-click unquarantine** (AC #8, #9): the surface
44
+ * composes with RFC-0023 Blockers pane via the `QuarantineStore`
45
+ * API + the `unquarantineFlooded()` helper. Unquarantine emits
46
+ * `Decision: signal-flooding-false-positive` referencing the
47
+ * original flooding Decision (feedback signal for v2
48
+ * reputation-weighting calibration).
49
+ * Pipeline NEVER halts on flooding (G0 non-blocking contract).
50
+ *
51
+ * 4. **OQ-13.3 residency-violation gate** (adapter-level): per `checkSignalResidency`,
52
+ * a signal whose `region` falls outside the adopter's declared regime
53
+ * `allowedRegions` is refused at adapter level. Pipeline never halts.
54
+ *
55
+ * @module signal-ingestion/significance
56
+ */
57
+ import type { DemandCluster } from './clustering.js';
58
+ import type { FloodingDetectionConfig, FloodingQuarantineConfig, SignalIngestionConfig, Tier2SignificanceThreshold, SaResonanceThresholds } from './config.js';
59
+ import type { RawSignal, SignalResidencyViolationDecision, SignalSourceName } from './types.js';
60
+ /**
61
+ * Outcome of running the Tier 2 significance gate on a single cluster.
62
+ * - `qualified` — meets all four threshold conditions; eligible for D1.
63
+ * - `monitored` — at least one condition unmet; cluster persisted but
64
+ * does NOT feed D1 (RFC-0030 §8).
65
+ */
66
+ export type Tier2SignificanceState = 'qualified' | 'monitored';
67
+ /**
68
+ * Which threshold conditions failed, when the cluster is `monitored`.
69
+ * `[]` when the cluster is `qualified`.
70
+ */
71
+ export interface Tier2SignificanceReasons {
72
+ signalCount: boolean;
73
+ uniqueSources: boolean;
74
+ tier1SignalCount: boolean;
75
+ clusterAgeDays: boolean;
76
+ }
77
+ /**
78
+ * Per RFC-0030 §9: cluster SA resonance bucket. The bucket directly determines
79
+ * the D1 weight multiplier (see `SA_WEIGHT_MULTIPLIERS`).
80
+ *
81
+ * - `full` — `saResonance >= fullWeight` (default 0.7). Full D1 weight.
82
+ * - `discounted` — `>= discounted` (default 0.4) and `< fullWeight`.
83
+ * D1 weight × 0.7.
84
+ * - `low-sa-review` — `> excluded` (default 0.0, exclusive) and `< discounted`.
85
+ * D1 weight × 0.3 + logged via Decision for Product Lead
86
+ * batch review (AC #3).
87
+ * - `out-of-scope` — `<= excluded` (default 0.0). Excluded from D1; logged
88
+ * as out-of-scope demand for separate triage.
89
+ * - `pending` — `cluster.saResonance` is `undefined` (Phase 3 default).
90
+ * Caller must populate `saResonance` before invoking
91
+ * the filter (typically via the Soul DID adapter); the
92
+ * bucket reports `pending` and the cluster is excluded
93
+ * from D1 by default (fail-closed).
94
+ */
95
+ export type SaResonanceBucket = 'full' | 'discounted' | 'low-sa-review' | 'out-of-scope' | 'pending';
96
+ /** Per-bucket D1 weight multiplier per RFC-0030 §9. */
97
+ export declare const SA_WEIGHT_MULTIPLIERS: Readonly<Record<SaResonanceBucket, number>>;
98
+ /**
99
+ * A `DemandCluster` annotated with its Phase 4 verdict on significance + SA.
100
+ * The augmented record is what downstream Phase 5 D1 reformulation consumes.
101
+ *
102
+ * `eligibleForD1` is `true` IFF the cluster `qualified` for the significance
103
+ * threshold AND its SA bucket is NOT `out-of-scope` / `pending`.
104
+ *
105
+ * `d1WeightMultiplier` is the combined product of:
106
+ * - significance flag (qualified → 1.0, monitored → 0.0)
107
+ * - SA bucket multiplier (per SA_WEIGHT_MULTIPLIERS)
108
+ * Downstream Phase 5 multiplies this against the existing `baseWeight ×
109
+ * tierMultiplier × icpResonanceWeight × recencyDecay` chain.
110
+ */
111
+ export interface SignificanceAssessedCluster {
112
+ cluster: DemandCluster;
113
+ tier2Significance: Tier2SignificanceState;
114
+ tier2Reasons: Tier2SignificanceReasons;
115
+ saResonanceBucket: SaResonanceBucket;
116
+ eligibleForD1: boolean;
117
+ d1WeightMultiplier: number;
118
+ }
119
+ /**
120
+ * Emitted when a cluster's SA resonance bucket is `low-sa-review` per AC #3 —
121
+ * the demand is real but adjacent-to-soul, and Product Lead should review it
122
+ * (NOT silently dropped). Routes via the RFC-0035 G0 catalog.
123
+ */
124
+ export interface SignalLowSaForReviewDecision {
125
+ type: 'Decision';
126
+ decision: 'signal-low-sa-for-review';
127
+ clusterId: string;
128
+ saResonance: number;
129
+ signalCount: number;
130
+ message: string;
131
+ }
132
+ /**
133
+ * Emitted when the SA bucket is `out-of-scope` (saResonance <= excluded
134
+ * threshold, default 0.0). Per RFC-0030 §9 the demand is logged for separate
135
+ * triage rather than fed into D1. Distinct from `low-sa-review` so operators
136
+ * can prioritise reviewing soul-adjacent demand over fully-out-of-scope
137
+ * demand.
138
+ */
139
+ export interface SignalOutOfScopeDecision {
140
+ type: 'Decision';
141
+ decision: 'signal-out-of-scope';
142
+ clusterId: string;
143
+ saResonance: number;
144
+ signalCount: number;
145
+ message: string;
146
+ }
147
+ /**
148
+ * Detection status returned by `detectFlooding()`.
149
+ * - `flooded` — the trigger condition fired; a Decision was emitted.
150
+ * - `clean` — detector ran, baseline sufficient, no trigger.
151
+ * - `calibrating` — rolling baseline has <`baselineDays` of history; no
152
+ * Decisions emitted (Tier 2 significance is sole defense
153
+ * during calibration). Per AC #4.
154
+ * - `empty-window`— the detection window contains zero signals.
155
+ */
156
+ export type FloodingDetectionStatus = 'flooded' | 'clean' | 'calibrating' | 'empty-window';
157
+ /**
158
+ * Z-score detector output for one detection window.
159
+ *
160
+ * `status` describes the outcome (cold-start / clean / flooded / empty).
161
+ * `decision` is populated iff `status === 'flooded'`; it's the Decision the
162
+ * caller routes to the RFC-0035 catalog.
163
+ */
164
+ export interface FloodingDetectionResult {
165
+ status: FloodingDetectionStatus;
166
+ /** Populated when `status === 'flooded'`. */
167
+ decision?: SignalFloodingDetectedDecision;
168
+ /** Number of signals in the detection window. */
169
+ signalCount: number;
170
+ /** Distinct sources in the detection window. */
171
+ uniqueSources: number;
172
+ /** Days of baseline data the detector had access to. */
173
+ baselineDaysObserved: number;
174
+ }
175
+ /**
176
+ * Per-source baseline samples. Each entry is the daily signal-count
177
+ * observation for that source over the rolling baseline window. The detector
178
+ * computes `{mean, stddev}` from the samples.
179
+ *
180
+ * Operators wire this map from their historical-data substrate; persistence
181
+ * is the caller's responsibility (orchestrator events.jsonl roll-up, etc.).
182
+ * AISDLC-433 ships the detection algorithm; the substrate plumbing is the
183
+ * caller's domain.
184
+ */
185
+ export type PerSourceBaseline = Record<string, number[]>;
186
+ /**
187
+ * Per-source baseline statistic. Internal — exposed for unit testing.
188
+ */
189
+ export interface BaselineStat {
190
+ /** Mean of the samples. */
191
+ mean: number;
192
+ /** Population standard deviation of the samples. */
193
+ stddev: number;
194
+ /** Number of samples (days observed). */
195
+ sampleCount: number;
196
+ }
197
+ /**
198
+ * Source-level flooding flag — surfaces in the Decision so the operator
199
+ * sees which source tripped the trigger.
200
+ */
201
+ export interface FloodingSourceFlag {
202
+ /** Source identifier (adapter name when available, falls back to sourceId prefix). */
203
+ sourceId: string;
204
+ /** Z-score for this source's window count vs its baseline. */
205
+ zScore: number;
206
+ /** Window signal count. */
207
+ windowCount: number;
208
+ /** Baseline mean signals/day. */
209
+ baselineMean: number;
210
+ /** Baseline standard deviation signals/day. */
211
+ baselineStddev: number;
212
+ /** Days of baseline data observed for this source. */
213
+ baselineDays: number;
214
+ }
215
+ /**
216
+ * Decision emitted when the z-score detector trips per RFC-0030 §13.5
217
+ * (AISDLC-433 v0.3 refinement). Replaces the legacy multi-indicator Decision.
218
+ */
219
+ export interface SignalFloodingDetectedDecision {
220
+ type: 'Decision';
221
+ decision: 'signal-flooding-detected';
222
+ /** Stable Decision ID — the operator unquarantine path references this. */
223
+ decisionId: string;
224
+ /** Detection-window cutoff used when this Decision was emitted. */
225
+ detectedAt: string;
226
+ /** Total signal count in the detection window. */
227
+ signalCount: number;
228
+ /** Number of distinct sources contributing to the window. */
229
+ uniqueSources: number;
230
+ /** Per-source z-scores + baseline stats for sources that exceeded threshold. */
231
+ flaggedSources: FloodingSourceFlag[];
232
+ /** Source IDs of signals quarantined as a result of this Decision (empty when quarantine disabled). */
233
+ quarantinedSourceIds: string[];
234
+ /** Quarantine duration applied (hours; 0 when disabled). */
235
+ quarantineDurationHours: number;
236
+ message: string;
237
+ }
238
+ /**
239
+ * Re-export of the live default for back-compat with the previous shipped
240
+ * surface. Phase 4 originally exposed `DEFAULT_FLOODING_DETECTION_CONFIG`
241
+ * as a frozen object; AISDLC-433 routes the same name to the v0.3 z-score
242
+ * defaults (sourced from `DEFAULT_SIGNAL_INGESTION_CONFIG.flooding.detection`)
243
+ * so downstream callers continue to import a working default object.
244
+ */
245
+ export declare const DEFAULT_FLOODING_DETECTION_CONFIG: FloodingDetectionConfig;
246
+ /**
247
+ * Apply the RFC-0030 §8 Tier 2 significance threshold to a single cluster.
248
+ *
249
+ * The four conditions are evaluated independently so reasons can be reported
250
+ * back; the cluster `qualified` IFF all four pass.
251
+ *
252
+ * `asOf` defaults to `new Date()` for cluster-age computation.
253
+ */
254
+ export declare function assessTier2Significance(cluster: DemandCluster, threshold?: Tier2SignificanceThreshold, asOf?: Date): {
255
+ state: Tier2SignificanceState;
256
+ reasons: Tier2SignificanceReasons;
257
+ };
258
+ /**
259
+ * Classify a cluster's SA resonance into one of five buckets per RFC-0030 §9.
260
+ *
261
+ * When `cluster.saResonance` is `undefined`, returns `pending` — the caller
262
+ * is expected to populate the field via the Soul DID adapter before
263
+ * invocation. Fail-closed: `pending` results in `eligibleForD1 = false`.
264
+ */
265
+ export declare function classifySaResonance(cluster: DemandCluster, thresholds?: SaResonanceThresholds): SaResonanceBucket;
266
+ /**
267
+ * Options for `assessClusterSignificance()`.
268
+ */
269
+ export interface AssessClusterSignificanceOptions {
270
+ config?: SignalIngestionConfig;
271
+ asOf?: Date;
272
+ }
273
+ /**
274
+ * Result returned by `assessClusterSignificance()`.
275
+ */
276
+ export interface AssessClusterSignificanceResult {
277
+ assessments: SignificanceAssessedCluster[];
278
+ /**
279
+ * `signal-low-sa-for-review` Decisions emitted for clusters whose SA bucket
280
+ * is `low-sa-review` — surfaces low-SA demand to the catalog for Product
281
+ * Lead batch review (AC #3).
282
+ */
283
+ lowSaDecisions: SignalLowSaForReviewDecision[];
284
+ /**
285
+ * `signal-out-of-scope` Decisions emitted for clusters whose SA bucket is
286
+ * `out-of-scope` — the demand is logged for separate triage rather than
287
+ * fed into D1.
288
+ */
289
+ outOfScopeDecisions: SignalOutOfScopeDecision[];
290
+ }
291
+ /**
292
+ * Apply Phase 4 significance + SA filter to a batch of `DemandCluster`s.
293
+ *
294
+ * The resulting `assessments` carry the final `d1WeightMultiplier` that
295
+ * Phase 5 multiplies into the D1 formula. Below-threshold clusters retain
296
+ * `eligibleForD1 = false` (not silently dropped) per RFC-0030 §8.
297
+ *
298
+ * `lowSaDecisions` are emitted for every cluster whose SA bucket is
299
+ * `low-sa-review` — these are the AC #3 "low-SA-but-high-volume" Decisions.
300
+ */
301
+ export declare function assessClusterSignificance(clusters: DemandCluster[], options?: AssessClusterSignificanceOptions): AssessClusterSignificanceResult;
302
+ /**
303
+ * Options for `detectFlooding()`. The z-score detector REPLACES the
304
+ * multiplier-based path that shipped with AISDLC-346.
305
+ */
306
+ export interface DetectFloodingOptions {
307
+ /**
308
+ * Detection thresholds. Defaults to the loaded config's `flooding.detection`
309
+ * block (or `DEFAULT_FLOODING_DETECTION_CONFIG` when no config supplied).
310
+ */
311
+ config?: FloodingDetectionConfig;
312
+ /**
313
+ * Quarantine sub-config. When omitted defaults to the framework default
314
+ * (`enabled: true`, `durationHours: 24`). Used to populate the Decision's
315
+ * `quarantineDurationHours` field + the `QuarantineStore` entries.
316
+ */
317
+ quarantineConfig?: FloodingQuarantineConfig;
318
+ /**
319
+ * Per-source rolling baseline. Each entry is a list of daily signal-count
320
+ * observations for that source over the rolling `baselineDays` window.
321
+ * The detector computes `{mean, stddev}` from the samples.
322
+ *
323
+ * Source key resolution (matches the pre-AISDLC-433 contract): prefers
324
+ * `metadata.adapterName`, falls back to the `sourceId` prefix before the
325
+ * first `-`.
326
+ */
327
+ perSourceBaselines?: PerSourceBaseline;
328
+ /** Detection-window cutoff. Defaults to `new Date()`. */
329
+ asOf?: Date;
330
+ /**
331
+ * Optional quarantine store the detector writes to. When supplied, every
332
+ * flooded source has its signals tagged in the store. When omitted, the
333
+ * Decision still carries the `quarantinedSourceIds` list but no
334
+ * persistence happens — useful for pure unit testing.
335
+ */
336
+ quarantineStore?: QuarantineStore;
337
+ /**
338
+ * Decision ID factory. Defaults to a UTC timestamp + 8-char random suffix.
339
+ * Tests override this to make assertions deterministic.
340
+ */
341
+ generateDecisionId?: () => string;
342
+ }
343
+ /**
344
+ * Z-score detector — RFC-0030 §13.5 v0.3 trigger condition is
345
+ * `windowCount > (mean + zScoreThreshold × stddev) AND uniqueSources_in_window
346
+ * < minUniqueSourcesForSuspicion`.
347
+ *
348
+ * Returns a `FloodingDetectionResult` whose `status` discriminates the four
349
+ * outcomes (flooded / clean / calibrating / empty-window). The caller routes
350
+ * `result.decision` to the catalog when `status === 'flooded'`.
351
+ *
352
+ * Cold-start (AC #4): when the maximum per-source `baselineDays` observed
353
+ * across all in-window sources is < `config.baselineDays`, the detector
354
+ * returns `status: 'calibrating'` with no Decision — Tier 2 significance is
355
+ * the sole defense until the rolling baseline has built up.
356
+ *
357
+ * Quarantine (AC #6, #7): when `quarantineConfig.enabled`, every in-window
358
+ * signal from a flagged source is tagged in the supplied `quarantineStore`
359
+ * with `expiresAt = asOf + quarantineDurationHours`. Auto-expiry happens
360
+ * lazily on read (see `isSignalQuarantined()`).
361
+ */
362
+ export declare function detectFlooding(signals: RawSignal[], options?: DetectFloodingOptions): FloodingDetectionResult;
363
+ /**
364
+ * Population-standard-deviation baseline stat. Exposed for unit testing.
365
+ * Returns `{mean: 0, stddev: 0, sampleCount: 0}` on empty input — caller's
366
+ * cold-start gate should prevent that from reaching `computeZScore()`.
367
+ */
368
+ export declare function computeBaselineStat(samples: readonly number[]): BaselineStat;
369
+ /**
370
+ * Z-score of a single observation against `BaselineStat`. When `stddev === 0`
371
+ * (degenerate baseline — every sample identical), returns `+Infinity` if the
372
+ * observation exceeds the mean, `0` if it equals the mean — matches the
373
+ * statistical convention that any deviation from a zero-variance baseline is
374
+ * infinitely surprising. Exposed for unit testing.
375
+ */
376
+ export declare function computeZScore(observation: number, stats: BaselineStat): number;
377
+ /**
378
+ * A single entry in the quarantine store. Created by `detectFlooding()` when
379
+ * a flooded source's signals are quarantined; consumed by:
380
+ * - The D1 path, to exclude quarantined signals from cluster scoring
381
+ * (`isSignalQuarantined()`).
382
+ * - The operator unquarantine flow (`unquarantineFlooded()`) for one-click
383
+ * release after a false-positive review.
384
+ * - The RFC-0023 Blockers pane, which renders pending Decisions + offers
385
+ * the unquarantine action.
386
+ */
387
+ export interface QuarantineEntry {
388
+ /** Signal `sourceId` quarantined. */
389
+ sourceId: string;
390
+ /** Adapter-level source key (the key used by the detector + baselines). */
391
+ adapterSource: string;
392
+ /** Originating Decision ID. The false-positive Decision references this. */
393
+ decisionId: string;
394
+ quarantinedAt: Date;
395
+ /** When quarantine auto-expires. */
396
+ expiresAt: Date;
397
+ /** Free-form rationale (z-score + baseline stats). */
398
+ reason: string;
399
+ }
400
+ /**
401
+ * Minimal in-memory `QuarantineStore` implementation. Production deployments
402
+ * persist to events.jsonl + a sidecar quarantine state file; the in-memory
403
+ * shape is the contract the persistent implementation honours.
404
+ *
405
+ * The store is intentionally narrow: `quarantine`, `isQuarantined`,
406
+ * `getActiveEntries`, `getEntryByDecisionId`, `release`. No batch
407
+ * operations — operators unquarantine one Decision at a time per the
408
+ * RFC-0023 one-click model.
409
+ */
410
+ export interface QuarantineStore {
411
+ /** Record a new quarantine entry. */
412
+ quarantine(entry: QuarantineEntry): void;
413
+ /** Whether a signal sourceId is currently quarantined (NOT auto-expired). */
414
+ isQuarantined(sourceId: string, asOf?: Date): boolean;
415
+ /**
416
+ * All currently-active quarantine entries (auto-expired entries excluded).
417
+ * Used by the TUI Blockers pane to render pending decisions.
418
+ */
419
+ getActiveEntries(asOf?: Date): QuarantineEntry[];
420
+ /** Entries created by a specific Decision (for unquarantine routing). */
421
+ getEntryByDecisionId(decisionId: string): QuarantineEntry[];
422
+ /** Release all entries for the given Decision (idempotent). */
423
+ release(decisionId: string, releasedAt?: Date): QuarantineEntry[];
424
+ }
425
+ /**
426
+ * Default in-memory store. Tests use this directly; production callers should
427
+ * implement a persistent variant satisfying the same interface.
428
+ */
429
+ export declare class InMemoryQuarantineStore implements QuarantineStore {
430
+ private readonly entries;
431
+ private readonly released;
432
+ quarantine(entry: QuarantineEntry): void;
433
+ isQuarantined(sourceId: string, asOf?: Date): boolean;
434
+ getActiveEntries(asOf?: Date): QuarantineEntry[];
435
+ getEntryByDecisionId(decisionId: string): QuarantineEntry[];
436
+ release(decisionId: string, _releasedAt?: Date): QuarantineEntry[];
437
+ }
438
+ /**
439
+ * Convenience: check whether a single `RawSignal` is currently quarantined by
440
+ * looking up its `sourceId` in the store. The D1 path calls this when
441
+ * computing `eligibleForD1` — quarantined signals are excluded from the
442
+ * D1(cluster) formula per AC #6.
443
+ *
444
+ * Returns `false` when no store is supplied (back-compat — pre-AISDLC-433
445
+ * D1 paths didn't have a quarantine layer to consult).
446
+ */
447
+ export declare function isSignalQuarantined(signal: RawSignal, store: QuarantineStore | undefined, asOf?: Date): boolean;
448
+ /**
449
+ * Operator unquarantine Decision — emitted by `unquarantineFlooded()` per
450
+ * AC #9. References the original flooding Decision so the v2
451
+ * reputation-weighting layer can calibrate against false-positive feedback.
452
+ */
453
+ export interface SignalFloodingFalsePositiveDecision {
454
+ type: 'Decision';
455
+ decision: 'signal-flooding-false-positive';
456
+ /** Stable ID for this false-positive Decision (audit trail). */
457
+ decisionId: string;
458
+ /** Original `signal-flooding-detected` Decision ID. */
459
+ originalDecisionId: string;
460
+ releasedAt: string;
461
+ /** Source IDs released back to D1 candidacy. */
462
+ releasedSourceIds: string[];
463
+ /** Free-form operator note explaining the false-positive call. */
464
+ operatorNote?: string;
465
+ message: string;
466
+ }
467
+ /**
468
+ * Options for `unquarantineFlooded()`.
469
+ */
470
+ export interface UnquarantineFloodedOptions {
471
+ store: QuarantineStore;
472
+ /** Decision ID of the original `signal-flooding-detected` Decision. */
473
+ originalDecisionId: string;
474
+ /** Optional operator note (free-form rationale). */
475
+ operatorNote?: string;
476
+ /** Clock override for the `releasedAt` timestamp. */
477
+ asOf?: Date;
478
+ /** Decision-ID factory for the false-positive Decision (tests override). */
479
+ generateDecisionId?: () => string;
480
+ }
481
+ /**
482
+ * Operator one-click unquarantine — releases every signal entry tagged with
483
+ * `originalDecisionId` and emits the `signal-flooding-false-positive`
484
+ * Decision per RFC-0030 §13.5 + AC #8 + AC #9.
485
+ *
486
+ * Returns `null` when no active entries match the Decision ID (idempotent —
487
+ * the operator's second click on the same row is a no-op + null result).
488
+ */
489
+ export declare function unquarantineFlooded(options: UnquarantineFloodedOptions): SignalFloodingFalsePositiveDecision | null;
490
+ /**
491
+ * Per-adopter regime declaration consumed by `checkSignalResidency`. Composes
492
+ * with RFC-0022 Compliance Posture per RFC-0030 OQ-13.3 — the adopter declares
493
+ * which regimes are active and the allowed regions per regime; signal-ingestion
494
+ * refuses signals from outside those regions.
495
+ *
496
+ * `regimes` is the active regime set (e.g. `['gdpr']`, `['hipaa', 'gdpr']`).
497
+ * `allowedRegionsByRegime` maps each regime to the set of region tags that
498
+ * regime permits (e.g. `gdpr: ['eu', 'gb']`, `hipaa: ['us']`). A signal is
499
+ * permitted IFF its `region` is in EVERY active regime's allowed-regions list.
500
+ *
501
+ * `allowedRegionsByRegime` keys not present in `regimes` are ignored (the
502
+ * regime isn't active for this adopter).
503
+ *
504
+ * `allowedRegionsByRegime` of `{}` (empty) for an active regime means NO
505
+ * regions are explicitly permitted → all signals are refused for that regime.
506
+ * Operators should declare regions OR remove the regime from the active set.
507
+ */
508
+ export interface ResidencyRegimeDeclaration {
509
+ regimes: string[];
510
+ allowedRegionsByRegime: Record<string, string[]>;
511
+ }
512
+ /**
513
+ * Outcome of residency-check on a single signal.
514
+ * - `{ permitted: true }` — signal MAY pass; adapter may emit it.
515
+ * - `{ permitted: false, decision }` — signal MUST be refused; adapter logs
516
+ * the Decision + emits the regimeOverrides clarification task.
517
+ */
518
+ export type SignalResidencyCheck = {
519
+ permitted: true;
520
+ } | {
521
+ permitted: false;
522
+ decision: SignalResidencyViolationDecision;
523
+ };
524
+ /**
525
+ * Check a single signal against the adopter's declared residency regimes.
526
+ *
527
+ * **Behaviour**:
528
+ * - When `declaration.regimes` is empty → signal is permitted (no regime
529
+ * constraints declared). Adopters not declaring a regime are not subject
530
+ * to residency gating.
531
+ * - When `signal.region` is `undefined` AND at least one regime is active →
532
+ * signal is permitted (the adapter didn't surface region metadata, which
533
+ * is treated as "not subject to gating" rather than "fails the gate" to
534
+ * avoid false-positives on adapters that don't yet plumb region — a
535
+ * visible-gap metric for the operator's regime config rollout).
536
+ * - When `signal.region` is present AND at least one active regime's
537
+ * `allowedRegions` does NOT include it → signal is REFUSED and the
538
+ * `Decision` records every regime that rejected the signal.
539
+ *
540
+ * The adapter SHOULD NOT call `fetchSignals` for refused signals — the
541
+ * return-value pattern lets the adapter short-circuit per-signal.
542
+ */
543
+ export declare function checkSignalResidency(signal: RawSignal, declaration: ResidencyRegimeDeclaration, adapterName: SignalSourceName): SignalResidencyCheck;
544
+ /**
545
+ * Convenience wrapper: filter a batch of signals against the residency gate,
546
+ * returning the (possibly empty) list of permitted signals + the list of
547
+ * Decision records for refused signals. Adapter implementations can call this
548
+ * in their `fetchSignals()` body to enforce residency before returning.
549
+ */
550
+ export declare function filterSignalsByResidency(signals: RawSignal[], declaration: ResidencyRegimeDeclaration, adapterName: SignalSourceName): {
551
+ permitted: RawSignal[];
552
+ decisions: SignalResidencyViolationDecision[];
553
+ };
554
+ //# sourceMappingURL=significance.d.ts.map