@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,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
|