@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.
Files changed (172) hide show
  1. package/dist/__test-helpers/git-env.d.ts +40 -0
  2. package/dist/__test-helpers/git-env.js +73 -0
  3. package/dist/adapters.d.ts +42 -3
  4. package/dist/adapters.js +133 -3
  5. package/dist/admission-composite.d.ts +134 -1
  6. package/dist/admission-composite.js +170 -6
  7. package/dist/admission-enrichment.d.ts +12 -3
  8. package/dist/admission-enrichment.js +71 -10
  9. package/dist/admission-hc.d.ts +20 -1
  10. package/dist/admission-hc.js +12 -1
  11. package/dist/admission-score.d.ts +44 -0
  12. package/dist/admission-score.js +11 -2
  13. package/dist/backlog-adapter.d.ts +45 -0
  14. package/dist/backlog-adapter.js +145 -1
  15. package/dist/calibration.d.ts +81 -0
  16. package/dist/calibration.js +76 -0
  17. package/dist/cli/commands/git-remote.d.ts +25 -0
  18. package/dist/cli/commands/git-remote.js +80 -1
  19. package/dist/cli/commands/init-features.d.ts +507 -0
  20. package/dist/cli/commands/init-features.js +1100 -0
  21. package/dist/cli/commands/init-templates.d.ts +301 -0
  22. package/dist/cli/commands/init-templates.js +1341 -0
  23. package/dist/cli/commands/init.d.ts +67 -0
  24. package/dist/cli/commands/init.js +301 -2
  25. package/dist/cli/commands/run.js +9 -1
  26. package/dist/cli/index.d.ts +11 -0
  27. package/dist/cli/index.js +42 -8
  28. package/dist/compliance/composer.d.ts +79 -0
  29. package/dist/compliance/composer.js +258 -0
  30. package/dist/compliance/errors.d.ts +64 -0
  31. package/dist/compliance/errors.js +85 -0
  32. package/dist/compliance/loader.d.ts +52 -0
  33. package/dist/compliance/loader.js +124 -0
  34. package/dist/compliance/types.d.ts +184 -0
  35. package/dist/compliance/types.js +41 -0
  36. package/dist/compliance-clearance.d.ts +269 -0
  37. package/dist/compliance-clearance.js +269 -0
  38. package/dist/config.js +17 -0
  39. package/dist/cost-tracker.d.ts +22 -0
  40. package/dist/cost-tracker.js +41 -0
  41. package/dist/database/adapters/external.js +5 -1
  42. package/dist/design-authority.d.ts +13 -0
  43. package/dist/design-authority.js +13 -0
  44. package/dist/embedding/adapters/openai-text-embedding-3-small.d.ts +71 -0
  45. package/dist/embedding/adapters/openai-text-embedding-3-small.js +190 -0
  46. package/dist/embedding/consumers/tessellation-drift.d.ts +74 -0
  47. package/dist/embedding/consumers/tessellation-drift.js +76 -0
  48. package/dist/embedding/cross-provider.d.ts +78 -0
  49. package/dist/embedding/cross-provider.js +75 -0
  50. package/dist/embedding/deprecation.d.ts +151 -0
  51. package/dist/embedding/deprecation.js +229 -0
  52. package/dist/embedding/errors.d.ts +90 -0
  53. package/dist/embedding/errors.js +150 -0
  54. package/dist/embedding/index.d.ts +29 -0
  55. package/dist/embedding/index.js +24 -0
  56. package/dist/embedding/pipeline-load.d.ts +146 -0
  57. package/dist/embedding/pipeline-load.js +178 -0
  58. package/dist/embedding/registry.d.ts +45 -0
  59. package/dist/embedding/registry.js +61 -0
  60. package/dist/embedding/stale-vector.d.ts +110 -0
  61. package/dist/embedding/stale-vector.js +92 -0
  62. package/dist/embedding/storage/index.d.ts +51 -0
  63. package/dist/embedding/storage/index.js +43 -0
  64. package/dist/embedding/storage/jsonl-backend.d.ts +150 -0
  65. package/dist/embedding/storage/jsonl-backend.js +332 -0
  66. package/dist/embedding/storage/types.d.ts +135 -0
  67. package/dist/embedding/storage/types.js +13 -0
  68. package/dist/embedding/types.d.ts +180 -0
  69. package/dist/embedding/types.js +10 -0
  70. package/dist/execute.d.ts +29 -2
  71. package/dist/execute.js +179 -35
  72. package/dist/index.d.ts +14 -2
  73. package/dist/index.js +19 -2
  74. package/dist/journey/inheritance-validator.d.ts +396 -0
  75. package/dist/journey/inheritance-validator.js +370 -0
  76. package/dist/journey/state-id-drift-rule.d.ts +137 -0
  77. package/dist/journey/state-id-drift-rule.js +245 -0
  78. package/dist/journey-sa2-router.d.ts +395 -0
  79. package/dist/journey-sa2-router.js +308 -0
  80. package/dist/models/classifier.d.ts +3 -1
  81. package/dist/models/classifier.js +61 -5
  82. package/dist/pillar-breakdown.d.ts +23 -1
  83. package/dist/pillar-breakdown.js +9 -0
  84. package/dist/runners/review-agent.js +6 -2
  85. package/dist/runners/runner-registry.d.ts +36 -0
  86. package/dist/runners/runner-registry.js +90 -0
  87. package/dist/runtime/attestations.d.ts +663 -11
  88. package/dist/runtime/attestations.js +971 -24
  89. package/dist/runtime/index.d.ts +1 -1
  90. package/dist/runtime/index.js +1 -1
  91. package/dist/runtime/parallelism-flag.d.ts +21 -3
  92. package/dist/runtime/parallelism-flag.js +27 -6
  93. package/dist/runtime/port-allocator.d.ts +11 -0
  94. package/dist/runtime/port-allocator.js +30 -0
  95. package/dist/sa-scoring/layer3-llm.js +6 -1
  96. package/dist/sa-scoring/revision-proposal-config.d.ts +178 -0
  97. package/dist/sa-scoring/revision-proposal-config.js +198 -0
  98. package/dist/sa-scoring/revision-proposal.d.ts +285 -0
  99. package/dist/sa-scoring/revision-proposal.js +417 -0
  100. package/dist/signal-ingestion/adapters/community-thread.d.ts +43 -0
  101. package/dist/signal-ingestion/adapters/community-thread.js +55 -0
  102. package/dist/signal-ingestion/adapters/in-app-feedback.d.ts +67 -0
  103. package/dist/signal-ingestion/adapters/in-app-feedback.js +51 -0
  104. package/dist/signal-ingestion/adapters/manual.d.ts +78 -0
  105. package/dist/signal-ingestion/adapters/manual.js +112 -0
  106. package/dist/signal-ingestion/adapters/support-ticket.d.ts +47 -0
  107. package/dist/signal-ingestion/adapters/support-ticket.js +51 -0
  108. package/dist/signal-ingestion/classifier.d.ts +205 -0
  109. package/dist/signal-ingestion/classifier.js +494 -0
  110. package/dist/signal-ingestion/clustering-types.d.ts +36 -0
  111. package/dist/signal-ingestion/clustering-types.js +14 -0
  112. package/dist/signal-ingestion/clustering.d.ts +200 -0
  113. package/dist/signal-ingestion/clustering.js +413 -0
  114. package/dist/signal-ingestion/config.d.ts +351 -0
  115. package/dist/signal-ingestion/config.js +587 -0
  116. package/dist/signal-ingestion/d1.d.ts +252 -0
  117. package/dist/signal-ingestion/d1.js +235 -0
  118. package/dist/signal-ingestion/errors.d.ts +73 -0
  119. package/dist/signal-ingestion/errors.js +108 -0
  120. package/dist/signal-ingestion/governance-events.d.ts +181 -0
  121. package/dist/signal-ingestion/governance-events.js +189 -0
  122. package/dist/signal-ingestion/index.d.ts +35 -0
  123. package/dist/signal-ingestion/index.js +53 -0
  124. package/dist/signal-ingestion/manual-share-metric.d.ts +93 -0
  125. package/dist/signal-ingestion/manual-share-metric.js +106 -0
  126. package/dist/signal-ingestion/registry.d.ts +40 -0
  127. package/dist/signal-ingestion/registry.js +137 -0
  128. package/dist/signal-ingestion/residency.d.ts +227 -0
  129. package/dist/signal-ingestion/residency.js +238 -0
  130. package/dist/signal-ingestion/significance.d.ts +554 -0
  131. package/dist/signal-ingestion/significance.js +555 -0
  132. package/dist/signal-ingestion/types.d.ts +191 -0
  133. package/dist/signal-ingestion/types.js +8 -0
  134. package/dist/substrate/drift-composition.d.ts +270 -0
  135. package/dist/substrate/drift-composition.js +306 -0
  136. package/dist/substrate/drift-tui-surface.d.ts +61 -0
  137. package/dist/substrate/drift-tui-surface.js +102 -0
  138. package/dist/substrate/identity-class.d.ts +176 -0
  139. package/dist/substrate/identity-class.js +201 -0
  140. package/dist/tessellation/cross-soul-provenance-rule.d.ts +133 -0
  141. package/dist/tessellation/cross-soul-provenance-rule.js +171 -0
  142. package/dist/tessellation/inter-soul-embedding-distance-rule.d.ts +61 -0
  143. package/dist/tessellation/inter-soul-embedding-distance-rule.js +67 -0
  144. package/dist/tessellation/rule-registry.d.ts +269 -0
  145. package/dist/tessellation/rule-registry.js +92 -0
  146. package/dist/tessellation/soul-slug-ast-scan-rule.d.ts +90 -0
  147. package/dist/tessellation/soul-slug-ast-scan-rule.js +158 -0
  148. package/dist/tessellation-admission.d.ts +162 -0
  149. package/dist/tessellation-admission.js +146 -0
  150. package/dist/tessellation-drift.d.ts +246 -0
  151. package/dist/tessellation-drift.js +250 -0
  152. package/dist/validate-config.js +13 -0
  153. package/dist/validate-issue.js +2 -2
  154. package/dist/variant/cardinality-activation.d.ts +126 -0
  155. package/dist/variant/cardinality-activation.js +101 -0
  156. package/dist/variant/deprecation-lifecycle.d.ts +184 -0
  157. package/dist/variant/deprecation-lifecycle.js +208 -0
  158. package/dist/variant/drift-extension.d.ts +136 -0
  159. package/dist/variant/drift-extension.js +164 -0
  160. package/dist/variant/engineering-review.d.ts +185 -0
  161. package/dist/variant/engineering-review.js +142 -0
  162. package/dist/variant/index.d.ts +32 -0
  163. package/dist/variant/index.js +32 -0
  164. package/dist/variant/inheritance-validator.d.ts +165 -0
  165. package/dist/variant/inheritance-validator.js +139 -0
  166. package/dist/variant/internal-adopter/index.d.ts +11 -0
  167. package/dist/variant/internal-adopter/index.js +10 -0
  168. package/dist/variant/internal-adopter/products.d.ts +156 -0
  169. package/dist/variant/internal-adopter/products.js +366 -0
  170. package/dist/variant-admission.d.ts +316 -0
  171. package/dist/variant-admission.js +247 -0
  172. package/package.json +11 -8
