container-superposition 0.1.4 → 0.1.6
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/README.md +74 -1370
- package/dist/scripts/init.js +350 -185
- package/dist/scripts/init.js.map +1 -1
- package/dist/tool/commands/adopt.d.ts +63 -0
- package/dist/tool/commands/adopt.d.ts.map +1 -0
- package/dist/tool/commands/adopt.js +1104 -0
- package/dist/tool/commands/adopt.js.map +1 -0
- package/dist/tool/commands/hash.d.ts +36 -0
- package/dist/tool/commands/hash.d.ts.map +1 -0
- package/dist/tool/commands/hash.js +242 -0
- package/dist/tool/commands/hash.js.map +1 -0
- package/dist/tool/commands/plan.d.ts +2 -0
- package/dist/tool/commands/plan.d.ts.map +1 -1
- package/dist/tool/commands/plan.js +262 -42
- package/dist/tool/commands/plan.js.map +1 -1
- package/dist/tool/schema/project-config.d.ts +17 -0
- package/dist/tool/schema/project-config.d.ts.map +1 -0
- package/dist/tool/schema/project-config.js +441 -0
- package/dist/tool/schema/project-config.js.map +1 -0
- package/dist/tool/schema/types.d.ts +39 -1
- package/dist/tool/schema/types.d.ts.map +1 -1
- package/dist/tool/utils/backup.d.ts +23 -0
- package/dist/tool/utils/backup.d.ts.map +1 -0
- package/dist/tool/utils/backup.js +123 -0
- package/dist/tool/utils/backup.js.map +1 -0
- package/docs/README.md +12 -2
- package/docs/adopt.md +202 -0
- package/docs/custom-patches.md +1 -1
- package/docs/discovery-commands.md +55 -3
- package/docs/examples.md +40 -6
- package/docs/filesystem-contract.md +58 -0
- package/docs/hash.md +183 -0
- package/docs/minimal-and-editor.md +1 -1
- package/docs/overlays.md +70 -0
- package/docs/presets-architecture.md +1 -1
- package/docs/presets.md +1 -1
- package/docs/publishing.md +36 -23
- package/docs/security.md +43 -0
- package/docs/specs/001-verbose-plan-graph/checklists/requirements.md +36 -0
- package/docs/specs/001-verbose-plan-graph/contracts/plan-verbose-output.md +96 -0
- package/docs/specs/001-verbose-plan-graph/data-model.md +111 -0
- package/docs/specs/001-verbose-plan-graph/plan.md +127 -0
- package/docs/specs/001-verbose-plan-graph/quickstart.md +106 -0
- package/docs/specs/001-verbose-plan-graph/research.md +100 -0
- package/docs/specs/001-verbose-plan-graph/spec.md +128 -0
- package/docs/specs/001-verbose-plan-graph/tasks.md +223 -0
- package/docs/specs/002-superposition-config-file/checklists/requirements.md +36 -0
- package/docs/specs/002-superposition-config-file/contracts/init-project-config.md +98 -0
- package/docs/specs/002-superposition-config-file/data-model.md +126 -0
- package/docs/specs/002-superposition-config-file/plan.md +213 -0
- package/docs/specs/002-superposition-config-file/quickstart.md +140 -0
- package/docs/specs/002-superposition-config-file/research.md +144 -0
- package/docs/specs/002-superposition-config-file/spec.md +136 -0
- package/docs/specs/002-superposition-config-file/tasks.md +215 -0
- package/docs/team-workflow.md +33 -1
- package/docs/workflows.md +139 -0
- package/features/cross-distro-packages/README.md +18 -0
- package/features/cross-distro-packages/devcontainer-feature.json +3 -3
- package/features/cross-distro-packages/install.sh +49 -7
- package/overlays/.presets/sdd.yml +84 -0
- package/overlays/README.md +7 -1
- package/overlays/amp/README.md +70 -0
- package/overlays/amp/devcontainer.patch.json +3 -0
- package/overlays/amp/overlay.yml +15 -0
- package/overlays/amp/setup.sh +21 -0
- package/overlays/amp/verify.sh +21 -0
- package/overlays/claude-code/README.md +83 -0
- package/overlays/claude-code/devcontainer.patch.json +3 -0
- package/overlays/claude-code/overlay.yml +15 -0
- package/overlays/claude-code/setup.sh +21 -0
- package/overlays/claude-code/verify.sh +21 -0
- package/overlays/gemini-cli/README.md +77 -0
- package/overlays/gemini-cli/devcontainer.patch.json +3 -0
- package/overlays/gemini-cli/overlay.yml +15 -0
- package/overlays/gemini-cli/setup.sh +21 -0
- package/overlays/gemini-cli/verify.sh +21 -0
- package/overlays/opencode/README.md +76 -0
- package/overlays/opencode/devcontainer.patch.json +3 -0
- package/overlays/opencode/overlay.yml +14 -0
- package/overlays/opencode/setup.sh +21 -0
- package/overlays/opencode/verify.sh +21 -0
- package/overlays/pandoc/README.md +279 -0
- package/overlays/pandoc/devcontainer.patch.json +14 -0
- package/overlays/pandoc/overlay.yml +19 -0
- package/overlays/pandoc/setup.sh +94 -0
- package/overlays/pandoc/verify.sh +13 -0
- package/overlays/spec-kit/README.md +181 -0
- package/overlays/spec-kit/devcontainer.patch.json +6 -0
- package/overlays/spec-kit/overlay.yml +19 -0
- package/overlays/spec-kit/setup.sh +45 -0
- package/overlays/spec-kit/verify.sh +33 -0
- package/overlays/windsurf-cli/README.md +69 -0
- package/overlays/windsurf-cli/devcontainer.patch.json +3 -0
- package/overlays/windsurf-cli/overlay.yml +15 -0
- package/overlays/windsurf-cli/setup.sh +21 -0
- package/overlays/windsurf-cli/verify.sh +21 -0
- package/package.json +1 -1
- package/tool/schema/config.schema.json +138 -9
|
@@ -0,0 +1,213 @@
|
|
|
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. The same schema
|
|
21
|
+
must also be writable from `adopt --project-file` so migration from an existing
|
|
22
|
+
`.devcontainer/` can produce a repository-root project config without inventing
|
|
23
|
+
a parallel declaration format. Persisted-input workflows must also support an
|
|
24
|
+
explicit repository-root override so users can run `init` or `regen` against a
|
|
25
|
+
different repository without first changing their shell working directory.
|
|
26
|
+
|
|
27
|
+
## Technical Context
|
|
28
|
+
|
|
29
|
+
**Language/Version**: TypeScript 5.3.3 on Node.js 20+
|
|
30
|
+
**Primary Dependencies**: Commander, chalk, boxen, js-yaml, ora, Inquirer
|
|
31
|
+
**Storage**: Filesystem-based project YAML config, `superposition.json`
|
|
32
|
+
manifests, overlay manifests, templates, and generated devcontainer artifacts
|
|
33
|
+
**Testing**: Vitest unit and command tests, shell-based smoke tests, TypeScript
|
|
34
|
+
compile checks
|
|
35
|
+
**Target Platform**: Node.js CLI on Linux, macOS, and Windows developer
|
|
36
|
+
environments
|
|
37
|
+
**Project Type**: CLI scaffolding tool
|
|
38
|
+
**Performance Goals**: Keep project-config discovery plus validation under 200
|
|
39
|
+
ms in representative repositories so initialization remains dominated by the
|
|
40
|
+
existing generation work rather than config loading
|
|
41
|
+
**Constraints**: Preserve backward compatibility for interactive, flag-driven,
|
|
42
|
+
explicit project-file, and explicit manifest-based flows; preserve source/dist
|
|
43
|
+
path compatibility with candidate-path resolution; maintain full parity between
|
|
44
|
+
supported clean generation inputs and project-config declarations; reject
|
|
45
|
+
conflicting persisted-input source combinations before generation; keep
|
|
46
|
+
ambiguity and validation failures user-facing and deterministic
|
|
47
|
+
**Scale/Scope**: Single feature spanning `scripts/init.ts`, shared schema/types,
|
|
48
|
+
config-loading helpers, command and composition tests, documentation, and
|
|
49
|
+
generation parity for supported customization inputs
|
|
50
|
+
|
|
51
|
+
## Constitution Check
|
|
52
|
+
|
|
53
|
+
_GATE: Must pass before Phase 0 research. Re-check after Phase 1 design and
|
|
54
|
+
before implementation._
|
|
55
|
+
|
|
56
|
+
- [x] Spec exists at `docs/specs/002-superposition-config-file/spec.md`.
|
|
57
|
+
- [x] Spec is committed and reviewed before implementation tasks or code begin.
|
|
58
|
+
- [x] Plan scope, compatibility impact, and complexity notes match the approved
|
|
59
|
+
spec.
|
|
60
|
+
- [x] Verification scope covers tests, smoke checks, and documentation updates
|
|
61
|
+
needed for the change.
|
|
62
|
+
- [x] User-visible changes include documentation updates and an `[Unreleased]`
|
|
63
|
+
`CHANGELOG.md` entry.
|
|
64
|
+
|
|
65
|
+
Gate status: Pass. Planning may proceed.
|
|
66
|
+
|
|
67
|
+
## Project Structure
|
|
68
|
+
|
|
69
|
+
### Documentation (this feature)
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
docs/specs/002-superposition-config-file/
|
|
73
|
+
├── plan.md
|
|
74
|
+
├── research.md
|
|
75
|
+
├── data-model.md
|
|
76
|
+
├── quickstart.md
|
|
77
|
+
├── contracts/
|
|
78
|
+
│ └── init-project-config.md
|
|
79
|
+
└── tasks.md
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Source Code (repository root)
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
scripts/
|
|
86
|
+
└── init.ts
|
|
87
|
+
|
|
88
|
+
tool/
|
|
89
|
+
├── __tests__/
|
|
90
|
+
│ ├── commands.test.ts
|
|
91
|
+
│ ├── composition.test.ts
|
|
92
|
+
│ ├── manifest-only.test.ts
|
|
93
|
+
│ ├── minimal-and-editor.test.ts
|
|
94
|
+
│ └── summary.test.ts
|
|
95
|
+
├── questionnaire/
|
|
96
|
+
│ └── composer.ts
|
|
97
|
+
├── schema/
|
|
98
|
+
│ ├── config.schema.json
|
|
99
|
+
│ ├── project-config.ts
|
|
100
|
+
│ └── types.ts
|
|
101
|
+
└── utils/
|
|
102
|
+
└── summary.ts
|
|
103
|
+
|
|
104
|
+
docs/
|
|
105
|
+
├── examples.md
|
|
106
|
+
├── workflows.md
|
|
107
|
+
└── specs/
|
|
108
|
+
|
|
109
|
+
README.md
|
|
110
|
+
CHANGELOG.md
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Structure Decision**: Keep the feature centered on `scripts/init.ts`, because
|
|
114
|
+
input discovery, CLI parsing, manifest handling, and answer merging already
|
|
115
|
+
converge there. Add one focused schema/helper module for project-config
|
|
116
|
+
discovery and validation, extend existing shared types for parity with clean
|
|
117
|
+
generation inputs, and keep verification concentrated in existing command and
|
|
118
|
+
composition test suites.
|
|
119
|
+
|
|
120
|
+
## Phase 0: Research
|
|
121
|
+
|
|
122
|
+
### Research Goals
|
|
123
|
+
|
|
124
|
+
- Confirm the correct precedence between project config, direct command input,
|
|
125
|
+
interactive completion, explicit `--from-project`, implicit project-file
|
|
126
|
+
source selection, and explicit manifest mode.
|
|
127
|
+
- Define what “full parity to clean generation” means for supported
|
|
128
|
+
customization inputs without introducing a second generation model.
|
|
129
|
+
- Confirm discovery, ambiguity handling, and validation boundaries for a
|
|
130
|
+
repository-root YAML config.
|
|
131
|
+
|
|
132
|
+
### Research Outputs
|
|
133
|
+
|
|
134
|
+
- [research.md](research.md)
|
|
135
|
+
|
|
136
|
+
## Phase 1: Design
|
|
137
|
+
|
|
138
|
+
### Data Model
|
|
139
|
+
|
|
140
|
+
- [data-model.md](data-model.md)
|
|
141
|
+
|
|
142
|
+
### Contracts
|
|
143
|
+
|
|
144
|
+
- [init-project-config.md](contracts/init-project-config.md)
|
|
145
|
+
|
|
146
|
+
### Quickstart
|
|
147
|
+
|
|
148
|
+
- [quickstart.md](quickstart.md)
|
|
149
|
+
|
|
150
|
+
## Implementation Approach
|
|
151
|
+
|
|
152
|
+
1. Add repository-root project-config discovery and validation to the standard
|
|
153
|
+
`init` flow and to `regen`, while keeping explicit manifest-based
|
|
154
|
+
regeneration behavior available as a separate mode.
|
|
155
|
+
2. Model project config as another partial-answer source that feeds the existing
|
|
156
|
+
`QuestionnaireAnswers` merge path.
|
|
157
|
+
3. Extend the supported config shape so it can declare every supported
|
|
158
|
+
clean-generation input, including customization surfaces already represented
|
|
159
|
+
in the current answer and generation flow.
|
|
160
|
+
4. Add explicit source-selection validation so `--from-project` and
|
|
161
|
+
`--from-manifest` remain mutually exclusive and cannot be combined with
|
|
162
|
+
clean-generation selection flags such as stack, overlays, or preset choices.
|
|
163
|
+
5. Preserve parity by ensuring project-config declarations yield the same final
|
|
164
|
+
generated output as equivalent direct user selections.
|
|
165
|
+
6. Add regression coverage for no-config fallback, override precedence,
|
|
166
|
+
project-file based regen, explicit `--from-project`, manifest isolation,
|
|
167
|
+
source-conflict validation, invalid config handling, ambiguity detection, and
|
|
168
|
+
customization parity.
|
|
169
|
+
7. Update docs and changelog entries so the declarative workflow, source
|
|
170
|
+
selection modes, and conflict rules are user-visible and auditable.
|
|
171
|
+
|
|
172
|
+
## Verification Strategy
|
|
173
|
+
|
|
174
|
+
- Add or update automated coverage for:
|
|
175
|
+
- repository-root project-config discovery
|
|
176
|
+
- no-config fallback behavior
|
|
177
|
+
- CLI-over-project-config precedence
|
|
178
|
+
- explicit `--from-project` behavior for `init` and `regen`
|
|
179
|
+
- implicit project-file selection for `init --no-interactive` and default
|
|
180
|
+
`regen`
|
|
181
|
+
- explicit manifest isolation from project-config defaults
|
|
182
|
+
- persisted-input source conflict validation (`--from-project`,
|
|
183
|
+
`--from-manifest`, and clean-generation selection flags)
|
|
184
|
+
- partial config completion through the existing questionnaire flow
|
|
185
|
+
- invalid YAML, unsupported keys or values, conflicts, and dual-file
|
|
186
|
+
ambiguity
|
|
187
|
+
- parity for supported customization inputs such as custom images, preset
|
|
188
|
+
glue, editor/minimal settings, environment-related settings, and additional
|
|
189
|
+
generated features
|
|
190
|
+
- Run `npm test`.
|
|
191
|
+
- Run `npm run lint`.
|
|
192
|
+
- Run `npm run test:smoke` when generation behavior changes across representative
|
|
193
|
+
stacks.
|
|
194
|
+
- Manually validate the scenarios in [quickstart.md](quickstart.md).
|
|
195
|
+
|
|
196
|
+
## Post-Design Constitution Check
|
|
197
|
+
|
|
198
|
+
- [x] Design preserves spec-first workflow and traces directly to the approved
|
|
199
|
+
spec.
|
|
200
|
+
- [x] Design preserves overlay contract integrity by extending the existing
|
|
201
|
+
answer and generation pipeline rather than inventing a parallel path.
|
|
202
|
+
- [x] Verification remains proportional to risk: automated tests, smoke
|
|
203
|
+
validation where applicable, and documentation updates are planned before
|
|
204
|
+
merge.
|
|
205
|
+
- [x] Documentation synchronization is explicit: `README.md`,
|
|
206
|
+
`docs/workflows.md`, `docs/examples.md`, `quickstart.md`, and `CHANGELOG.md`.
|
|
207
|
+
- [x] Simplicity and compatibility remain intact: project config is a default
|
|
208
|
+
persisted input source, explicit `--from-project` and explicit manifest
|
|
209
|
+
modes remain separate, and candidate-path compatibility stays required.
|
|
210
|
+
|
|
211
|
+
## Complexity Tracking
|
|
212
|
+
|
|
213
|
+
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,136 @@
|
|
|
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
|
+
3. **Given** a repository with an existing hand-crafted `.devcontainer/`, **When** a maintainer runs `adopt --project-file`, **Then** the tool writes a repository-root project config that captures the inferred stack, overlay selections, output path, and supported customization inputs from the adopted setup.
|
|
33
|
+
4. **Given** a maintainer is working outside the target repository, **When** they run `init --from-project --project-root <path>` or `regen --project-root <path>`, **Then** the tool resolves the project file and relative output paths from that selected repository root.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
### User Story 2 - Use config-driven setup in automation (Priority: P2)
|
|
38
|
+
|
|
39
|
+
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.
|
|
40
|
+
|
|
41
|
+
**Why this priority**: Declarative setup is most valuable when it works in unattended workflows and shared operational contexts.
|
|
42
|
+
|
|
43
|
+
**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.
|
|
44
|
+
|
|
45
|
+
**Acceptance Scenarios**:
|
|
46
|
+
|
|
47
|
+
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.
|
|
48
|
+
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.
|
|
49
|
+
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`.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### User Story 3 - Correct invalid or ambiguous config quickly (Priority: P3)
|
|
54
|
+
|
|
55
|
+
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.
|
|
56
|
+
|
|
57
|
+
**Why this priority**: Declarative workflows only improve team reliability if configuration problems are surfaced clearly and early.
|
|
58
|
+
|
|
59
|
+
**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.
|
|
60
|
+
|
|
61
|
+
**Acceptance Scenarios**:
|
|
62
|
+
|
|
63
|
+
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.
|
|
64
|
+
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.
|
|
65
|
+
|
|
66
|
+
### Edge Cases
|
|
67
|
+
|
|
68
|
+
- What happens when no project config file exists? The current interactive and flag-driven flows remain available without behavior changes.
|
|
69
|
+
- 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.
|
|
70
|
+
- 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.
|
|
71
|
+
- 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.
|
|
72
|
+
- 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.
|
|
73
|
+
- 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.
|
|
74
|
+
- 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.
|
|
75
|
+
- 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.
|
|
76
|
+
- How does the system handle both `.superposition.yml` and `superposition.yml` in one repository? It treats this as an error to avoid ambiguity.
|
|
77
|
+
- How does the system handle `adopt --project-file` when a repository already contains a supported project config file? It reuses that file path, and it must still stop on dual-file ambiguity so the source of truth stays deterministic.
|
|
78
|
+
- How does the system handle project-file or manifest discovery from outside the target repository? An explicit project-root option may redirect persisted-input discovery and relative output resolution to that repository root.
|
|
79
|
+
|
|
80
|
+
## Requirements _(mandatory)_
|
|
81
|
+
|
|
82
|
+
### Functional Requirements
|
|
83
|
+
|
|
84
|
+
- **FR-001**: The system MUST support exactly two project-level configuration filenames for this feature: `.superposition.yml` and `superposition.yml`.
|
|
85
|
+
- **FR-002**: The system MUST look for the project config file only in the repository root from which the generation flow is run.
|
|
86
|
+
- **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.
|
|
87
|
+
- **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.
|
|
88
|
+
- **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.
|
|
89
|
+
- **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.
|
|
90
|
+
- **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.
|
|
91
|
+
- **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.
|
|
92
|
+
- **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.
|
|
93
|
+
- **FR-010**: The system MUST preserve the current interactive and flag-driven behavior for users who do not provide a project config file.
|
|
94
|
+
- **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.
|
|
95
|
+
- **FR-012**: The system MUST stop and report an ambiguity error when both supported project config filenames are present in the same repository.
|
|
96
|
+
- **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.
|
|
97
|
+
- **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.
|
|
98
|
+
- **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.
|
|
99
|
+
- **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.
|
|
100
|
+
- **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.
|
|
101
|
+
- **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.
|
|
102
|
+
- **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.
|
|
103
|
+
- **FR-020**: The system MUST allow `adopt --project-file` to write a repository-root project config that represents the inferred adopted setup using the same supported declaration surface as other project-config workflows.
|
|
104
|
+
- **FR-021**: The system MUST allow `init` and `regen` to resolve project-file and manifest discovery from an explicitly selected repository root so users can run persisted-input workflows without changing their shell working directory first.
|
|
105
|
+
|
|
106
|
+
### Key Entities _(include if feature involves data)_
|
|
107
|
+
|
|
108
|
+
- **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.
|
|
109
|
+
- **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.
|
|
110
|
+
- **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.
|
|
111
|
+
- **Validation Result**: The user-facing outcome of checking the project config file, including syntax problems, unsupported entries, conflict findings, ambiguity conditions, and corrective guidance.
|
|
112
|
+
|
|
113
|
+
## Dependencies & Impact _(mandatory)_
|
|
114
|
+
|
|
115
|
+
- **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
|
|
116
|
+
- **Compatibility Impact**: Backward compatible
|
|
117
|
+
- **Required Documentation Updates**: README.md, workflow and examples documentation, quickstart guidance, CHANGELOG.md
|
|
118
|
+
- **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
|
|
119
|
+
|
|
120
|
+
## Assumptions
|
|
121
|
+
|
|
122
|
+
- 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.
|
|
123
|
+
- Explicit command input remains the highest-precedence input for a single run so users can make temporary overrides without editing the shared config file.
|
|
124
|
+
- `--from-project` and `--from-manifest` are mutually exclusive persisted-input modes rather than additive sources for one run.
|
|
125
|
+
- A single repository should contain at most one supported project config file so the source of truth stays deterministic and easy to explain.
|
|
126
|
+
|
|
127
|
+
## Success Criteria _(mandatory)_
|
|
128
|
+
|
|
129
|
+
### Measurable Outcomes
|
|
130
|
+
|
|
131
|
+
- **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.
|
|
132
|
+
- **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.
|
|
133
|
+
- **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.
|
|
134
|
+
- **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.
|
|
135
|
+
- **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.
|
|
136
|
+
- **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.
|