container-superposition 0.1.3 → 0.1.5

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 (141) hide show
  1. package/README.md +72 -1014
  2. package/dist/scripts/init.js +512 -238
  3. package/dist/scripts/init.js.map +1 -1
  4. package/dist/tool/commands/adopt.d.ts +62 -0
  5. package/dist/tool/commands/adopt.d.ts.map +1 -0
  6. package/dist/tool/commands/adopt.js +767 -0
  7. package/dist/tool/commands/adopt.js.map +1 -0
  8. package/dist/tool/commands/doctor.js +2 -2
  9. package/dist/tool/commands/explain.d.ts.map +1 -1
  10. package/dist/tool/commands/explain.js +88 -0
  11. package/dist/tool/commands/explain.js.map +1 -1
  12. package/dist/tool/commands/hash.d.ts +36 -0
  13. package/dist/tool/commands/hash.d.ts.map +1 -0
  14. package/dist/tool/commands/hash.js +242 -0
  15. package/dist/tool/commands/hash.js.map +1 -0
  16. package/dist/tool/commands/plan.d.ts +53 -0
  17. package/dist/tool/commands/plan.d.ts.map +1 -1
  18. package/dist/tool/commands/plan.js +784 -42
  19. package/dist/tool/commands/plan.js.map +1 -1
  20. package/dist/tool/questionnaire/composer.d.ts +12 -3
  21. package/dist/tool/questionnaire/composer.d.ts.map +1 -1
  22. package/dist/tool/questionnaire/composer.js +133 -20
  23. package/dist/tool/questionnaire/composer.js.map +1 -1
  24. package/dist/tool/schema/project-config.d.ts +15 -0
  25. package/dist/tool/schema/project-config.d.ts.map +1 -0
  26. package/dist/tool/schema/project-config.js +359 -0
  27. package/dist/tool/schema/project-config.js.map +1 -0
  28. package/dist/tool/schema/types.d.ts +57 -1
  29. package/dist/tool/schema/types.d.ts.map +1 -1
  30. package/dist/tool/utils/backup.d.ts +23 -0
  31. package/dist/tool/utils/backup.d.ts.map +1 -0
  32. package/dist/tool/utils/backup.js +123 -0
  33. package/dist/tool/utils/backup.js.map +1 -0
  34. package/dist/tool/utils/gitignore.d.ts +15 -0
  35. package/dist/tool/utils/gitignore.d.ts.map +1 -0
  36. package/dist/tool/utils/gitignore.js +41 -0
  37. package/dist/tool/utils/gitignore.js.map +1 -0
  38. package/dist/tool/utils/services-export.d.ts +14 -0
  39. package/dist/tool/utils/services-export.d.ts.map +1 -0
  40. package/dist/tool/utils/services-export.js +478 -0
  41. package/dist/tool/utils/services-export.js.map +1 -0
  42. package/dist/tool/utils/summary.d.ts +69 -0
  43. package/dist/tool/utils/summary.d.ts.map +1 -0
  44. package/dist/tool/utils/summary.js +260 -0
  45. package/dist/tool/utils/summary.js.map +1 -0
  46. package/docs/README.md +12 -2
  47. package/docs/adopt.md +196 -0
  48. package/docs/custom-patches.md +1 -1
  49. package/docs/discovery-commands.md +55 -3
  50. package/docs/examples.md +40 -6
  51. package/docs/filesystem-contract.md +58 -0
  52. package/docs/hash.md +183 -0
  53. package/docs/minimal-and-editor.md +1 -1
  54. package/docs/overlays.md +108 -5
  55. package/docs/presets-architecture.md +1 -1
  56. package/docs/presets.md +1 -1
  57. package/docs/publishing.md +36 -23
  58. package/docs/security.md +43 -0
  59. package/docs/specs/001-verbose-plan-graph/checklists/requirements.md +36 -0
  60. package/docs/specs/001-verbose-plan-graph/contracts/plan-verbose-output.md +96 -0
  61. package/docs/specs/001-verbose-plan-graph/data-model.md +111 -0
  62. package/docs/specs/001-verbose-plan-graph/plan.md +127 -0
  63. package/docs/specs/001-verbose-plan-graph/quickstart.md +106 -0
  64. package/docs/specs/001-verbose-plan-graph/research.md +100 -0
  65. package/docs/specs/001-verbose-plan-graph/spec.md +128 -0
  66. package/docs/specs/001-verbose-plan-graph/tasks.md +223 -0
  67. package/docs/specs/002-superposition-config-file/checklists/requirements.md +36 -0
  68. package/docs/specs/002-superposition-config-file/contracts/init-project-config.md +98 -0
  69. package/docs/specs/002-superposition-config-file/data-model.md +126 -0
  70. package/docs/specs/002-superposition-config-file/plan.md +208 -0
  71. package/docs/specs/002-superposition-config-file/quickstart.md +140 -0
  72. package/docs/specs/002-superposition-config-file/research.md +144 -0
  73. package/docs/specs/002-superposition-config-file/spec.md +130 -0
  74. package/docs/specs/002-superposition-config-file/tasks.md +213 -0
  75. package/docs/team-workflow.md +27 -1
  76. package/docs/workflows.md +136 -0
  77. package/overlays/.presets/microservice.yml +32 -6
  78. package/overlays/.presets/sdd.yml +84 -0
  79. package/overlays/.presets/web-api.yml +76 -56
  80. package/overlays/README.md +7 -1
  81. package/overlays/amp/README.md +70 -0
  82. package/overlays/amp/devcontainer.patch.json +3 -0
  83. package/overlays/amp/overlay.yml +15 -0
  84. package/overlays/amp/setup.sh +21 -0
  85. package/overlays/amp/verify.sh +21 -0
  86. package/overlays/claude-code/README.md +83 -0
  87. package/overlays/claude-code/devcontainer.patch.json +3 -0
  88. package/overlays/claude-code/overlay.yml +15 -0
  89. package/overlays/claude-code/setup.sh +21 -0
  90. package/overlays/claude-code/verify.sh +21 -0
  91. package/overlays/cloudflared/README.md +190 -0
  92. package/overlays/cloudflared/devcontainer.patch.json +3 -0
  93. package/overlays/cloudflared/overlay.yml +15 -0
  94. package/overlays/cloudflared/setup.sh +49 -0
  95. package/overlays/cloudflared/verify.sh +21 -0
  96. package/overlays/direnv/README.md +6 -4
  97. package/overlays/direnv/setup.sh +0 -12
  98. package/overlays/gemini-cli/README.md +77 -0
  99. package/overlays/gemini-cli/devcontainer.patch.json +3 -0
  100. package/overlays/gemini-cli/overlay.yml +15 -0
  101. package/overlays/gemini-cli/setup.sh +21 -0
  102. package/overlays/gemini-cli/verify.sh +21 -0
  103. package/overlays/grpc-tools/README.md +242 -0
  104. package/overlays/grpc-tools/devcontainer.patch.json +14 -0
  105. package/overlays/grpc-tools/overlay.yml +14 -0
  106. package/overlays/grpc-tools/setup.sh +57 -0
  107. package/overlays/grpc-tools/verify.sh +47 -0
  108. package/overlays/keycloak/.env.example +5 -0
  109. package/overlays/keycloak/README.md +238 -0
  110. package/overlays/keycloak/devcontainer.patch.json +17 -0
  111. package/overlays/keycloak/docker-compose.yml +32 -0
  112. package/overlays/keycloak/overlay.yml +23 -0
  113. package/overlays/keycloak/verify.sh +54 -0
  114. package/overlays/mailpit/.env.example +4 -0
  115. package/overlays/mailpit/README.md +191 -0
  116. package/overlays/mailpit/devcontainer.patch.json +20 -0
  117. package/overlays/mailpit/docker-compose.yml +17 -0
  118. package/overlays/mailpit/overlay.yml +26 -0
  119. package/overlays/mailpit/verify.sh +52 -0
  120. package/overlays/ngrok/overlay.yml +2 -1
  121. package/overlays/opencode/README.md +76 -0
  122. package/overlays/opencode/devcontainer.patch.json +3 -0
  123. package/overlays/opencode/overlay.yml +14 -0
  124. package/overlays/opencode/setup.sh +21 -0
  125. package/overlays/opencode/verify.sh +21 -0
  126. package/overlays/python/README.md +51 -35
  127. package/overlays/python/devcontainer.patch.json +7 -4
  128. package/overlays/python/setup.sh +50 -23
  129. package/overlays/python/verify.sh +29 -1
  130. package/overlays/spec-kit/README.md +181 -0
  131. package/overlays/spec-kit/devcontainer.patch.json +6 -0
  132. package/overlays/spec-kit/overlay.yml +19 -0
  133. package/overlays/spec-kit/setup.sh +45 -0
  134. package/overlays/spec-kit/verify.sh +33 -0
  135. package/overlays/windsurf-cli/README.md +69 -0
  136. package/overlays/windsurf-cli/devcontainer.patch.json +3 -0
  137. package/overlays/windsurf-cli/overlay.yml +15 -0
  138. package/overlays/windsurf-cli/setup.sh +21 -0
  139. package/overlays/windsurf-cli/verify.sh +21 -0
  140. package/package.json +1 -1
  141. package/tool/schema/config.schema.json +138 -9
