@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,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signal ingestion source-adapter substrate for RFC-0030 Phase 1.
|
|
3
|
+
*
|
|
4
|
+
* Source adapters fetch raw demand signals from external systems while keeping
|
|
5
|
+
* classification, clustering, and scoring out of this layer.
|
|
6
|
+
*/
|
|
7
|
+
export type SignalSourceName = 'signal-source-support-ticket' | 'signal-source-community-thread' | 'signal-source-in-app-feedback' | 'signal-source-manual' | (string & {});
|
|
8
|
+
export type SignalTier = 1 | 2;
|
|
9
|
+
export type CustomerTier = 'enterprise' | 'mid' | 'smb' | 'free' | 'churned';
|
|
10
|
+
export interface RawSignal {
|
|
11
|
+
/** Stable identifier in the source system, e.g. zendesk-ticket-12345. */
|
|
12
|
+
sourceId: string;
|
|
13
|
+
/** Original source timestamp. */
|
|
14
|
+
sourceTimestamp: Date;
|
|
15
|
+
/** Optional customer/account identifier supplied by the source. */
|
|
16
|
+
customerId?: string;
|
|
17
|
+
/** Optional structured tier supplied by the source. */
|
|
18
|
+
customerTier?: CustomerTier;
|
|
19
|
+
/** Free-text signal body. */
|
|
20
|
+
payload: string;
|
|
21
|
+
/** Source-specific structured metadata. */
|
|
22
|
+
metadata?: Record<string, unknown>;
|
|
23
|
+
/** Required for manual signals per RFC-0030 OQ-13.4. */
|
|
24
|
+
attestedBy?: string;
|
|
25
|
+
/** Auto-filled for manual signals when omitted. */
|
|
26
|
+
attestedAt?: Date;
|
|
27
|
+
/**
|
|
28
|
+
* Optional ISO-3166 country code or compliance region tag for the signal's
|
|
29
|
+
* origin (e.g. 'eu', 'us-east', 'gb', 'apac', 'us'). Consumed by the
|
|
30
|
+
* Phase 4 residency-violation gate per RFC-0030 OQ-13.3: when the adopter
|
|
31
|
+
* has a declared regime constraint (via RFC-0022 compliance posture) that
|
|
32
|
+
* requires data residency in a specific region, signals from outside the
|
|
33
|
+
* allowed region(s) are refused and emitted as
|
|
34
|
+
* `Decision: signal-residency-violation`. When undefined, the residency
|
|
35
|
+
* gate skips this signal (no false positives on adapters that don't surface
|
|
36
|
+
* region metadata).
|
|
37
|
+
*/
|
|
38
|
+
region?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Optional evidence link for manual signals per RFC-0030 OQ-13.4 v0.3
|
|
41
|
+
* re-walkthrough. When present (call recording URL, ticket URL, transcript
|
|
42
|
+
* link), the audit trail is materially stronger. When absent, the attested
|
|
43
|
+
* observation stands but is flagged in the manual-share quality metric.
|
|
44
|
+
*
|
|
45
|
+
* The pipeline preserves this field through classification + clustering +
|
|
46
|
+
* D1 aggregation so it remains visible in the audit export.
|
|
47
|
+
*/
|
|
48
|
+
evidenceUrl?: string;
|
|
49
|
+
}
|
|
50
|
+
export interface SignalSourceAdapter {
|
|
51
|
+
readonly name: SignalSourceName;
|
|
52
|
+
readonly defaultTier: SignalTier;
|
|
53
|
+
/**
|
|
54
|
+
* RFC-0030 OQ-13.1 v0.3 re-walkthrough: when `true`, this adapter requires
|
|
55
|
+
* OAuth credential management (refresh tokens, scopes) which is deferred to
|
|
56
|
+
* a future credential-management RFC. The Phase 1 registry refuses to fetch
|
|
57
|
+
* from such adapters and emits `Decision: adapter-requires-credential-mgmt-rfc`.
|
|
58
|
+
*
|
|
59
|
+
* Defaults to `false` (undefined → false) — all v1-shipped adapters MUST be
|
|
60
|
+
* env-var-based.
|
|
61
|
+
*/
|
|
62
|
+
readonly requiresOAuth?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Adapter self-validation. Credential lifecycle is intentionally deferred to
|
|
65
|
+
* a future RFC; Phase 1 only reports whether this adapter can be used.
|
|
66
|
+
*/
|
|
67
|
+
isAvailable(): Promise<boolean>;
|
|
68
|
+
/** Fetch immutable signals from the source since the provided timestamp. */
|
|
69
|
+
fetchSignals(since: Date): Promise<RawSignal[]>;
|
|
70
|
+
}
|
|
71
|
+
export interface AdapterCredentialInvalidDecision {
|
|
72
|
+
type: 'Decision';
|
|
73
|
+
decision: 'adapter-credential-invalid';
|
|
74
|
+
adapter: SignalSourceName;
|
|
75
|
+
message: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* RFC-0030 OQ-13.1 v0.3 re-walkthrough: emitted when an adapter's required
|
|
79
|
+
* credential env var is missing or empty. Downstream auto-action: emit a
|
|
80
|
+
* SETUP task asking the operator to set the env var. Pipeline continues with
|
|
81
|
+
* remaining valid adapters.
|
|
82
|
+
*
|
|
83
|
+
* Distinct from `AdapterCredentialRejectedDecision` (env var present but
|
|
84
|
+
* upstream auth call failed). Two distinct operator actions: SETUP vs.
|
|
85
|
+
* ROTATION. v0.2's collapsed `adapter-credential-invalid` is preserved for
|
|
86
|
+
* backward compat — adapters that don't yet probe env vars surface the
|
|
87
|
+
* legacy Decision.
|
|
88
|
+
*/
|
|
89
|
+
export interface AdapterCredentialNotConfiguredDecision {
|
|
90
|
+
type: 'Decision';
|
|
91
|
+
decision: 'adapter-credential-not-configured';
|
|
92
|
+
adapter: SignalSourceName;
|
|
93
|
+
envVarName: string;
|
|
94
|
+
message: string;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* RFC-0030 OQ-13.1 v0.3 re-walkthrough: emitted when an adapter has the
|
|
98
|
+
* credential env var present BUT the upstream service rejected the auth call
|
|
99
|
+
* (401 / 403). Downstream auto-action: emit a ROTATION task asking the
|
|
100
|
+
* operator to rotate / re-generate the credential. Pipeline continues with
|
|
101
|
+
* remaining valid adapters.
|
|
102
|
+
*/
|
|
103
|
+
export interface AdapterCredentialRejectedDecision {
|
|
104
|
+
type: 'Decision';
|
|
105
|
+
decision: 'adapter-credential-rejected';
|
|
106
|
+
adapter: SignalSourceName;
|
|
107
|
+
message: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* RFC-0030 OQ-13.1 v0.3 re-walkthrough: emitted when an adapter declares
|
|
111
|
+
* `requiresOAuth = true`. Phase 1 ships ENV-VAR-ONLY adapters; OAuth lifecycle
|
|
112
|
+
* (refresh tokens, scopes) is a substantial separate concern deferred to a
|
|
113
|
+
* future credential-management RFC. The registry refuses such adapters and
|
|
114
|
+
* surfaces this Decision; pipeline continues with the env-var-based adapters.
|
|
115
|
+
*/
|
|
116
|
+
export interface AdapterRequiresCredentialMgmtRfcDecision {
|
|
117
|
+
type: 'Decision';
|
|
118
|
+
decision: 'adapter-requires-credential-mgmt-rfc';
|
|
119
|
+
adapter: SignalSourceName;
|
|
120
|
+
message: string;
|
|
121
|
+
}
|
|
122
|
+
export interface ManualSignalIncompleteDecision {
|
|
123
|
+
type: 'Decision';
|
|
124
|
+
decision: 'manual-signal-incomplete';
|
|
125
|
+
adapter: 'signal-source-manual';
|
|
126
|
+
sourceId?: string;
|
|
127
|
+
message: string;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* RFC-0030 OQ-13.4 v0.3 re-walkthrough: emitted when a manual signal entry
|
|
131
|
+
* would exceed the per-operator daily cap (default 10/day, configurable via
|
|
132
|
+
* `manualEntry.dailyCapPerOperator`). Downstream auto-action: surface a
|
|
133
|
+
* batch-review escalation task. The signal is REFUSED (not silently dropped)
|
|
134
|
+
* so the operator sees the rejection and can escalate legitimately.
|
|
135
|
+
*/
|
|
136
|
+
export interface ManualSignalRateLimitExceededDecision {
|
|
137
|
+
type: 'Decision';
|
|
138
|
+
decision: 'manual-signal-rate-limit-exceeded';
|
|
139
|
+
adapter: 'signal-source-manual';
|
|
140
|
+
attestedBy: string;
|
|
141
|
+
/** UTC ISO date (YYYY-MM-DD) of the bucket that overflowed. */
|
|
142
|
+
utcDate: string;
|
|
143
|
+
dailyCap: number;
|
|
144
|
+
sourceId?: string;
|
|
145
|
+
message: string;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* RFC-0030 OQ-13.4 v0.3 re-walkthrough: emitted when the rolling
|
|
149
|
+
* manual/total share metric exceeds the configured threshold (default 30%
|
|
150
|
+
* over a 7-day window). Architectural anti-pattern warning, NOT a block —
|
|
151
|
+
* surfaces that the pipeline is acting as a data-entry tool rather than
|
|
152
|
+
* automated demand-detection. Pipeline continues normally.
|
|
153
|
+
*/
|
|
154
|
+
export interface ManualSignalShareElevatedDecision {
|
|
155
|
+
type: 'Decision';
|
|
156
|
+
decision: 'manual-signal-share-elevated';
|
|
157
|
+
/** Computed manual/total ratio over the window. */
|
|
158
|
+
manualShare: number;
|
|
159
|
+
/** Threshold that was exceeded (config: `manualEntry.qualityMetric.shareWarningThreshold`). */
|
|
160
|
+
threshold: number;
|
|
161
|
+
windowDays: number;
|
|
162
|
+
manualSignals: number;
|
|
163
|
+
totalSignals: number;
|
|
164
|
+
message: string;
|
|
165
|
+
}
|
|
166
|
+
export interface SignalFetchResult {
|
|
167
|
+
signals: RawSignal[];
|
|
168
|
+
decisions: Array<AdapterCredentialInvalidDecision | AdapterCredentialNotConfiguredDecision | AdapterCredentialRejectedDecision | AdapterRequiresCredentialMgmtRfcDecision | ManualSignalIncompleteDecision | ManualSignalRateLimitExceededDecision | SignalResidencyViolationDecision>;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Emitted at adapter level when a signal's `region` doesn't match the adopter's
|
|
172
|
+
* declared regime constraints per RFC-0030 OQ-13.3 (composes with RFC-0022
|
|
173
|
+
* Compliance Posture). Adapter response: refuse the signal + log the Decision +
|
|
174
|
+
* emit a `compliance.yaml regimeOverrides` clarification task. Pipeline does
|
|
175
|
+
* NOT halt — the catalog absorbs the violation (G0 non-blocking pipeline contract
|
|
176
|
+
* per RFC-0035).
|
|
177
|
+
*/
|
|
178
|
+
export interface SignalResidencyViolationDecision {
|
|
179
|
+
type: 'Decision';
|
|
180
|
+
decision: 'signal-residency-violation';
|
|
181
|
+
adapter: SignalSourceName;
|
|
182
|
+
sourceId: string;
|
|
183
|
+
/** The region the signal claimed (or 'unknown' when region metadata absent). */
|
|
184
|
+
signalRegion: string;
|
|
185
|
+
/** Regime IDs (e.g. 'gdpr', 'hipaa') whose residency constraints were violated. */
|
|
186
|
+
violatedRegimes: string[];
|
|
187
|
+
/** Allowed regions per the adopter's regime declaration. */
|
|
188
|
+
allowedRegions: string[];
|
|
189
|
+
message: string;
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signal ingestion source-adapter substrate for RFC-0030 Phase 1.
|
|
3
|
+
*
|
|
4
|
+
* Source adapters fetch raw demand signals from external systems while keeping
|
|
5
|
+
* classification, clustering, and scoring out of this layer.
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC-0028 §7.2 — structural + statistical drift composition.
|
|
3
|
+
*
|
|
4
|
+
* Phase 3 of RFC-0028 §7.2 v0.2 resolution. Wires the canonical pairing of
|
|
5
|
+
* the two drift-detection layers with the explicit composition rules the
|
|
6
|
+
* operator resolved on 2026-05-27:
|
|
7
|
+
*
|
|
8
|
+
* 1. **Structural drift (CI authoring-time) REJECTS deployment.** The
|
|
9
|
+
* type-registry CI gate (`scripts/check-substrate-contract.mjs`,
|
|
10
|
+
* AISDLC-453) is the hard gate. When any of its 5 assertions fail it emits
|
|
11
|
+
* `Decision: substrate-structural-drift-detected` (severity HIGH) and
|
|
12
|
+
* blocks PR merge via a non-zero exit code. This module does NOT rebuild
|
|
13
|
+
* that gate — it *represents* its outcome so the two layers can be
|
|
14
|
+
* composed and correlated. {@link toStructuralDriftEvents} maps the gate's
|
|
15
|
+
* result into the composition model.
|
|
16
|
+
*
|
|
17
|
+
* 2. **Statistical drift (runtime) SURFACES to operator (RFC-0035 G0
|
|
18
|
+
* non-blocking).** PPA's `SoulDriftDetected` signal (rolling 30-day mean
|
|
19
|
+
* < 0.4 or stddev > 0.15 sustained for 3 sprints) routes to
|
|
20
|
+
* `Decision: soul-statistical-drift-detected` → operator batch review with
|
|
21
|
+
* three reconciliation paths. The pipeline NEVER halts on statistical
|
|
22
|
+
* drift. {@link evaluateStatisticalDrift} computes the signal;
|
|
23
|
+
* {@link composeDrift} routes the firing signal to the catalog request.
|
|
24
|
+
*
|
|
25
|
+
* 3. **Both Decisions composable in the catalog.** Both classes carry a
|
|
26
|
+
* `soulId` + a stable `driftClass` discriminant and share one catalog
|
|
27
|
+
* scope ({@link DRIFT_DECISION_SCOPE}) so an operator can query
|
|
28
|
+
* "show me all drift events for Soul X" and get structural (rejected at
|
|
29
|
+
* CI) and statistical (caught at runtime) events side-by-side —
|
|
30
|
+
* {@link correlateDriftBySoul}.
|
|
31
|
+
*
|
|
32
|
+
* 4. **Cold-start handling.** Statistical detection needs a rolling 30d
|
|
33
|
+
* baseline. Pre-baseline (< 30d of signal), the detector returns a
|
|
34
|
+
* `calibrating` status and emits NO statistical Decisions — structural
|
|
35
|
+
* detection is the sole defense during the calibration window. The
|
|
36
|
+
* cold-start shape mirrors RFC-0030 §13 OQ-13.5's z-score flooding
|
|
37
|
+
* detector (calibrating until the rolling window fills, then active).
|
|
38
|
+
*
|
|
39
|
+
* **AC-8 — no parallel event emitter.** This module does NOT import or write
|
|
40
|
+
* to the catalog event log directly. Mirroring the Phase 1 `identity-class.ts`
|
|
41
|
+
* audit and the Phase 2 `check-substrate-contract.mjs` gate, it produces
|
|
42
|
+
* `DriftDecisionRequest` payloads (summary + scope + source + options) that
|
|
43
|
+
* the *caller* forwards to the existing RFC-0035 substrate via
|
|
44
|
+
* `node pipeline-cli/bin/cli-decisions.mjs add` (or `makeDecisionOpenedEvent`
|
|
45
|
+
* + `appendDecisionEvent` in-process). The request shape is byte-compatible
|
|
46
|
+
* with `cli-decisions add --summary … --scope … --option id:desc`. This keeps
|
|
47
|
+
* the orchestrator package free of a build-time dependency on
|
|
48
|
+
* `@ai-sdlc/pipeline-cli`'s dist output and avoids a second emitter.
|
|
49
|
+
*
|
|
50
|
+
* @see spec/rfcs/RFC-0028-engineering-axis-substrate-enforcement.md §7.2
|
|
51
|
+
* @see spec/rfcs/RFC-0035-decision-catalog-operator-routing.md (G0 routing)
|
|
52
|
+
* @see scripts/check-substrate-contract.mjs (the structural layer, AISDLC-453)
|
|
53
|
+
* @module substrate/drift-composition
|
|
54
|
+
*/
|
|
55
|
+
/**
|
|
56
|
+
* The two canonical drift classes per RFC-0028 §7.2. The discriminant is
|
|
57
|
+
* stable so the catalog can correlate both classes for a single Soul DID.
|
|
58
|
+
*/
|
|
59
|
+
export type DriftClass = 'structural' | 'statistical';
|
|
60
|
+
/**
|
|
61
|
+
* The RFC-0035 Decision scope used for every drift Decision. Both classes
|
|
62
|
+
* share one scope so `cli-decisions list --scope substrate-drift` returns
|
|
63
|
+
* the composed view (AC-3 / AC-5).
|
|
64
|
+
*/
|
|
65
|
+
export declare const DRIFT_DECISION_SCOPE = "substrate-drift";
|
|
66
|
+
/** Decision summary slug for structural drift (matches AISDLC-453 gate). */
|
|
67
|
+
export declare const STRUCTURAL_DECISION_SLUG = "substrate-structural-drift-detected";
|
|
68
|
+
/** Decision summary slug for statistical drift (RFC-0028 §7.2 rule 2). */
|
|
69
|
+
export declare const STATISTICAL_DECISION_SLUG = "soul-statistical-drift-detected";
|
|
70
|
+
/**
|
|
71
|
+
* Statistical-drift detection thresholds, frozen from RFC-0028 §7.2 / PPA's
|
|
72
|
+
* `SoulDriftDetected` definition. A drift fires when the rolling 30-day mean
|
|
73
|
+
* drops below {@link MEAN_FLOOR} OR the rolling stddev exceeds
|
|
74
|
+
* {@link STDDEV_CEILING}, sustained for {@link SUSTAINED_SPRINTS} sprints.
|
|
75
|
+
*/
|
|
76
|
+
export declare const MEAN_FLOOR = 0.4;
|
|
77
|
+
export declare const STDDEV_CEILING = 0.15;
|
|
78
|
+
export declare const SUSTAINED_SPRINTS = 3;
|
|
79
|
+
/** Rolling baseline window in days (RFC-0028 §7.2 cold-start: 30d). */
|
|
80
|
+
export declare const BASELINE_WINDOW_DAYS = 30;
|
|
81
|
+
/**
|
|
82
|
+
* One Decision-option choice the operator picks from. Mirrors the
|
|
83
|
+
* RFC-0035 `DecisionOption` shape (`pipeline-cli/src/decisions/decision-record.ts`)
|
|
84
|
+
* without importing it — kept structurally identical so a caller can spread
|
|
85
|
+
* these directly into `makeDecisionOpenedEvent({ options })` or render them as
|
|
86
|
+
* `--option <id>:<description>` flags for `cli-decisions add`.
|
|
87
|
+
*/
|
|
88
|
+
export interface DriftDecisionOption {
|
|
89
|
+
id: string;
|
|
90
|
+
description: string;
|
|
91
|
+
consequences?: string[];
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* A ready-to-file Decision request. The caller forwards this to the RFC-0035
|
|
95
|
+
* catalog (CLI or in-process). The field names match the catalog's
|
|
96
|
+
* `OpenDecisionInput` so no translation layer is needed.
|
|
97
|
+
*/
|
|
98
|
+
export interface DriftDecisionRequest {
|
|
99
|
+
/** RFC-0035 Decision source. Structural=emergent-finding; statistical=framework-calibration. */
|
|
100
|
+
source: 'emergent-finding' | 'framework-calibration';
|
|
101
|
+
scope: string;
|
|
102
|
+
summary: string;
|
|
103
|
+
body?: string;
|
|
104
|
+
/** Statistical drift is reversible (G0 non-blocking); structural is a hard gate. */
|
|
105
|
+
reversible: boolean;
|
|
106
|
+
options: DriftDecisionOption[];
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* A drift event in the composition model — the side-by-side unit an operator
|
|
110
|
+
* sees. Both structural and statistical events project to this shape so the
|
|
111
|
+
* TUI / catalog can render them together.
|
|
112
|
+
*/
|
|
113
|
+
export interface DriftEvent {
|
|
114
|
+
driftClass: DriftClass;
|
|
115
|
+
/** Soul DID the drift applies to. */
|
|
116
|
+
soulId: string;
|
|
117
|
+
/**
|
|
118
|
+
* Structural = HIGH (hard gate). Statistical = advisory (non-blocking, G0).
|
|
119
|
+
*/
|
|
120
|
+
severity: 'high' | 'advisory';
|
|
121
|
+
/** Whether this drift class blocks deployment. Structural=true always. */
|
|
122
|
+
blocking: boolean;
|
|
123
|
+
/** One-line operator-facing summary (used as the Decision summary). */
|
|
124
|
+
summary: string;
|
|
125
|
+
/** Free-form detail body for the Decision. */
|
|
126
|
+
detail?: string;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* The three (and only three) operator reconciliation paths for a
|
|
130
|
+
* `soul-statistical-drift-detected` Decision, per RFC-0028 §7.2:
|
|
131
|
+
*
|
|
132
|
+
* (a) confirm drift as legitimate evolution → emit DID amendment
|
|
133
|
+
* (b) confirm drift as substrate violation → file fix task
|
|
134
|
+
* (c) defer for the next operator review window
|
|
135
|
+
*/
|
|
136
|
+
export declare const STATISTICAL_RECONCILIATION_OPTIONS: readonly DriftDecisionOption[];
|
|
137
|
+
/** Structural-drift reconciliation options mirror the AISDLC-453 CI gate. */
|
|
138
|
+
export declare const STRUCTURAL_RECONCILIATION_OPTIONS: readonly DriftDecisionOption[];
|
|
139
|
+
/**
|
|
140
|
+
* The relevant subset of the structural gate's failure record
|
|
141
|
+
* (`scripts/check-substrate-contract.mjs#AssertionResult`). Re-declared here
|
|
142
|
+
* as a structural type so this module does not import the `.mjs` CI script
|
|
143
|
+
* (which lives outside the orchestrator build graph) — callers pass the
|
|
144
|
+
* gate's result through.
|
|
145
|
+
*/
|
|
146
|
+
export interface StructuralGateFailure {
|
|
147
|
+
soulId: string;
|
|
148
|
+
message: string;
|
|
149
|
+
/** The gate's pre-formatted Decision summary, when present. */
|
|
150
|
+
decisionSummary?: string;
|
|
151
|
+
}
|
|
152
|
+
export interface StructuralGateResult {
|
|
153
|
+
/** True when the gate passed (no structural drift). */
|
|
154
|
+
passed: boolean;
|
|
155
|
+
/** True when no contracts exist (cold-start no-op). */
|
|
156
|
+
coldStart: boolean;
|
|
157
|
+
failures: StructuralGateFailure[];
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Project the structural CI gate's result into composition `DriftEvent`s.
|
|
161
|
+
*
|
|
162
|
+
* One `DriftEvent` per gate failure. Always `blocking: true` / severity
|
|
163
|
+
* `high` — structural drift is the hard gate (RFC-0028 §7.2 rule 1). Returns
|
|
164
|
+
* `[]` when the gate passed or was a cold-start no-op (no contracts).
|
|
165
|
+
*/
|
|
166
|
+
export declare function toStructuralDriftEvents(result: StructuralGateResult): DriftEvent[];
|
|
167
|
+
/**
|
|
168
|
+
* A single dated drift-metric sample for one Soul DID. `value` is the PPA
|
|
169
|
+
* soul-coherence metric in [0, 1]; `at` is the sample timestamp.
|
|
170
|
+
*/
|
|
171
|
+
export interface SoulDriftSample {
|
|
172
|
+
/** ISO-8601 timestamp (or any Date-parseable string). */
|
|
173
|
+
at: string;
|
|
174
|
+
/** Coherence metric in [0, 1]; lower = more drift. */
|
|
175
|
+
value: number;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* The detector's status. `calibrating` = pre-baseline (< 30d of signal); the
|
|
179
|
+
* detector emits NO statistical Decisions in this state (cold-start, AC-4).
|
|
180
|
+
* `active` = baseline accumulated; drift may fire.
|
|
181
|
+
*/
|
|
182
|
+
export type StatisticalDriftStatus = 'calibrating' | 'active';
|
|
183
|
+
export interface StatisticalDriftResult {
|
|
184
|
+
status: StatisticalDriftStatus;
|
|
185
|
+
/** True only when status is `active` AND the drift condition is met. */
|
|
186
|
+
drifted: boolean;
|
|
187
|
+
/** Rolling mean over the baseline window (null while calibrating). */
|
|
188
|
+
rollingMean: number | null;
|
|
189
|
+
/** Rolling population stddev over the window (null while calibrating). */
|
|
190
|
+
rollingStdDev: number | null;
|
|
191
|
+
/** Consecutive sprints the drift condition has held (active state). */
|
|
192
|
+
sustainedSprints: number;
|
|
193
|
+
/** Human-readable reason — used for the Decision detail when drifted. */
|
|
194
|
+
reason: string;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Evaluate statistical drift for one Soul DID over its metric history.
|
|
198
|
+
*
|
|
199
|
+
* Cold-start (AC-4): if the span between the earliest sample and `now` is
|
|
200
|
+
* shorter than {@link BASELINE_WINDOW_DAYS}, the detector is still
|
|
201
|
+
* `calibrating` — it returns `drifted: false` with null statistics and the
|
|
202
|
+
* caller emits no Decision. Structural detection (AISDLC-453) is the sole
|
|
203
|
+
* defense during this window.
|
|
204
|
+
*
|
|
205
|
+
* Once the window is filled the detector is `active`: drift fires when the
|
|
206
|
+
* rolling mean < {@link MEAN_FLOOR} OR the rolling stddev >
|
|
207
|
+
* {@link STDDEV_CEILING}, AND that condition has held for at least
|
|
208
|
+
* {@link SUSTAINED_SPRINTS} consecutive sprint buckets.
|
|
209
|
+
*
|
|
210
|
+
* The cold-start shape mirrors RFC-0030 §13 OQ-13.5's z-score flooding
|
|
211
|
+
* detector (calibrating until the window accumulates, then active).
|
|
212
|
+
*
|
|
213
|
+
* @param samples Metric history (any order). Empty → calibrating.
|
|
214
|
+
* @param sprintFlags Per-sprint booleans (most-recent last) indicating
|
|
215
|
+
* whether the drift condition held in each sprint; used to enforce the
|
|
216
|
+
* "3 sustained sprints" rule independent of raw sample cadence. When
|
|
217
|
+
* omitted, sustained-sprint accounting falls back to whether the current
|
|
218
|
+
* window meets the condition (counts as 1 sprint, so a single-window
|
|
219
|
+
* breach is reported but does not satisfy the 3-sprint rule).
|
|
220
|
+
* @param now Clock override for deterministic tests.
|
|
221
|
+
*/
|
|
222
|
+
export declare function evaluateStatisticalDrift(samples: SoulDriftSample[], sprintFlags?: boolean[], now?: Date): StatisticalDriftResult;
|
|
223
|
+
/**
|
|
224
|
+
* Project an `active` + `drifted` statistical result into a composition
|
|
225
|
+
* `DriftEvent`. Returns `null` while calibrating or not drifted — there is
|
|
226
|
+
* nothing to surface to the operator (AC-4: no statistical Decisions during
|
|
227
|
+
* cold-start).
|
|
228
|
+
*/
|
|
229
|
+
export declare function toStatisticalDriftEvent(soulId: string, result: StatisticalDriftResult): DriftEvent | null;
|
|
230
|
+
export interface ComposeDriftResult {
|
|
231
|
+
/** All composed drift events (structural + statistical), side-by-side. */
|
|
232
|
+
events: DriftEvent[];
|
|
233
|
+
/**
|
|
234
|
+
* Ready-to-file Decision requests, one per surfaced/blocked event, in the
|
|
235
|
+
* same order as `events`. The caller forwards each to the RFC-0035 catalog
|
|
236
|
+
* (`cli-decisions add` / `makeDecisionOpenedEvent`) — this module does NOT
|
|
237
|
+
* write the event log itself (AC-8).
|
|
238
|
+
*/
|
|
239
|
+
requests: DriftDecisionRequest[];
|
|
240
|
+
/** True if any structural (blocking) drift is present — the CI hard gate. */
|
|
241
|
+
blocked: boolean;
|
|
242
|
+
}
|
|
243
|
+
/** Build the catalog request for one composed drift event. */
|
|
244
|
+
export declare function toDecisionRequest(event: DriftEvent): DriftDecisionRequest;
|
|
245
|
+
/**
|
|
246
|
+
* Compose the structural gate outcome with a set of statistical results.
|
|
247
|
+
*
|
|
248
|
+
* - Structural events → `substrate-structural-drift-detected` (HIGH,
|
|
249
|
+
* blocking). Represented from the CI gate result; the gate itself already
|
|
250
|
+
* emits + blocks at CI time (AISDLC-453), so the catalog request here is the
|
|
251
|
+
* composition/audit projection (so structural + statistical sit
|
|
252
|
+
* side-by-side in one scope).
|
|
253
|
+
* - Statistical drifted events → `soul-statistical-drift-detected`
|
|
254
|
+
* (advisory, non-blocking, G0) with the three reconciliation options.
|
|
255
|
+
* - Calibrating / non-drifted statistical results emit NO request (AC-4).
|
|
256
|
+
*
|
|
257
|
+
* The pipeline never halts here: `blocked` reports the structural hard-gate
|
|
258
|
+
* state for the CI caller to act on, but statistical drift never sets it.
|
|
259
|
+
*/
|
|
260
|
+
export declare function composeDrift(structural: StructuralGateResult, statistical: Array<{
|
|
261
|
+
soulId: string;
|
|
262
|
+
result: StatisticalDriftResult;
|
|
263
|
+
}>): ComposeDriftResult;
|
|
264
|
+
/**
|
|
265
|
+
* Group composed drift events by Soul DID so an operator can query
|
|
266
|
+
* "show me all drift events for Soul X" and get both classes side-by-side.
|
|
267
|
+
* Returns a map keyed by `soulId` whose values preserve event order.
|
|
268
|
+
*/
|
|
269
|
+
export declare function correlateDriftBySoul(events: DriftEvent[]): Map<string, DriftEvent[]>;
|
|
270
|
+
//# sourceMappingURL=drift-composition.d.ts.map
|