@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
@@ -11,6 +11,7 @@
11
11
  * 3. The branch-protection helper (applyBranchProtection) including the
12
12
  * `--dry-run` JSON-print path required by AC #6.
13
13
  * 4. The "next steps" summary printed at the end of init (AC #5).
14
+ * 5. The compliance-posture wizard step (RFC-0022 §7 / AISDLC-324).
14
15
  *
15
16
  * Test surface: every public function takes a small options bag with
16
17
  * injectable side-effect adapters (prompter, writeFile, runCommand) so the
@@ -18,16 +19,204 @@
18
19
  * up a TTY or shelling out to `gh`. Production callers in `init.ts` pass
19
20
  * the real adapters.
20
21
  */
22
+ import type { DerivedGates } from '../../compliance/types.js';
23
+ /**
24
+ * A single regulatory regime option shown in the init wizard multi-select.
25
+ */
26
+ export interface ComplianceRegimeChoice {
27
+ /** Canonical regime identifier (e.g. 'HIPAA', 'SOC2-T2'). */
28
+ value: string;
29
+ /** Human-readable label shown in the prompt. */
30
+ label: string;
31
+ }
32
+ /**
33
+ * Canonical list of regulatory regimes presented in the compliance wizard.
34
+ * Mirrors the entries in spec/compliance/regime-mappings.yaml.
35
+ */
36
+ export declare const COMPLIANCE_REGIME_CHOICES: readonly ComplianceRegimeChoice[];
37
+ /**
38
+ * Compute DerivedGates from a list of regime IDs using tightest-wins semantics.
39
+ * Unknown regime IDs are skipped (the wizard's informational display degrades
40
+ * gracefully rather than throwing).
41
+ *
42
+ * This is a lightweight inline computation used exclusively by the init wizard.
43
+ * The canonical composer (orchestrator/src/compliance/composer.ts) is used for
44
+ * all post-init runtime gate resolution.
45
+ */
46
+ export declare function computeInitWizardDerivedGates(regimes: string[]): DerivedGates;
47
+ /**
48
+ * RFC-0009 §8.7 enumerates THREE triggers under which the framework's
49
+ * `shared-with-rls` default for `DatabaseBranchPool` is INSUFFICIENT and the
50
+ * operator MUST upgrade to a per-soul (`per-shard`) pool:
51
+ *
52
+ * 1. **Regulatory hard requirement** — HIPAA / PCI-DSS L1 / FedRAMP /
53
+ * SOC2-with-physical-isolation / regional data residency. The compliance
54
+ * posture wizard already drives this trigger via `INIT_WIZARD_REGIME_GATES`
55
+ * (regimes → `databaseBranchPool: 'per-shard'` on `DerivedGates`).
56
+ *
57
+ * 2. **Customer contract** — a vendor agreement explicitly requires tenant
58
+ * physical isolation, independent of regulatory baseline. Adopter-declared
59
+ * during `init`; not derivable from RFC-0022.
60
+ *
61
+ * 3. **Operator security review** — an explicit risk identified during
62
+ * operator security review that RLS cannot mitigate (side-channel,
63
+ * supply-chain, regulator pre-approval gap). Adopter-declared during
64
+ * `init`; not derivable from RFC-0022.
65
+ *
66
+ * If ANY trigger fires → per-soul pool is required. Triggers 2 + 3 are
67
+ * opt-in answers the init wizard collects directly; trigger 1 is computed
68
+ * from declared regimes upstream.
69
+ *
70
+ * Per RFC-0009 OQ-11 resolution (2026-05-04): the framework cannot
71
+ * auto-detect triggers 2 and 3 — the operator declares them via the wizard
72
+ * checklist.
73
+ */
74
+ export type Oq11TriggerKind = 'regulatory' | 'customer-contract' | 'operator-security-review';
75
+ /**
76
+ * Adopter-declared answers for triggers 2 + 3 of the §8.7 checklist.
77
+ * Trigger 1 (regulatory) is sourced from declared regimes, not from this bag.
78
+ */
79
+ export interface Oq11TriggerAnswers {
80
+ /** Trigger 2 — customer contract requires tenant physical isolation. */
81
+ customerContract: boolean;
82
+ /** Trigger 3 — operator security review identified a risk RLS cannot mitigate. */
83
+ operatorSecurityReview: boolean;
84
+ }
85
+ /**
86
+ * Result of applying the OQ-11 trigger checklist on top of regime-derived gates.
87
+ */
88
+ export interface Oq11TriggerChecklistResult {
89
+ /** The (possibly upgraded) DerivedGates. `databaseBranchPool` is `per-shard` when any trigger fires. */
90
+ derivedGates: DerivedGates;
91
+ /** Names of the triggers that fired (empty when none fire — shared-with-rls remains). */
92
+ triggers: Oq11TriggerKind[];
93
+ }
94
+ /**
95
+ * Apply the RFC-0009 §8.7 / OQ-11 trigger checklist on top of regime-derived
96
+ * `DerivedGates`. Upgrades `databaseBranchPool` from `shared-with-rls` to
97
+ * `per-shard` when ANY of the three triggers fires:
98
+ *
99
+ * - Regulatory: already reflected in `inputGates.databaseBranchPool === 'per-shard'`
100
+ * (set by `computeInitWizardDerivedGates` when a per-shard-forcing regime was
101
+ * declared). When this is the case, 'regulatory' is recorded in `triggers`.
102
+ * - Customer contract: `answers.customerContract === true`.
103
+ * - Operator security review: `answers.operatorSecurityReview === true`.
104
+ *
105
+ * The function is monotonic — once `databaseBranchPool` is `per-shard`, it stays
106
+ * `per-shard`. Other DerivedGates fields are passed through unchanged.
107
+ *
108
+ * Pure function — no I/O, no side-effects. The wizard wires it into
109
+ * `runComplianceStep`; tests pin behavior directly.
110
+ */
111
+ export declare function applyOq11TriggerChecklistUpgrade(inputGates: DerivedGates, answers: Oq11TriggerAnswers): Oq11TriggerChecklistResult;
112
+ /**
113
+ * Human-readable line for each trigger kind, shown in the wizard summary so
114
+ * the operator can see WHY the framework selected `per-shard`.
115
+ */
116
+ export declare function describeOq11Trigger(kind: Oq11TriggerKind): string;
117
+ /**
118
+ * Result of the compliance posture wizard step.
119
+ */
120
+ export interface ComplianceStepResult {
121
+ /** Regime IDs declared by the operator (empty = "(none declared)" baseline). */
122
+ regimes: string[];
123
+ /** Who attested the regimes apply. Auto-filled from git config user.email. */
124
+ attestedBy: string;
125
+ /** ISO-8601 timestamp of attestation. Auto-filled at wizard run time. */
126
+ attestedAt: string;
127
+ /** Optional operator rationale for the attestation. */
128
+ attestedNotes?: string;
129
+ /** Derived gate values computed from the declared regimes (+ §8.7 trigger upgrade). */
130
+ derivedGates: DerivedGates;
131
+ /**
132
+ * Triggers from the RFC-0009 §8.7 / OQ-11 checklist that fired during this
133
+ * wizard run (empty when none fired — shared-with-rls is sufficient).
134
+ */
135
+ oq11Triggers: Oq11TriggerKind[];
136
+ /** Absolute path of the written compliance.yaml file. */
137
+ yamlPath: string;
138
+ /** True if compliance.yaml was written; false in dry-run or if already exists. */
139
+ written: boolean;
140
+ }
141
+ /**
142
+ * Build the .ai-sdlc/compliance.yaml content for a given compliance declaration.
143
+ *
144
+ * The written file contains the declared `spec.regimes` with attestation metadata.
145
+ * The computed `derivedGates` are added as YAML comments (read-only reference)
146
+ * so the loader continues to compute them from regimes (not from spec.derivedGates,
147
+ * which is the operator-override field requiring _notes for each entry).
148
+ *
149
+ * Pure function — no filesystem side-effects, fully testable.
150
+ */
151
+ export declare function buildComplianceYaml(opts: {
152
+ projectName: string;
153
+ regimes: string[];
154
+ attestedBy: string;
155
+ attestedAt: string;
156
+ attestedNotes?: string;
157
+ derivedGates: DerivedGates;
158
+ }): string;
159
+ /**
160
+ * Format the derived gates for console display (the "✓ Wrote ... with derived gates:" block).
161
+ */
162
+ export declare function formatDerivedGatesDisplay(derivedGates: DerivedGates): string;
163
+ /**
164
+ * DB-pool rationale displayed when a compliance regime forces `per-shard`.
165
+ * Returns null if the DB-pool is `shared-with-rls` (no rationale needed).
166
+ */
167
+ export declare function getDbPoolRationale(regimes: string[], derivedGates: DerivedGates): string | null;
168
+ /**
169
+ * Run the compliance posture wizard step (RFC-0022 §7 / AISDLC-324).
170
+ *
171
+ * Inserted into the init wizard BEFORE the gate-config feature prompts.
172
+ * Always runs — even for unregulated projects (declaring "(none)" is the
173
+ * explicit choice; the resulting compliance.yaml carries that decision).
174
+ *
175
+ * Flow:
176
+ * 1. Auto-detect git config user.email for attestedBy default.
177
+ * 2. If --yes or non-TTY: use baseline (no regimes), auto-fill attestedBy.
178
+ * 3. Otherwise: multi-select regimes, text-input attestedBy + notes.
179
+ * 4. Compute derivedGates via inline tightest-wins composition.
180
+ * 5. Write .ai-sdlc/compliance.yaml (skips if file already exists and not
181
+ * in --add compliance mode).
182
+ * 6. Log derived gates + DB-pool rationale.
183
+ */
184
+ export declare function runComplianceStep(projectDir: string, flags: WizardFlags, adapters: FeatureAdapters): Promise<ComplianceStepResult>;
21
185
  /** Per-feature on/off bits derived from prompts + flags. */
22
186
  export interface FeatureSelection {
23
187
  dor: boolean;
24
188
  attestation: boolean;
25
189
  classifier: boolean;
26
190
  branchProtection: boolean;
191
+ /**
192
+ * `workflows` — scaffold the full GitHub Actions workflow bundle
193
+ * (ai-sdlc-gate, verify-attestation, ai-sdlc-review, auto-enable-auto-merge).
194
+ * Enabled by `--with-workflows` flag or `--add workflows` subcommand (AISDLC-261).
195
+ */
196
+ workflows: boolean;
197
+ /**
198
+ * `signalIngestion` — scaffold the RFC-0030 signal-ingestion config stub at
199
+ * `.ai-sdlc/signal-ingestion.yaml` (Phase 6 / AISDLC-348). The file ships
200
+ * `enabled: false`; the pipeline runtime stays dark until the operator
201
+ * explicitly flips it AND opts in via `AI_SDLC_SIGNAL_INGESTION` during
202
+ * the soak window. Default OFF in `--yes` mode (per the soak convention)
203
+ * but available via `--with-signal-ingestion` / `--add signal-ingestion`.
204
+ */
205
+ signalIngestion: boolean;
27
206
  }
28
207
  /** All feature flags off — used as the initial state before flags + prompts. */
29
208
  export declare const NO_FEATURES: FeatureSelection;
30
- /** All features on — the answer used by `--yes` (accept all defaults). */
209
+ /**
210
+ * All features on — the answer used by `--yes` (accept all defaults).
211
+ *
212
+ * Note: `signalIngestion` is deliberately FALSE in this set even though
213
+ * `--yes` accepts all *defaults*. RFC-0030's pipeline is gated by the
214
+ * `AI_SDLC_SIGNAL_INGESTION` env flag during its soak window, and the
215
+ * shipped default for the flag is OFF. Scaffolding the config stub on a
216
+ * fresh adopter who hasn't opted in would be noise; the file is only
217
+ * meaningful when the operator has explicit interest. Adopters opt in
218
+ * via `--with-signal-ingestion` or `--add signal-ingestion`.
219
+ */
31
220
  export declare const ALL_FEATURES: FeatureSelection;
32
221
  /** Flag-bag controlling wizard behavior (already parsed from argv). */
33
222
  export interface WizardFlags {
@@ -41,14 +230,41 @@ export interface WizardFlags {
41
230
  withClassifier: boolean;
42
231
  /** `--with-branch-protection` forces branch-protection on without prompting. */
43
232
  withBranchProtection: boolean;
233
+ /**
234
+ * `--with-workflows` scaffolds the full GitHub Actions workflow bundle
235
+ * (ai-sdlc-gate, verify-attestation, ai-sdlc-review, auto-enable-auto-merge)
236
+ * without prompting (AISDLC-261).
237
+ */
238
+ withWorkflows: boolean;
239
+ /**
240
+ * `--with-signal-ingestion` scaffolds the RFC-0030 signal-ingestion config
241
+ * stub at `.ai-sdlc/signal-ingestion.yaml` without prompting (AISDLC-348).
242
+ * The file ships `enabled: false`; the pipeline stays dark until the
243
+ * operator explicitly opts in. Always OFF by default in `--yes` mode.
244
+ */
245
+ withSignalIngestion: boolean;
44
246
  /**
45
247
  * `--add <feature>` extends an already-initialized repo with a single
46
248
  * feature without re-prompting. AC #7 (idempotent extension). When set,
47
249
  * the wizard short-circuits to scaffold ONLY this feature.
48
250
  */
49
- add?: 'dor' | 'attestation' | 'classifier' | 'branch-protection';
251
+ add?: 'dor' | 'attestation' | 'classifier' | 'branch-protection' | 'workflows' | 'signal-ingestion';
50
252
  /** `--dry-run` — print what would be done, don't write. */
51
253
  dryRun: boolean;
254
+ /**
255
+ * `--workspace <name>` opts into a per-workspace install at
256
+ * `packages/<name>/.ai-sdlc/` instead of the git-root default.
257
+ * Only relevant when the git root already has an `.ai-sdlc/` directory
258
+ * (e.g. the repo root already has AI-SDLC installed and the operator
259
+ * wants to add a child-workspace install). Without this flag, init
260
+ * refuses to nest if the git root already has `.ai-sdlc/`.
261
+ */
262
+ workspace?: string;
263
+ /**
264
+ * `--force` — when set, overwrite workflow files that already exist instead
265
+ * of skipping them. Only applies to the `workflows` feature (AISDLC-261).
266
+ */
267
+ force: boolean;
52
268
  }
53
269
  /**
54
270
  * Single-question prompter contract — accepts a question + default and
@@ -91,7 +307,86 @@ export interface FeatureAdapters {
91
307
  };
92
308
  /** Sink for operator-visible output (defaults to console.log). */
93
309
  log: (line: string) => void;
310
+ /**
311
+ * Multi-select prompt — returns the array of selected choice values.
312
+ * Production adapter uses `@inquirer/prompts` `checkbox`.
313
+ * Tests inject a stub that returns scripted selections.
314
+ */
315
+ multiSelect: (question: string, choices: ComplianceRegimeChoice[]) => Promise<string[]>;
316
+ /**
317
+ * Text input prompt — returns the entered string.
318
+ * Production adapter uses `@inquirer/prompts` `input`.
319
+ * Tests inject a stub that returns scripted values.
320
+ */
321
+ textInput: (question: string, defaultValue?: string) => Promise<string>;
322
+ }
323
+ /**
324
+ * Result returned by `resolveInstallTarget`. The caller uses `installDir`
325
+ * as the `projectDir` argument passed down to `initProject` and the wizard
326
+ * stage. The `resolved` flag is true when the target differs from `cwd`
327
+ * (i.e. we walked up to the git root).
328
+ */
329
+ export interface InstallTargetResult {
330
+ /** Absolute path to the directory where `.ai-sdlc/` should be written. */
331
+ installDir: string;
332
+ /** True when `installDir !== cwd` (we resolved up to the git root). */
333
+ resolved: boolean;
334
+ /** Error message when the target is refused; installDir is unset in this case. */
335
+ error?: string;
94
336
  }
337
+ /**
338
+ * Options bag for `resolveInstallTarget`. Adapters allow tests to inject
339
+ * controlled filesystem / subprocess behaviour without touching real disk.
340
+ */
341
+ export interface ResolveInstallTargetOptions {
342
+ /** Working directory to start from (defaults to `process.cwd()`). */
343
+ cwd?: string;
344
+ /** The `--workspace <name>` flag value, if provided. */
345
+ workspace?: string;
346
+ /** Config directory name (defaults to `.ai-sdlc`). */
347
+ configDirName?: string;
348
+ /**
349
+ * Override for `git rev-parse --show-toplevel`. Receives the cwd and
350
+ * returns the git root path, or throws if not inside a git repo.
351
+ */
352
+ gitShowToplevel?: (cwd: string) => string;
353
+ /** Override for existence checks (defaults to `node:fs.existsSync`). */
354
+ exists?: (path: string) => boolean;
355
+ /**
356
+ * When true, skip the "already installed at <root>" nesting check.
357
+ * Used by the `--add <feature>` extension path, which intentionally
358
+ * extends an already-initialized repo (the existing `.ai-sdlc/` IS
359
+ * the install the operator wants to extend).
360
+ */
361
+ skipExistingCheck?: boolean;
362
+ }
363
+ /**
364
+ * Resolve the AI-SDLC install target directory for the current invocation
365
+ * (AISDLC-262).
366
+ *
367
+ * ## Default behavior (no `--workspace` flag)
368
+ *
369
+ * 1. Shell out to `git rev-parse --show-toplevel` to find the repo root.
370
+ * - If the cwd is not inside a git repo, install at cwd (plain-dir
371
+ * fallback — same as the pre-AISDLC-262 behavior).
372
+ * 2. If `<git-root>/.ai-sdlc/` **already exists**, refuse with a clear
373
+ * "already installed at <root>; pass --workspace <name>" message so
374
+ * the operator knows exactly what to do next.
375
+ * 3. Otherwise install at the git root.
376
+ *
377
+ * ## `--workspace <name>` mode
378
+ *
379
+ * The operator explicitly wants a per-workspace install at
380
+ * `packages/<name>/.ai-sdlc/` (or `<name>/.ai-sdlc/` if `packages/` does
381
+ * not exist under the git root). No nesting check is performed — the
382
+ * operator has opted in.
383
+ *
384
+ * ## Dry-run output
385
+ *
386
+ * The resolved `installDir` is logged by the caller on the FIRST output
387
+ * line so adopters can sanity-check the target before any files are written.
388
+ */
389
+ export declare function resolveInstallTarget(opts?: ResolveInstallTargetOptions): InstallTargetResult;
95
390
  /**
96
391
  * Build the production adapter bag. Pulled into a factory so tests can
97
392
  * compose a partial override bag (e.g. only override `prompt`) and let
@@ -135,6 +430,10 @@ export interface ApplyResult {
135
430
  * Idempotent: any file that already exists at the target path is skipped
136
431
  * with a "skip" log line. This is what makes `--add <feature>` safe to
137
432
  * run on an already-initialized repo (AC #7).
433
+ *
434
+ * The `workflows` feature (AISDLC-261) supports `--force` to overwrite
435
+ * existing workflow files with the current template versions. Use this
436
+ * to upgrade a pre-261 repo to the full workflow bundle.
138
437
  */
139
438
  export declare function applyFeatureSelection(projectDir: string, selection: FeatureSelection, flags: WizardFlags, adapters: FeatureAdapters): Promise<ApplyResult>;
140
439
  export interface BranchProtectionResult {