@@ -0,0 +1,208 @@
1
+ # Implementation Plan: Project Configuration File
2
+
3
+ **Branch**: `002-superposition-config-file` | **Date**: 2026-03-11 | **Spec**: [spec.md](spec.md)
4
+ **Input**: Feature specification from `docs/specs/002-superposition-config-file/spec.md`
5
+
6
+ **Note**: This plan follows the approved spec and constitution gates for the
7
+ active feature branch.
8
+
9
+ ## Summary
10
+
11
+ Add repository-root project config support so `init` and `regen` can load a
12
+ committed `.superposition.yml` or `superposition.yml` as a persisted source of
13
+ truth for supported generation flows, with full parity to supported generation
14
+ inputs, including customization surfaces such as custom container definitions,
15
+ environment-related settings, preset glue, and additional generated features.
16
+ The design extends the existing answer-merging flow instead of creating a second
17
+ generation pipeline, introduces an explicit `--from-project` mode, allows
18
+ implicit project-file use for `init --no-interactive` and default `regen` when
19
+ no conflicting source or selection flags are supplied, and keeps explicit
20
+ manifest-based regeneration as a separate persisted-input mode.
21
+
22
+ ## Technical Context
23
+
24
+ **Language/Version**: TypeScript 5.3.3 on Node.js 20+
25
+ **Primary Dependencies**: Commander, chalk, boxen, js-yaml, ora, Inquirer
26
+ **Storage**: Filesystem-based project YAML config, `superposition.json`
27
+ manifests, overlay manifests, templates, and generated devcontainer artifacts
28
+ **Testing**: Vitest unit and command tests, shell-based smoke tests, TypeScript
29
+ compile checks
30
+ **Target Platform**: Node.js CLI on Linux, macOS, and Windows developer
31
+ environments
32
+ **Project Type**: CLI scaffolding tool
33
+ **Performance Goals**: Keep project-config discovery plus validation under 200
34
+ ms in representative repositories so initialization remains dominated by the
35
+ existing generation work rather than config loading
36
+ **Constraints**: Preserve backward compatibility for interactive, flag-driven,
37
+ explicit project-file, and explicit manifest-based flows; preserve source/dist
38
+ path compatibility with candidate-path resolution; maintain full parity between
39
+ supported clean generation inputs and project-config declarations; reject
40
+ conflicting persisted-input source combinations before generation; keep
41
+ ambiguity and validation failures user-facing and deterministic
42
+ **Scale/Scope**: Single feature spanning `scripts/init.ts`, shared schema/types,
43
+ config-loading helpers, command and composition tests, documentation, and
44
+ generation parity for supported customization inputs
45
+
46
+ ## Constitution Check
47
+
48
+ _GATE: Must pass before Phase 0 research. Re-check after Phase 1 design and
49
+ before implementation._
50
+
51
+ - [x] Spec exists at `docs/specs/002-superposition-config-file/spec.md`.
52
+ - [x] Spec is committed and reviewed before implementation tasks or code begin.
53
+ - [x] Plan scope, compatibility impact, and complexity notes match the approved
54
+ spec.
55
+ - [x] Verification scope covers tests, smoke checks, and documentation updates
56
+ needed for the change.
57
+ - [x] User-visible changes include documentation updates and an `[Unreleased]`
58
+ `CHANGELOG.md` entry.
59
+
60
+ Gate status: Pass. Planning may proceed.
61
+
62
+ ## Project Structure
63
+
64
+ ### Documentation (this feature)
65
+
66
+ ```text
67
+ docs/specs/002-superposition-config-file/
68
+ ├── plan.md
69
+ ├── research.md
70
+ ├── data-model.md
71
+ ├── quickstart.md
72
+ ├── contracts/
73
+ │ └── init-project-config.md
74
+ └── tasks.md
75
+ ```
76
+
77
+ ### Source Code (repository root)
78
+
79
+ ```text
80
+ scripts/
81
+ └── init.ts
82
+
83
+ tool/
84
+ ├── __tests__/
85
+ │ ├── commands.test.ts
86
+ │ ├── composition.test.ts
87
+ │ ├── manifest-only.test.ts
88
+ │ ├── minimal-and-editor.test.ts
89
+ │ └── summary.test.ts
90
+ ├── questionnaire/
91
+ │ └── composer.ts
92
+ ├── schema/
93
+ │ ├── config.schema.json
94
+ │ ├── project-config.ts
95
+ │ └── types.ts
96
+ └── utils/
97
+ └── summary.ts
98
+
99
+ docs/
100
+ ├── examples.md
101
+ ├── workflows.md
102
+ └── specs/
103
+
104
+ README.md
105
+ CHANGELOG.md
106
+ ```
107
+
108
+ **Structure Decision**: Keep the feature centered on `scripts/init.ts`, because
109
+ input discovery, CLI parsing, manifest handling, and answer merging already
110
+ converge there. Add one focused schema/helper module for project-config
111
+ discovery and validation, extend existing shared types for parity with clean
112
+ generation inputs, and keep verification concentrated in existing command and
113
+ composition test suites.
114
+
115
+ ## Phase 0: Research
116
+
117
+ ### Research Goals
118
+
119
+ - Confirm the correct precedence between project config, direct command input,
120
+ interactive completion, explicit `--from-project`, implicit project-file
121
+ source selection, and explicit manifest mode.
122
+ - Define what “full parity to clean generation” means for supported
123
+ customization inputs without introducing a second generation model.
124
+ - Confirm discovery, ambiguity handling, and validation boundaries for a
125
+ repository-root YAML config.
126
+
127
+ ### Research Outputs
128
+
129
+ - [research.md](research.md)
130
+
131
+ ## Phase 1: Design
132
+
133
+ ### Data Model
134
+
135
+ - [data-model.md](data-model.md)
136
+
137
+ ### Contracts
138
+
139
+ - [init-project-config.md](contracts/init-project-config.md)
140
+
141
+ ### Quickstart
142
+
143
+ - [quickstart.md](quickstart.md)
144
+
145
+ ## Implementation Approach
146
+
147
+ 1. Add repository-root project-config discovery and validation to the standard
148
+ `init` flow and to `regen`, while keeping explicit manifest-based
149
+ regeneration behavior available as a separate mode.
150
+ 2. Model project config as another partial-answer source that feeds the existing
151
+ `QuestionnaireAnswers` merge path.
152
+ 3. Extend the supported config shape so it can declare every supported
153
+ clean-generation input, including customization surfaces already represented
154
+ in the current answer and generation flow.
155
+ 4. Add explicit source-selection validation so `--from-project` and
156
+ `--from-manifest` remain mutually exclusive and cannot be combined with
157
+ clean-generation selection flags such as stack, overlays, or preset choices.
158
+ 5. Preserve parity by ensuring project-config declarations yield the same final
159
+ generated output as equivalent direct user selections.
160
+ 6. Add regression coverage for no-config fallback, override precedence,
161
+ project-file based regen, explicit `--from-project`, manifest isolation,
162
+ source-conflict validation, invalid config handling, ambiguity detection, and
163
+ customization parity.
164
+ 7. Update docs and changelog entries so the declarative workflow, source
165
+ selection modes, and conflict rules are user-visible and auditable.
166
+
167
+ ## Verification Strategy
168
+
169
+ - Add or update automated coverage for:
170
+ - repository-root project-config discovery
171
+ - no-config fallback behavior
172
+ - CLI-over-project-config precedence
173
+ - explicit `--from-project` behavior for `init` and `regen`
174
+ - implicit project-file selection for `init --no-interactive` and default
175
+ `regen`
176
+ - explicit manifest isolation from project-config defaults
177
+ - persisted-input source conflict validation (`--from-project`,
178
+ `--from-manifest`, and clean-generation selection flags)
179
+ - partial config completion through the existing questionnaire flow
180
+ - invalid YAML, unsupported keys or values, conflicts, and dual-file
181
+ ambiguity
182
+ - parity for supported customization inputs such as custom images, preset
183
+ glue, editor/minimal settings, environment-related settings, and additional
184
+ generated features
185
+ - Run `npm test`.
186
+ - Run `npm run lint`.
187
+ - Run `npm run test:smoke` when generation behavior changes across representative
188
+ stacks.
189
+ - Manually validate the scenarios in [quickstart.md](quickstart.md).
190
+
191
+ ## Post-Design Constitution Check
192
+
193
+ - [x] Design preserves spec-first workflow and traces directly to the approved
194
+ spec.
195
+ - [x] Design preserves overlay contract integrity by extending the existing
196
+ answer and generation pipeline rather than inventing a parallel path.
197
+ - [x] Verification remains proportional to risk: automated tests, smoke
198
+ validation where applicable, and documentation updates are planned before
199
+ merge.
200
+ - [x] Documentation synchronization is explicit: `README.md`,
201
+ `docs/workflows.md`, `docs/examples.md`, `quickstart.md`, and `CHANGELOG.md`.
202
+ - [x] Simplicity and compatibility remain intact: project config is a default
203
+ persisted input source, explicit `--from-project` and explicit manifest
204
+ modes remain separate, and candidate-path compatibility stays required.
205
+
206
+ ## Complexity Tracking
207
+
208
+ No constitution violations require a design exception.
@@ -0,0 +1,140 @@
1
+ # Quickstart: Project Configuration File
2
+
3
+ ## Goal
4
+
5
+ Use a committed repository-root config file to declare the same supported setup
6
+ intent that users would otherwise provide through clean generation commands.
7
+
8
+ ## 1. Add one project config file at the repository root
9
+
10
+ Choose exactly one:
11
+
12
+ - `.superposition.yml`
13
+ - `superposition.yml`
14
+
15
+ Do not keep both in the same repository.
16
+
17
+ ## 2. Declare the intended environment
18
+
19
+ Define the supported clean-generation inputs your project needs, such as:
20
+
21
+ - stack
22
+ - overlays
23
+ - presets and preset parameters
24
+ - output path
25
+ - custom image or container definition
26
+ - environment-related settings
27
+ - additional generated features and other supported customization inputs
28
+
29
+ ## 3. Run standard initialization
30
+
31
+ ```bash
32
+ npm run init
33
+ ```
34
+
35
+ Expected result:
36
+
37
+ - the project config file supplies default generation intent
38
+ - only still-missing required values are collected interactively
39
+ - the generated output matches the declared setup and supported customization
40
+ settings
41
+
42
+ ## 4. Override a value for one run
43
+
44
+ ```bash
45
+ npm run init -- --output ./tmp-devcontainer
46
+ ```
47
+
48
+ Expected result:
49
+
50
+ - the direct command value wins for that run only
51
+ - the committed project config remains the default source of truth
52
+
53
+ ## 5. Use the same config in automation
54
+
55
+ Run initialization from CI or another scripted workflow in a repository that
56
+ contains the committed project config.
57
+
58
+ Expected result:
59
+
60
+ - non-interactive runs use declared defaults without prompting for already
61
+ declared values
62
+ - repeated runs resolve the same configuration
63
+
64
+ ## 6. Regenerate from the project file
65
+
66
+ ```bash
67
+ npm run init -- regen
68
+ ```
69
+
70
+ Expected result:
71
+
72
+ - `regen` uses the repository project file when one exists
73
+ - the command does not require `--from-project` in that default case
74
+ - the generated output matches the project file's declared intent
75
+
76
+ ## 7. Preserve explicit manifest regeneration
77
+
78
+ ```bash
79
+ npm run init -- --from-manifest ./.devcontainer/superposition.json --no-interactive
80
+ ```
81
+
82
+ Expected result:
83
+
84
+ - the manifest remains the persisted input source for that run
85
+ - repository project config does not silently override it
86
+
87
+ ## 8. Reject conflicting source modes early
88
+
89
+ ```bash
90
+ npm run init -- init --from-project --stack compose
91
+ ```
92
+
93
+ Expected result:
94
+
95
+ - the command fails before generation
96
+ - the error explains that persisted-input source flags cannot be mixed with
97
+ clean-generation selection flags
98
+
99
+ ## 9. Validate parity for supported customization inputs
100
+
101
+ For any supported customization input that can be expressed through the existing
102
+ clean-generation path:
103
+
104
+ - declare it in the project config file
105
+ - run generation
106
+ - confirm the final generated output matches the equivalent clean-generation
107
+ result
108
+
109
+ Examples of parity checks:
110
+
111
+ - custom image or container definition
112
+ - environment-related settings
113
+ - preset glue values
114
+ - additional generated features
115
+
116
+ ## 10. Maintainer workflow review
117
+
118
+ Review result for `SC-003`:
119
+
120
+ - a maintainer can create or update `.superposition.yml`, run `npm run init -- --no-interactive`, and inspect the generated output without reconstructing a long command
121
+ - the documented workflow keeps the committed project config as the source of truth while still allowing one-run CLI overrides
122
+
123
+ ## 11. Verification record
124
+
125
+ Validated during implementation:
126
+
127
+ - targeted regression tests for project-config discovery, precedence, manifest isolation, no-config fallback, and customization parity
128
+ - targeted regression tests for explicit `--from-project`, implicit project-file
129
+ `regen`, and source-conflict validation
130
+ - `npm test`
131
+ - `npm run lint`
132
+ - `npm run test:smoke`
133
+
134
+ Observed outcomes:
135
+
136
+ - valid project-config driven runs generated the expected manifest and devcontainer output
137
+ - `regen` used the repository project file by default when present and still
138
+ allowed explicit manifest-based regeneration
139
+ - `--no-interactive` now works with a repository-root project config and still fails without any persisted input source
140
+ - explicit `--from-manifest` runs ignored repository project-config defaults as required
@@ -0,0 +1,144 @@
1
+ # Research: Project Configuration File
2
+
3
+ ## Decision 1: Treat project config as a partial-answer source in the existing init flow
4
+
5
+ **Decision**: Load `.superposition.yml` or `superposition.yml` into the same
6
+ partial-answer merge flow already used for direct command input and manifest
7
+ translation.
8
+
9
+ **Rationale**: The repository already has `QuestionnaireAnswers`,
10
+ `buildAnswersFromCliArgs`, `buildAnswersFromManifest`, and `mergeAnswers`.
11
+ Reusing that path keeps generation behavior aligned across interactive, CLI,
12
+ manifest, and project-config inputs.
13
+
14
+ **Alternatives considered**:
15
+
16
+ - Build a separate config-only generation pipeline: rejected because it would
17
+ duplicate behavior and drift from the main generation path.
18
+ - Translate project config into a manifest before generation: rejected because
19
+ the project config is intended to be the human-authored source of intent, not
20
+ a derived artifact.
21
+
22
+ ## Decision 2: Keep explicit manifest mode separate from project-config defaults
23
+
24
+ **Decision**: Project config is the default persisted input source for standard
25
+ initialization, but explicit manifest-based runs remain a separate mode and do
26
+ not merge project-config values silently.
27
+
28
+ **Rationale**: The feature spec explicitly preserves manifest-based regeneration
29
+ as a separate path. Mixing the two persisted inputs would make source-of-truth
30
+ selection ambiguous and weaken predictability.
31
+
32
+ **Alternatives considered**:
33
+
34
+ - Always merge project config into manifest-based runs: rejected because explicit
35
+ manifest input is a stronger per-run instruction.
36
+ - Replace manifest workflows entirely: rejected because it would break existing
37
+ regeneration behavior and expand scope.
38
+
39
+ ## Decision 3: Support project-file based regeneration as a first-class persisted input mode
40
+
41
+ **Decision**: `regen` supports the repository project file as a persisted input
42
+ source, and it may use that source implicitly when no conflicting source or
43
+ clean-generation selection flags are present.
44
+
45
+ **Rationale**: The project file is now a version-controlled source of truth, so
46
+ regeneration should not force teams back to a generated manifest when the
47
+ project file already expresses the supported intent.
48
+
49
+ **Alternatives considered**:
50
+
51
+ - Keep `regen` manifest-only: rejected because it would create an arbitrary
52
+ split between initialization and regeneration for the same declared intent.
53
+ - Require `--from-project` for every project-file based regen: rejected because
54
+ the default regen path should be able to use the repository source of truth
55
+ directly when no ambiguity exists.
56
+
57
+ ## Decision 4: Define parity in terms of supported clean-generation inputs
58
+
59
+ **Decision**: “Full parity” means every currently supported clean-generation
60
+ input that materially affects generated output can be declared in the project
61
+ config file, including customization surfaces such as custom images,
62
+ editor/minimal settings, preset glue, environment-related settings, and
63
+ additional generated features already represented by the generation flow.
64
+
65
+ **Rationale**: The user value is not just basic overlay selection; it is a
66
+ declarative source of truth for the full supported generation surface. Limiting
67
+ project config to a subset would force teams back to long commands for the most
68
+ important customizations.
69
+
70
+ **Alternatives considered**:
71
+
72
+ - Support only stack and overlays first: rejected because it would not satisfy
73
+ the parity requirement in the approved spec.
74
+ - Allow arbitrary raw devcontainer fragments in project config: rejected because
75
+ it would blur the boundary between supported generation inputs and unmanaged
76
+ custom output.
77
+
78
+ ## Decision 5: Restrict discovery to the repository root and fail on dual-file ambiguity
79
+
80
+ **Decision**: Discover project config only in the current repository root and
81
+ fail if both supported filenames exist.
82
+
83
+ **Rationale**: The feature is explicitly project-level. Root-only discovery is
84
+ predictable for local workflows and CI, and dual-file failure preserves a
85
+ single visible source of truth.
86
+
87
+ **Alternatives considered**:
88
+
89
+ - Search parent directories: rejected because it risks binding nested work to
90
+ the wrong config.
91
+ - Prefer one filename silently: rejected because ambiguity should be surfaced,
92
+ not hidden.
93
+
94
+ ## Decision 6: Validation must happen before generation and name the offending config entry
95
+
96
+ **Decision**: Project-config validation fails before generation begins and
97
+ reports syntax errors, unsupported keys, unsupported values, conflicts, missing
98
+ required values, and ambiguity in terms of the file content or repository state
99
+ the user must correct.
100
+
101
+ **Rationale**: Declarative workflows are only trustworthy if failures point back
102
+ to the committed source of truth rather than forcing users to infer hidden merge
103
+ behavior.
104
+
105
+ **Alternatives considered**:
106
+
107
+ - Let composition fail later: rejected because it hides whether the problem is
108
+ config input or generation logic.
109
+ - Ignore unknown keys: rejected because it would make committed config content
110
+ misleading.
111
+
112
+ ## Decision 7: Persisted-input source conflicts must fail before generation
113
+
114
+ **Decision**: `--from-project` and `--from-manifest` are mutually exclusive,
115
+ and persisted-input source modes fail fast when combined with clean-generation
116
+ selection flags such as stack, overlays, or preset selection.
117
+
118
+ **Rationale**: Source selection must stay explicit and predictable. Allowing
119
+ multiple persisted-input sources or mixing source modes with structural
120
+ generation selection flags would make the effective source of truth ambiguous.
121
+
122
+ **Alternatives considered**:
123
+
124
+ - Merge persisted-input sources in precedence order: rejected because it hides
125
+ which source actually defines the run.
126
+ - Allow source modes plus structural overrides: rejected because it weakens the
127
+ contract of deliberate source selection.
128
+
129
+ ## Decision 8: Verification must include parity cases, not only happy-path loading
130
+
131
+ **Decision**: Verification covers clean-generation parity for supported
132
+ customization inputs in addition to discovery, precedence, and validation
133
+ behavior.
134
+
135
+ **Rationale**: The highest-risk regressions are cases where project config loads
136
+ but silently loses part of the intended output surface, especially customization
137
+ settings that teams expect to be declarative.
138
+
139
+ **Alternatives considered**:
140
+
141
+ - Test only project-config discovery: rejected because discovery alone does not
142
+ prove parity.
143
+ - Rely on manual parity checks only: rejected because user-visible generation
144
+ behavior needs automated regression protection.
@@ -0,0 +1,130 @@
1
+ # Feature Specification: Project Configuration File
2
+
3
+ **Feature Branch**: `002-superposition-config-file`
4
+ **Created**: 2026-03-11
5
+ **Status**: Final
6
+ **Input**: Add a repository-root project config file so teams and automation can generate the same environment from committed declarative setup instead of reconstructing long CLI commands.
7
+
8
+ > Use repo-relative Markdown links for repository files. The root `README.md`
9
+ > is the only exception and may use package-friendly hosted URLs.
10
+
11
+ ## Review & Approval _(mandatory before implementation)_
12
+
13
+ - **Spec Path**: `docs/specs/002-superposition-config-file/spec.md`
14
+ - **Commit Status**: Committed
15
+ - **Review Status**: Approved
16
+ - **Implementation Gate**: No implementation code may begin until this spec is committed and reviewed.
17
+
18
+ ## User Scenarios & Testing _(mandatory)_
19
+
20
+ ### User Story 1 - Generate from committed project config (Priority: P1)
21
+
22
+ A project maintainer defines the desired development environment in a single repository-root config file so any teammate can generate the same stack, overlay set, output target, and supported customizations without reconstructing a long command.
23
+
24
+ **Why this priority**: This is the core user value. It turns setup intent into a durable, reviewable project artifact instead of a one-off shell command.
25
+
26
+ **Independent Test**: Place a valid `.superposition.yml` or `superposition.yml` in the repository root, run the generation flow without supplying the equivalent long-form options, and confirm the generated output matches the declared stack, overlay selection, output location, and supported customization settings.
27
+
28
+ **Acceptance Scenarios**:
29
+
30
+ 1. **Given** a repository with a valid project config file in its root that defines stack, overlay selections, output location, and supported customization settings, **When** a maintainer runs the generation flow from that repository root, **Then** the tool uses those values as the starting configuration for generation.
31
+ 2. **Given** a repository with a committed project config file, **When** a teammate clones the repository and runs the same generation flow from a fresh checkout, **Then** they receive the same effective project setup without needing the original author’s shell history or copied command examples.
32
+
33
+ ---
34
+
35
+ ### User Story 2 - Use config-driven setup in automation (Priority: P2)
36
+
37
+ A team uses the same committed project config file in CI or scripted workflows so environment generation is repeatable, unattended, and insulated from copied command examples.
38
+
39
+ **Why this priority**: Declarative setup is most valuable when it works in unattended workflows and shared operational contexts.
40
+
41
+ **Independent Test**: Run the generation flow in a non-interactive context from a repository that contains a valid project config file and confirm it completes with no prompt for values already defined in the file, while still allowing explicit per-run overrides.
42
+
43
+ **Acceptance Scenarios**:
44
+
45
+ 1. **Given** a non-interactive workflow and a valid project config file, **When** the generation flow starts, **Then** it completes using the file-defined values without requiring interactive answers for those settings.
46
+ 2. **Given** a repository where the committed project config file is unchanged, **When** the automation workflow runs repeatedly, **Then** each run resolves the same requested configuration and any direct command overrides affect only that run.
47
+ 3. **Given** a repository with a valid project config file and no conflicting persisted-input flag or clean-generation selection flags, **When** a user runs `init --no-interactive` or `regen` in the default project-file mode, **Then** the tool uses the project file as the persisted input source without requiring `--from-project`.
48
+
49
+ ---
50
+
51
+ ### User Story 3 - Correct invalid or ambiguous config quickly (Priority: P3)
52
+
53
+ A contributor receives clear guidance when the project config file is invalid, incomplete, or ambiguous so they can fix the committed source of truth instead of debugging generated output or hidden fallback behavior.
54
+
55
+ **Why this priority**: Declarative workflows only improve team reliability if configuration problems are surfaced clearly and early.
56
+
57
+ **Independent Test**: Introduce invalid entries, unsupported values, missing required selections for non-interactive use, or ambiguous file conditions and verify the tool stops before generation with actionable guidance tied to the file content or repository state.
58
+
59
+ **Acceptance Scenarios**:
60
+
61
+ 1. **Given** a project config file with unsupported keys, unsupported values, or conflicting selections, **When** the generation flow validates the file, **Then** it stops before generating files and reports each issue in terms the contributor can correct.
62
+ 2. **Given** both supported project config filenames are present in the same repository, **When** the generation flow starts, **Then** it stops and instructs the user to keep only one project config file so the source of truth is unambiguous.
63
+
64
+ ### Edge Cases
65
+
66
+ - What happens when no project config file exists? The current interactive and flag-driven flows remain available without behavior changes.
67
+ - What happens when a project config file defines only part of the setup? The tool uses the provided values and continues to collect any still-required missing choices through the existing flow.
68
+ - How does the system handle explicit command input that conflicts with the project config file? Explicit command input takes precedence for that run, and the user can still keep the file as the shared default.
69
+ - How does the system handle an explicit manifest-based run? The explicit manifest remains the persisted input source for that run, and the project config file does not silently override it.
70
+ - How does the system handle explicit project-file or manifest-source flags that are combined with each other or with clean-generation selection flags such as stack, overlay, or preset selection? It fails before generation and tells the user to choose exactly one persisted input source for that run.
71
+ - How does the system handle `init --no-interactive` or `regen` when a valid project config file exists and no other persisted-input source or clean-generation selection flags are provided? It may use the project file implicitly as the persisted input source for that run.
72
+ - How does the system handle supported customizations such as environment settings, custom container definitions, or additional generated features? Those values are treated as first-class generation inputs and must round-trip through the project config file without being dropped.
73
+ - How does the system handle unsupported overlay IDs, invalid categories, or conflicting selections in the project config file? It fails validation before generation and explains the invalid entries.
74
+ - How does the system handle both `.superposition.yml` and `superposition.yml` in one repository? It treats this as an error to avoid ambiguity.
75
+
76
+ ## Requirements _(mandatory)_
77
+
78
+ ### Functional Requirements
79
+
80
+ - **FR-001**: The system MUST support exactly two project-level configuration filenames for this feature: `.superposition.yml` and `superposition.yml`.
81
+ - **FR-002**: The system MUST look for the project config file only in the repository root from which the generation flow is run.
82
+ - **FR-003**: The system MUST treat the project config file as the default persisted input source for standard initialization when an explicit manifest input is not provided.
83
+ - **FR-004**: The system MUST read project config values into the same setup decisions already available through interactive answers and direct command input, including stack choice, overlay selections, preset selections, output location, and other generation options that materially affect the resulting setup.
84
+ - **FR-005**: The system MUST allow every supported clean-generation input that materially affects generated output to be declared in `.superposition.yml` or `superposition.yml` instead of requiring a long command.
85
+ - **FR-006**: The system MUST support declaring customization inputs in the project config file, including custom container definitions, environment-related settings, additional generated features, and other first-class generation customizations that affect the resulting devcontainer output.
86
+ - **FR-007**: The system MUST preserve declared project-config customization inputs through generation so the resulting output reflects the same customization values selected for that run.
87
+ - **FR-008**: Users MUST be able to generate a project environment from a valid project config file without re-entering values already defined in that file.
88
+ - **FR-009**: The system MUST allow explicit command input supplied for a run to override conflicting values from the project config file for that run only.
89
+ - **FR-010**: The system MUST preserve the current interactive and flag-driven behavior for users who do not provide a project config file.
90
+ - **FR-011**: The system MUST validate the project config file before generating output and MUST report invalid YAML, unsupported keys, unsupported values, missing required values, or conflicting selections with actionable correction guidance.
91
+ - **FR-012**: The system MUST stop and report an ambiguity error when both supported project config filenames are present in the same repository.
92
+ - **FR-013**: The system MUST produce the same effective project setup from a project config file as it would from an equivalent set of direct user selections across the full supported declaration surface.
93
+ - **FR-014**: The system MUST allow a partially defined project config file to act as shared defaults while still collecting any remaining required choices through the existing user flow.
94
+ - **FR-015**: The system MUST keep explicit manifest-based runs as a separate persisted-input mode and MUST NOT silently merge project config values into a run that was explicitly started from a manifest.
95
+ - **FR-016**: The system MUST support an explicit `--from-project` source-selection mode for both initialization and regeneration flows so users can deliberately choose the repository project file as the persisted input source for a run.
96
+ - **FR-017**: The system MUST allow `init --no-interactive` and `regen` to use the repository project file implicitly when a valid project config file exists and no other persisted-input source flag or clean-generation selection flags are supplied.
97
+ - **FR-018**: The system MUST reject conflicting persisted-input source combinations before generation, including `--from-project` with `--from-manifest` and either source-selection mode combined with clean-generation selection flags such as stack, overlay, or preset selection.
98
+ - **FR-019**: The system MUST document how teams create, commit, validate, and use the project config file in local development, regeneration, and automation workflows, including how parity with clean generation applies to supported customization inputs and how source-selection conflicts are resolved.
99
+
100
+ ### Key Entities _(include if feature involves data)_
101
+
102
+ - **Project Configuration File**: The committed repository-root definition of desired setup choices, including filename, declared setup values, supported customization inputs, and whether it is the only supported config file present.
103
+ - **Generation Request**: The effective set of choices used for one generation run after combining defaults, project config values, any explicit command input, and, when explicitly requested, manifest-based input, including supported customization inputs.
104
+ - **Customization Input**: A supported user-configurable generation setting beyond basic stack and overlay selection, such as custom container definitions, environment-related settings, or additional generated features that alter the final output.
105
+ - **Validation Result**: The user-facing outcome of checking the project config file, including syntax problems, unsupported entries, conflict findings, ambiguity conditions, and corrective guidance.
106
+
107
+ ## Dependencies & Impact _(mandatory)_
108
+
109
+ - **Affected Areas**: Standard initialization workflow, clean-generation parity, supported customization handling, manifest-based regeneration boundaries, project-file based regeneration boundaries, CLI usage patterns, onboarding workflow, CI/CD workflow, user documentation
110
+ - **Compatibility Impact**: Backward compatible
111
+ - **Required Documentation Updates**: README.md, workflow and examples documentation, quickstart guidance, CHANGELOG.md
112
+ - **Verification Plan**: Unit tests for config resolution and validation, integration tests for config-driven generation, smoke tests for representative stacks, manual validation for onboarding and automation flows
113
+
114
+ ## Assumptions
115
+
116
+ - The project config file becomes the team-readable source of truth for default setup intent, including supported customization inputs, but it does not remove support for current interactive, flag-driven, or explicit manifest-based flows.
117
+ - Explicit command input remains the highest-precedence input for a single run so users can make temporary overrides without editing the shared config file.
118
+ - `--from-project` and `--from-manifest` are mutually exclusive persisted-input modes rather than additive sources for one run.
119
+ - A single repository should contain at most one supported project config file so the source of truth stays deterministic and easy to explain.
120
+
121
+ ## Success Criteria _(mandatory)_
122
+
123
+ ### Measurable Outcomes
124
+
125
+ - **SC-001**: In validation testing, 95% of fresh repository checkouts that contain a valid project config file can generate the intended environment without requiring users to reconstruct setup options from prior command history.
126
+ - **SC-002**: In representative automation tests, 100% of successful non-interactive generation runs complete without prompting for any value already defined in the project config file and without changing the committed project config file.
127
+ - **SC-003**: In usability review, at least 90% of maintainers can define or update a project’s shared setup intent within 10 minutes using the documented config file workflow.
128
+ - **SC-004**: In invalid-configuration tests, 90% of failures identify the problematic file condition or config entry and the required correction in the first error output seen by the user.
129
+ - **SC-005**: In parity validation, every supported customization that can be expressed through the clean generation path can also be declared in the project config file and produces the same final generated output.
130
+ - **SC-006**: In CLI validation tests, 100% of runs that combine conflicting persisted-input source flags or mix a persisted-input source with clean-generation selection flags fail before generation with a source-conflict error that identifies the invalid combination.