@@ -0,0 +1,507 @@
1
+ /**
2
+ * `ai-sdlc init` interactive wizard + feature dispatcher (AISDLC-143).
3
+ *
4
+ * Per Q4(b) of the operator-ratified quality-gate redesign, `ai-sdlc init`
5
+ * is a wizard by default with `--yes` for non-interactive (CI/scripts) and
6
+ * `--with-X` flags for explicit opt-in (`--with-dor`, `--with-attestation`,
7
+ * `--with-classifier`, `--with-branch-protection`). This module owns:
8
+ *
9
+ * 1. The ordered prompt list (resolveFeatureSelection).
10
+ * 2. The feature-toggle → file-write dispatcher (applyFeatureSelection).
11
+ * 3. The branch-protection helper (applyBranchProtection) including the
12
+ * `--dry-run` JSON-print path required by AC #6.
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).
15
+ *
16
+ * Test surface: every public function takes a small options bag with
17
+ * injectable side-effect adapters (prompter, writeFile, runCommand) so the
18
+ * test suite can drive every wizard branch hermetically without spinning
19
+ * up a TTY or shelling out to `gh`. Production callers in `init.ts` pass
20
+ * the real adapters.
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>;
185
+ /** Per-feature on/off bits derived from prompts + flags. */
186
+ export interface FeatureSelection {
187
+ dor: boolean;
188
+ attestation: boolean;
189
+ classifier: boolean;
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;
206
+ }
207
+ /** All feature flags off — used as the initial state before flags + prompts. */
208
+ export declare const NO_FEATURES: FeatureSelection;
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
+ */
220
+ export declare const ALL_FEATURES: FeatureSelection;
221
+ /** Flag-bag controlling wizard behavior (already parsed from argv). */
222
+ export interface WizardFlags {
223
+ /** `--yes` short-circuits the wizard; treats every prompt as "yes". */
224
+ yes: boolean;
225
+ /** `--with-dor` forces the DoR feature on without prompting. */
226
+ withDor: boolean;
227
+ /** `--with-attestation` forces attestation infra on without prompting. */
228
+ withAttestation: boolean;
229
+ /** `--with-classifier` forces the classifier on without prompting. */
230
+ withClassifier: boolean;
231
+ /** `--with-branch-protection` forces branch-protection on without prompting. */
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;
246
+ /**
247
+ * `--add <feature>` extends an already-initialized repo with a single
248
+ * feature without re-prompting. AC #7 (idempotent extension). When set,
249
+ * the wizard short-circuits to scaffold ONLY this feature.
250
+ */
251
+ add?: 'dor' | 'attestation' | 'classifier' | 'branch-protection' | 'workflows' | 'signal-ingestion';
252
+ /** `--dry-run` — print what would be done, don't write. */
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;
268
+ }
269
+ /**
270
+ * Single-question prompter contract — accepts a question + default and
271
+ * returns the user's answer. The production adapter wraps `@inquirer/prompts`
272
+ * so the user gets a real readline TTY; tests inject a stub that returns
273
+ * scripted answers without touching stdin.
274
+ *
275
+ * Why a single-question primitive instead of "ask all questions at once":
276
+ * the prompts are conditional in some cases (e.g. branch-protection only
277
+ * makes sense after the user has chosen which CI gates exist). Keeping
278
+ * the primitive small lets `resolveFeatureSelection` decide ordering +
279
+ * skip questions whose answer is already determined by a `--with-X` flag.
280
+ */
281
+ export type Prompter = (question: string, defaultYes: boolean) => Promise<boolean>;
282
+ /**
283
+ * Side-effect adapter bag — every part of the dispatcher that touches
284
+ * disk or shells out goes through this so tests can assert on intents
285
+ * without mocking `node:fs` globally.
286
+ */
287
+ export interface FeatureAdapters {
288
+ /** Resolve to an interactive prompt answer. */
289
+ prompt: Prompter;
290
+ /** Write a file. Production = `node:fs.writeFileSync`. */
291
+ writeFile: (path: string, contents: string) => void;
292
+ /**
293
+ * Append `contents` to `path` exactly once: if `sentinel` is already
294
+ * present in the file, no-op. If the file doesn't exist, behaves like
295
+ * a write. Used for the husky pre-push sign block + CLAUDE.md pointer
296
+ * (both of which need to coexist with user-edited content).
297
+ */
298
+ appendOnce: (path: string, contents: string, sentinel: string) => 'appended' | 'skipped';
299
+ /** mkdir -p. Production = `node:fs.mkdirSync({ recursive: true })`. */
300
+ mkdirp: (path: string) => void;
301
+ /** Test for path existence. Production = `node:fs.existsSync`. */
302
+ exists: (path: string) => boolean;
303
+ /** Run a shell command (used for `gh api`). Production = `execSync`. */
304
+ runCommand: (cmd: string, args: string[]) => {
305
+ stdout: string;
306
+ exitCode: number;
307
+ };
308
+ /** Sink for operator-visible output (defaults to console.log). */
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;
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;
390
+ /**
391
+ * Build the production adapter bag. Pulled into a factory so tests can
392
+ * compose a partial override bag (e.g. only override `prompt`) and let
393
+ * the rest fall through to real disk writes.
394
+ *
395
+ * The `prompt` adapter is a lazy import of `@inquirer/prompts.confirm`
396
+ * so that:
397
+ * 1. Tests don't pay the import cost when they inject their own stub.
398
+ * 2. `--yes` runs (which never call `prompt`) don't pay it either.
399
+ * 3. The orchestrator's runtime `dist/` is smaller for the common case.
400
+ */
401
+ export declare function buildProductionAdapters(): FeatureAdapters;
402
+ /**
403
+ * Resolve the per-feature on/off vector by combining (in priority order):
404
+ * 1. `--add <feature>` — if set, ONLY that feature is on; everything
405
+ * else is suppressed (idempotent extension, AC #7).
406
+ * 2. `--yes` — accept every default (every feature on).
407
+ * 3. `--with-X` flags — opt-in without prompting.
408
+ * 4. Interactive prompts for any feature still undetermined.
409
+ *
410
+ * Returns a fully-determined FeatureSelection. The dispatcher then writes
411
+ * exactly the union of features marked true.
412
+ */
413
+ export declare function resolveFeatureSelection(flags: WizardFlags, adapters: Pick<FeatureAdapters, 'prompt' | 'log'>): Promise<FeatureSelection>;
414
+ /** Return value of `applyFeatureSelection` — what was actually written. */
415
+ export interface ApplyResult {
416
+ /** Files that were newly created on this run. */
417
+ created: string[];
418
+ /** Files that already existed and were left untouched (idempotent). */
419
+ skipped: string[];
420
+ /** Files that would have been created if not for `--dry-run`. */
421
+ wouldCreate: string[];
422
+ /** Branch-protection result, if attempted. */
423
+ branchProtection?: BranchProtectionResult;
424
+ }
425
+ /**
426
+ * Write the union of feature templates into the project dir. AC #4 says
427
+ * the BASELINE workflow templates (gate workflow) are always written; the
428
+ * per-feature template sets are written only when their toggle is on.
429
+ *
430
+ * Idempotent: any file that already exists at the target path is skipped
431
+ * with a "skip" log line. This is what makes `--add <feature>` safe to
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.
437
+ */
438
+ export declare function applyFeatureSelection(projectDir: string, selection: FeatureSelection, flags: WizardFlags, adapters: FeatureAdapters): Promise<ApplyResult>;
439
+ export interface BranchProtectionResult {
440
+ /** Whether the rule was actually applied. False in dry-run. */
441
+ applied: boolean;
442
+ /** The PUT body as a JSON string (always populated for visibility). */
443
+ bodyJson: string;
444
+ /** Error message from `gh api`, if non-zero exit. */
445
+ error?: string;
446
+ }
447
+ /**
448
+ * Recommended branch-protection ruleset for AI-SDLC adopters. AC #1 #4:
449
+ * the required checks are `ai-sdlc/pr-ready` (the gate aggregator) and
450
+ * `codecov/patch` (the de facto coverage signal). Other AI-SDLC apps
451
+ * post their own statuses but they're all rolled into pr-ready.
452
+ *
453
+ * The body conforms to the GitHub REST API
454
+ * `PUT /repos/{owner}/{repo}/branches/{branch}/protection` schema.
455
+ */
456
+ export declare const RECOMMENDED_BRANCH_PROTECTION_BODY: {
457
+ required_status_checks: {
458
+ strict: boolean;
459
+ contexts: string[];
460
+ };
461
+ enforce_admins: boolean;
462
+ required_pull_request_reviews: {
463
+ dismiss_stale_reviews: boolean;
464
+ require_code_owner_reviews: boolean;
465
+ required_approving_review_count: number;
466
+ };
467
+ restrictions: null;
468
+ allow_force_pushes: boolean;
469
+ allow_deletions: boolean;
470
+ };
471
+ /**
472
+ * Apply (or print, in dry-run) the recommended branch protection rule
473
+ * to the `main` branch of the repo at `projectDir`. AC #6 explicitly
474
+ * requires that `--dry-run` print the JSON without applying.
475
+ *
476
+ * The repo identity (`owner/repo`) is resolved by shelling out to
477
+ * `gh repo view --json nameWithOwner -q .nameWithOwner`. We could parse
478
+ * the git remote ourselves (see git-remote.ts) but `gh` already resolves
479
+ * forks + renames + custom default branches consistently, and the user
480
+ * needs `gh` on PATH for the PUT to work anyway.
481
+ */
482
+ export declare function applyBranchProtection(projectDir: string, flags: WizardFlags, adapters: Pick<FeatureAdapters, 'runCommand' | 'log'>): Promise<BranchProtectionResult>;
483
+ /**
484
+ * Print the structured "next steps" summary at the end of init. AC #5:
485
+ * the summary must include operator action items conditional on which
486
+ * features were chosen (e.g. `gh secret set` commands when attestation
487
+ * was opted in).
488
+ *
489
+ * Returns the rendered summary as a string in addition to logging it,
490
+ * so tests can assert on it without re-stringifying console output.
491
+ */
492
+ export declare function renderNextSteps(selection: FeatureSelection, result: ApplyResult, adapters: Pick<FeatureAdapters, 'log'>): string;
493
+ /**
494
+ * The pointer block we append to CLAUDE.md so a freshly-initialized repo's
495
+ * Claude Code sessions know where to find the AI-SDLC quality-gate docs.
496
+ * Idempotent — guarded by a sentinel so re-running init doesn't duplicate
497
+ * the block.
498
+ */
499
+ export declare const CLAUDE_MD_POINTER = "\n<!-- ai-sdlc:recommendation-pointer -->\n## AI-SDLC quality gate\n\nThis repo is bootstrapped with the AI-SDLC framework. The single PR-ready\nmerge gate is `ai-sdlc/pr-ready` (see `.github/workflows/ai-sdlc-gate.yml`).\nRun `ai-sdlc health` to verify your local config; see\n`docs/operations/init.md` for the adopter guide.\n<!-- end ai-sdlc:recommendation-pointer -->\n";
500
+ /** Sentinel marker used by the CLAUDE.md pointer for idempotency. */
501
+ export declare const CLAUDE_MD_SENTINEL = "<!-- ai-sdlc:recommendation-pointer -->";
502
+ /**
503
+ * Append the recommendation pointer to CLAUDE.md (or create the file if
504
+ * missing). Idempotent: if the sentinel is already present we no-op.
505
+ */
506
+ export declare function ensureClaudeMdPointer(projectDir: string, adapters: Pick<FeatureAdapters, 'exists' | 'writeFile' | 'appendOnce' | 'log'>, dryRun: boolean): void;
507
+ //# sourceMappingURL=init-features.d.ts.map