container-superposition 0.1.6 → 0.1.8

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 (238) hide show
  1. package/README.md +24 -15
  2. package/dist/scripts/init.js +1 -1534
  3. package/dist/scripts/init.js.map +1 -1
  4. package/dist/tool/cli/args.d.ts +20 -0
  5. package/dist/tool/cli/args.d.ts.map +1 -0
  6. package/dist/tool/cli/args.js +325 -0
  7. package/dist/tool/cli/args.js.map +1 -0
  8. package/dist/tool/cli/run.d.ts +2 -0
  9. package/dist/tool/cli/run.d.ts.map +1 -0
  10. package/dist/tool/cli/run.js +318 -0
  11. package/dist/tool/cli/run.js.map +1 -0
  12. package/dist/tool/commands/adopt.d.ts.map +1 -1
  13. package/dist/tool/commands/adopt.js +1 -27
  14. package/dist/tool/commands/adopt.js.map +1 -1
  15. package/dist/tool/commands/doctor.d.ts +3 -0
  16. package/dist/tool/commands/doctor.d.ts.map +1 -1
  17. package/dist/tool/commands/doctor.js +1068 -70
  18. package/dist/tool/commands/doctor.js.map +1 -1
  19. package/dist/tool/commands/explain.d.ts.map +1 -1
  20. package/dist/tool/commands/explain.js +18 -0
  21. package/dist/tool/commands/explain.js.map +1 -1
  22. package/dist/tool/commands/migrate.d.ts +7 -0
  23. package/dist/tool/commands/migrate.d.ts.map +1 -0
  24. package/dist/tool/commands/migrate.js +52 -0
  25. package/dist/tool/commands/migrate.js.map +1 -0
  26. package/dist/tool/questionnaire/answers.d.ts +16 -0
  27. package/dist/tool/questionnaire/answers.d.ts.map +1 -0
  28. package/dist/tool/questionnaire/answers.js +102 -0
  29. package/dist/tool/questionnaire/answers.js.map +1 -0
  30. package/dist/tool/questionnaire/composer.d.ts +3 -3
  31. package/dist/tool/questionnaire/composer.d.ts.map +1 -1
  32. package/dist/tool/questionnaire/composer.js +902 -37
  33. package/dist/tool/questionnaire/composer.js.map +1 -1
  34. package/dist/tool/questionnaire/presets.d.ts +60 -0
  35. package/dist/tool/questionnaire/presets.d.ts.map +1 -0
  36. package/dist/tool/questionnaire/presets.js +164 -0
  37. package/dist/tool/questionnaire/presets.js.map +1 -0
  38. package/dist/tool/questionnaire/questionnaire.d.ts +10 -0
  39. package/dist/tool/questionnaire/questionnaire.d.ts.map +1 -0
  40. package/dist/tool/questionnaire/questionnaire.js +580 -0
  41. package/dist/tool/questionnaire/questionnaire.js.map +1 -0
  42. package/dist/tool/schema/manifest-migrations.d.ts +5 -0
  43. package/dist/tool/schema/manifest-migrations.d.ts.map +1 -1
  44. package/dist/tool/schema/manifest-migrations.js +45 -0
  45. package/dist/tool/schema/manifest-migrations.js.map +1 -1
  46. package/dist/tool/schema/overlay-loader.d.ts.map +1 -1
  47. package/dist/tool/schema/overlay-loader.js +25 -0
  48. package/dist/tool/schema/overlay-loader.js.map +1 -1
  49. package/dist/tool/schema/project-config.d.ts +14 -2
  50. package/dist/tool/schema/project-config.d.ts.map +1 -1
  51. package/dist/tool/schema/project-config.js +277 -34
  52. package/dist/tool/schema/project-config.js.map +1 -1
  53. package/dist/tool/schema/target-rules.d.ts +78 -0
  54. package/dist/tool/schema/target-rules.d.ts.map +1 -0
  55. package/dist/tool/schema/target-rules.js +367 -0
  56. package/dist/tool/schema/target-rules.js.map +1 -0
  57. package/dist/tool/schema/types.d.ts +123 -12
  58. package/dist/tool/schema/types.d.ts.map +1 -1
  59. package/dist/tool/utils/merge.d.ts.map +1 -1
  60. package/dist/tool/utils/merge.js +9 -0
  61. package/dist/tool/utils/merge.js.map +1 -1
  62. package/dist/tool/utils/parameters.d.ts +76 -0
  63. package/dist/tool/utils/parameters.d.ts.map +1 -0
  64. package/dist/tool/utils/parameters.js +125 -0
  65. package/dist/tool/utils/parameters.js.map +1 -0
  66. package/dist/tool/utils/paths.d.ts +2 -0
  67. package/dist/tool/utils/paths.d.ts.map +1 -0
  68. package/dist/tool/utils/paths.js +31 -0
  69. package/dist/tool/utils/paths.js.map +1 -0
  70. package/docs/creating-overlays.md +151 -2
  71. package/docs/deployment-targets.md +88 -56
  72. package/docs/examples.md +20 -17
  73. package/docs/filesystem-contract.md +5 -0
  74. package/docs/minimal-and-editor.md +65 -5
  75. package/docs/overlay-imports.md +202 -101
  76. package/docs/overlays.md +162 -34
  77. package/docs/quick-reference.md +99 -0
  78. package/docs/specs/003-mkdocs2-overlay/spec.md +114 -0
  79. package/docs/specs/004-doctor-fix/spec.md +70 -0
  80. package/docs/specs/005-cuda-overlay/spec.md +101 -0
  81. package/docs/specs/006-rocm-overlay/spec.md +109 -0
  82. package/docs/specs/007-init-project-file/spec.md +66 -0
  83. package/docs/specs/007-target-aware-generation/spec.md +126 -0
  84. package/docs/specs/008-project-file-canonical/spec.md +83 -0
  85. package/docs/specs/009-project-env/spec.md +147 -0
  86. package/docs/specs/010-compose-env-materialization/spec.md +130 -0
  87. package/docs/specs/011-overlay-parameters/spec.md +235 -0
  88. package/overlays/.shared/README.md +105 -21
  89. package/overlays/.shared/compose/common-healthchecks.md +60 -0
  90. package/overlays/.shared/compose/nvidia-gpu-devcontainer.yml +22 -0
  91. package/overlays/.shared/vscode/recommended-extensions.json +15 -11
  92. package/overlays/alertmanager/setup.sh +4 -19
  93. package/overlays/alertmanager/verify.sh +8 -9
  94. package/overlays/all/README.md +43 -0
  95. package/overlays/all/devcontainer.patch.json +6 -0
  96. package/overlays/all/overlay.yml +14 -0
  97. package/overlays/amp/setup.sh +5 -0
  98. package/overlays/bun/setup.sh +10 -1
  99. package/overlays/bun/verify.sh +6 -1
  100. package/overlays/claude-code/setup.sh +5 -0
  101. package/overlays/cloudflared/setup.sh +9 -12
  102. package/overlays/codex/README.md +9 -6
  103. package/overlays/codex/devcontainer.patch.json +7 -1
  104. package/overlays/codex/setup.sh +5 -0
  105. package/overlays/codex/verify.sh +8 -0
  106. package/overlays/comfyui/.env.example +34 -0
  107. package/overlays/comfyui/README.md +342 -0
  108. package/overlays/comfyui/devcontainer.patch.json +15 -0
  109. package/overlays/comfyui/docker-compose.yml +39 -0
  110. package/overlays/comfyui/overlay.yml +20 -0
  111. package/overlays/comfyui/setup.sh +36 -0
  112. package/overlays/comfyui/verify.sh +103 -0
  113. package/overlays/commitlint/setup.sh +5 -0
  114. package/overlays/cuda/README.md +179 -0
  115. package/overlays/cuda/devcontainer.patch.json +7 -0
  116. package/overlays/cuda/overlay.yml +17 -0
  117. package/overlays/cuda/setup.sh +32 -0
  118. package/overlays/cuda/verify.sh +38 -0
  119. package/overlays/devcontainer-cli/README.md +50 -0
  120. package/overlays/devcontainer-cli/devcontainer.patch.json +13 -0
  121. package/overlays/devcontainer-cli/overlay.yml +16 -0
  122. package/overlays/devcontainer-cli/setup.sh +14 -0
  123. package/overlays/direnv/devcontainer.patch.json +6 -0
  124. package/overlays/direnv/setup.sh +7 -6
  125. package/overlays/dotnet/setup.sh +14 -7
  126. package/overlays/duckdb/devcontainer.patch.json +1 -2
  127. package/overlays/gcloud/devcontainer.patch.json +0 -6
  128. package/overlays/gcloud/setup.sh +51 -0
  129. package/overlays/gemini-cli/setup.sh +5 -0
  130. package/overlays/git-helpers/devcontainer.patch.json +2 -1
  131. package/overlays/go/setup.sh +15 -14
  132. package/overlays/jaeger/overlay.yml +2 -0
  133. package/overlays/just/setup.sh +5 -17
  134. package/overlays/k3d/README.md +201 -0
  135. package/overlays/k3d/devcontainer.patch.json +9 -0
  136. package/overlays/k3d/overlay.yml +19 -0
  137. package/overlays/k3d/setup.sh +34 -0
  138. package/overlays/k3d/verify.sh +38 -0
  139. package/overlays/keycloak/docker-compose.yml +6 -4
  140. package/overlays/keycloak/verify.sh +4 -3
  141. package/overlays/kind/devcontainer.patch.json +1 -2
  142. package/overlays/kind/setup.sh +8 -17
  143. package/overlays/minio/setup.sh +10 -18
  144. package/overlays/mkdocs/overlay.yml +2 -1
  145. package/overlays/mkdocs2/README.md +135 -0
  146. package/overlays/mkdocs2/devcontainer.patch.json +19 -0
  147. package/overlays/mkdocs2/overlay.yml +17 -0
  148. package/overlays/mkdocs2/setup.sh +67 -0
  149. package/overlays/mkdocs2/verify.sh +35 -0
  150. package/overlays/modern-cli-tools/devcontainer.patch.json +7 -1
  151. package/overlays/modern-cli-tools/setup.sh +21 -71
  152. package/overlays/mongodb/devcontainer.patch.json +0 -6
  153. package/overlays/mongodb/setup.sh +59 -0
  154. package/overlays/mysql/verify.sh +4 -3
  155. package/overlays/nats/.env.example +1 -1
  156. package/overlays/nats/README.md +1 -1
  157. package/overlays/nats/docker-compose.yml +1 -1
  158. package/overlays/ngrok/setup.sh +9 -6
  159. package/overlays/nodejs/setup.sh +5 -0
  160. package/overlays/ollama/.env.example +14 -0
  161. package/overlays/ollama/README.md +325 -0
  162. package/overlays/ollama/devcontainer.patch.json +14 -0
  163. package/overlays/ollama/docker-compose.yml +24 -0
  164. package/overlays/ollama/overlay.yml +22 -0
  165. package/overlays/ollama/setup.sh +106 -0
  166. package/overlays/ollama/verify.sh +99 -0
  167. package/overlays/open-webui/.env.example +5 -0
  168. package/overlays/open-webui/README.md +162 -0
  169. package/overlays/open-webui/devcontainer.patch.json +14 -0
  170. package/overlays/open-webui/docker-compose.yml +23 -0
  171. package/overlays/open-webui/overlay.yml +38 -0
  172. package/overlays/openapi-tools/devcontainer.patch.json +1 -2
  173. package/overlays/openapi-tools/setup.sh +9 -8
  174. package/overlays/opencode/setup.sh +5 -0
  175. package/overlays/otel-collector/overlay.yml +2 -0
  176. package/overlays/otel-collector/setup.sh +3 -16
  177. package/overlays/otel-demo-nodejs/verify.sh +8 -9
  178. package/overlays/otel-demo-python/verify.sh +16 -10
  179. package/overlays/pandoc/README.md +22 -15
  180. package/overlays/pandoc/devcontainer.patch.json +6 -2
  181. package/overlays/pandoc/setup.sh +217 -18
  182. package/overlays/pandoc/verify.sh +16 -4
  183. package/overlays/pgvector/.env.example +6 -0
  184. package/overlays/pgvector/README.md +215 -0
  185. package/overlays/pgvector/devcontainer.patch.json +23 -0
  186. package/overlays/pgvector/docker-compose.yml +32 -0
  187. package/overlays/pgvector/overlay.yml +44 -0
  188. package/overlays/playwright/devcontainer.patch.json +3 -1
  189. package/overlays/playwright/setup.sh +37 -0
  190. package/overlays/postgres/.env.example +5 -5
  191. package/overlays/postgres/devcontainer.patch.json +4 -4
  192. package/overlays/postgres/docker-compose.yml +15 -5
  193. package/overlays/postgres/overlay.yml +19 -1
  194. package/overlays/powershell/setup.sh +49 -13
  195. package/overlays/pre-commit/setup.sh +12 -3
  196. package/overlays/prometheus/overlay.yml +2 -0
  197. package/overlays/promtail/verify.sh +16 -10
  198. package/overlays/pulumi/devcontainer.patch.json +1 -1
  199. package/overlays/python/setup.sh +28 -9
  200. package/overlays/python/verify.sh +4 -2
  201. package/overlays/qdrant/.env.example +4 -0
  202. package/overlays/qdrant/README.md +216 -0
  203. package/overlays/qdrant/devcontainer.patch.json +20 -0
  204. package/overlays/qdrant/docker-compose.yml +25 -0
  205. package/overlays/qdrant/overlay.yml +40 -0
  206. package/overlays/redpanda/docker-compose.yml +3 -5
  207. package/overlays/rocm/README.md +227 -0
  208. package/overlays/rocm/devcontainer.patch.json +4 -0
  209. package/overlays/rocm/overlay.yml +17 -0
  210. package/overlays/rocm/setup.sh +45 -0
  211. package/overlays/rocm/verify.sh +47 -0
  212. package/overlays/rust/setup.sh +11 -18
  213. package/overlays/skaffold/README.md +256 -0
  214. package/overlays/skaffold/devcontainer.patch.json +9 -0
  215. package/overlays/skaffold/overlay.yml +20 -0
  216. package/overlays/skaffold/setup.sh +33 -0
  217. package/overlays/skaffold/verify.sh +24 -0
  218. package/overlays/spec-kit/setup.sh +7 -3
  219. package/overlays/sqlite/setup.sh +14 -14
  220. package/overlays/sqlserver/docker-compose.yml +3 -3
  221. package/overlays/sqlserver/verify.sh +22 -5
  222. package/overlays/tempo/verify.sh +16 -10
  223. package/overlays/tilt/devcontainer.patch.json +1 -2
  224. package/overlays/tilt/setup.sh +14 -4
  225. package/overlays/windsurf-cli/setup.sh +27 -4
  226. package/overlays/windsurf-cli/verify.sh +13 -3
  227. package/package.json +4 -2
  228. package/templates/scripts/setup-utils.sh +228 -0
  229. package/tool/schema/config.schema.json +141 -9
  230. package/tool/schema/overlay-manifest.schema.json +38 -0
  231. package/overlays/.shared/compose/common-healthchecks.yml +0 -38
  232. /package/overlays/otel-demo-nodejs/{Dockerfile-otel-demo-nodejs → Dockerfile} +0 -0
  233. /package/overlays/otel-demo-nodejs/{package-otel-demo-nodejs.json → package.json} +0 -0
  234. /package/overlays/otel-demo-nodejs/{server-otel-demo-nodejs.js → server.js} +0 -0
  235. /package/overlays/otel-demo-nodejs/{tracing-otel-demo-nodejs.js → tracing.js} +0 -0
  236. /package/overlays/otel-demo-python/{Dockerfile-otel-demo-python → Dockerfile} +0 -0
  237. /package/overlays/otel-demo-python/{app-otel-demo-python.py → app.py} +0 -0
  238. /package/overlays/otel-demo-python/{requirements-otel-demo-python.txt → requirements.txt} +0 -0
@@ -0,0 +1,101 @@
1
+ # Feature Specification: CUDA (NVIDIA GPU) Overlay
2
+
3
+ **Feature Branch**: `copilot/add-cuda-overlay-for-gpu`
4
+ **Created**: 2026-03-22
5
+ **Status**: Final
6
+ **Input**: Add a `cuda` overlay to enable NVIDIA GPU-accelerated workloads inside a dev container.
7
+
8
+ ## Review & Approval _(mandatory before implementation)_
9
+
10
+ - **Spec Path**: `docs/specs/005-cuda-overlay/spec.md`
11
+ - **Commit Status**: Committed
12
+ - **Review Status**: Approved
13
+ - **Implementation Gate**: No implementation code may begin until this spec is committed and reviewed.
14
+
15
+ ## User Scenarios & Testing _(mandatory)_
16
+
17
+ ### User Story 1 - GPU passthrough for ML/inference workloads (Priority: P1)
18
+
19
+ A developer wants to run NVIDIA GPU-accelerated workloads (ML training, inference, CUDA compute) inside a dev container without manually configuring Docker runtime flags.
20
+
21
+ **Why this priority**: GPU-accelerated dev containers require specific Docker runtime flags (`--gpus=all`) and VS Code devcontainer host requirements (`gpu: true`) that must be set correctly for the container to access the GPU. Without the overlay, users must add these manually and correctly every time.
22
+
23
+ **Independent Test**: Select the `cuda` overlay, rebuild the container, and confirm that `nvidia-smi` exits 0 and reports the GPU correctly.
24
+
25
+ **Acceptance Scenarios**:
26
+
27
+ 1. **Given** a user selects the `cuda` overlay, **When** the devcontainer is built, **Then** `devcontainer.json` includes `"runArgs": ["--gpus=all"]` and `"hostRequirements": {"gpu": true}`.
28
+ 2. **Given** the NVIDIA Container Toolkit is installed on the host, **When** the devcontainer starts, **Then** `nvidia-smi` is accessible inside the container.
29
+ 3. **Given** the container is running, **When** `setup.sh` executes, **Then** it reports whether `nvidia-smi` is available and prints a helpful message if it is not.
30
+
31
+ ---
32
+
33
+ ### User Story 2 - Conflict enforcement between cuda and rocm (Priority: P1)
34
+
35
+ A user selects both `cuda` and `rocm` and expects the tool to report a conflict, because only one GPU compute framework can be active at a time.
36
+
37
+ **Why this priority**: CUDA (NVIDIA) and ROCm (AMD) are mutually exclusive GPU compute frameworks. Allowing both would produce an incoherent configuration.
38
+
39
+ **Independent Test**: Attempt to generate a devcontainer with both `cuda` and `rocm` selected and confirm the tool surfaces a conflict and blocks generation.
40
+
41
+ **Acceptance Scenarios**:
42
+
43
+ 1. **Given** a user selects both `cuda` and `rocm`, **When** they run `container-superposition init`, **Then** the tool reports a conflict and prevents generation.
44
+ 2. **Given** `cuda` lists `rocm` in `conflicts`, **When** `rocm` is added in the future, **Then** `rocm` must also list `cuda` in its `conflicts` (bidirectional enforcement). Note: `rocm` does not exist yet; when it is added the reciprocal conflict must be declared in `overlays/rocm/overlay.yml`.
45
+
46
+ ---
47
+
48
+ ## Design
49
+
50
+ ### overlay.yml
51
+
52
+ ```yaml
53
+ id: cuda
54
+ name: CUDA (NVIDIA GPU)
55
+ description: NVIDIA CUDA libraries and GPU passthrough for containerized ML/inference workloads
56
+ category: dev
57
+ supports: []
58
+ requires: []
59
+ suggests: []
60
+ conflicts:
61
+ - rocm
62
+ tags:
63
+ - gpu
64
+ - cuda
65
+ - nvidia
66
+ - ml
67
+ - inference
68
+ ports: []
69
+ ```
70
+
71
+ ### devcontainer.patch.json
72
+
73
+ Set `runArgs` for GPU passthrough and `hostRequirements` to signal GPU need:
74
+
75
+ ```json
76
+ {
77
+ "runArgs": ["--gpus=all"],
78
+ "hostRequirements": { "gpu": true }
79
+ }
80
+ ```
81
+
82
+ ### setup.sh
83
+
84
+ - Check whether `nvidia-smi` is reachable inside the container.
85
+ - Print a helpful message if it is not (host driver / toolkit not configured).
86
+
87
+ ### verify.sh
88
+
89
+ - Assert `nvidia-smi` exits 0 (used by the `doctor` command).
90
+
91
+ ### README.md
92
+
93
+ - Clear prerequisites section (host drivers, NVIDIA Container Toolkit).
94
+ - Troubleshooting tips for common failure modes.
95
+ - Note that the overlay does not replace or install host drivers.
96
+
97
+ ## Out of Scope
98
+
99
+ - Installing or replacing host NVIDIA drivers.
100
+ - Guaranteeing version alignment between CUDA user-space libraries and the host kernel module.
101
+ - ROCm (AMD GPU) support — tracked separately.
@@ -0,0 +1,109 @@
1
+ # Feature Specification: ROCm (AMD GPU) Overlay
2
+
3
+ **Feature Branch**: `copilot/add-rocm-overlay`
4
+ **Created**: 2026-03-22
5
+ **Status**: Accepted
6
+ **Input**: Add a `rocm` overlay to enable AMD GPU-accelerated workloads inside a dev container.
7
+
8
+ ## Review & Approval _(mandatory before implementation)_
9
+
10
+ - **Spec Path**: `docs/specs/006-rocm-overlay/spec.md`
11
+ - **Commit Status**: Committed
12
+ - **Review Status**: Approved
13
+ - **Implementation Gate**: No implementation code may begin until this spec is committed and reviewed.
14
+
15
+ ## Overview
16
+
17
+ Add a `rocm` overlay to enable AMD GPU-accelerated workloads inside a dev container using the ROCm open software platform.
18
+
19
+ > **Note:** ROCm-in-container is a supported but more fragile path than CUDA. It depends heavily on the host kernel version, AMD driver stack, specific device support, and container runtime configuration. Treat this as a separate supported profile — not a drop-in equivalent of CUDA.
20
+
21
+ ## User Scenarios & Testing _(mandatory)_
22
+
23
+ ### User Story 1 - AMD GPU passthrough for ML/inference workloads (Priority: P1)
24
+
25
+ 1. **Given** a user selects the `rocm` overlay, **When** the devcontainer is built, **Then** `devcontainer.json` includes `"runArgs": ["--device=/dev/kfd", "--device=/dev/dri", "--group-add=video", "--group-add=render"]`.
26
+ 2. **Given** the AMD GPU drivers and ROCm runtime are installed on the host, **When** the devcontainer starts, **Then** `rocm-smi` is accessible inside the container.
27
+ 3. **Given** the container is running, **When** `setup.sh` executes, **Then** it reports whether `rocm-smi` is available and prints a helpful message if it is not.
28
+ 4. **Given** `rocm-smi` is not available, **When** `verify.sh` executes, **Then** it exits 1 for the `doctor` command.
29
+
30
+ ---
31
+
32
+ ## Prerequisites (host-side — out of scope for this overlay)
33
+
34
+ 1. Supported AMD GPU hardware (RDNA 2+, most CDNA — check [ROCm hardware support matrix](https://rocm.docs.amd.com/en/latest/compatibility/compatibility-matrix.html))
35
+ 2. AMD GPU drivers (`amdgpu`) installed on the host
36
+ 3. ROCm runtime installed on the host (or the container image bundles it)
37
+ 4. User added to the `render` and `video` groups, or appropriate device permissions set
38
+ 5. `/dev/kfd` and `/dev/dri` devices accessible in the container
39
+
40
+ ## Design
41
+
42
+ ### overlay.yml
43
+
44
+ ```yaml
45
+ id: rocm
46
+ name: ROCm (AMD GPU)
47
+ description: AMD ROCm libraries and GPU passthrough for containerized ML/inference workloads
48
+ category: dev
49
+ supports: []
50
+ requires: []
51
+ suggests: []
52
+ conflicts:
53
+ - cuda
54
+ tags:
55
+ - dev
56
+ - gpu
57
+ - rocm
58
+ - amd
59
+ - ml
60
+ - inference
61
+ ports: []
62
+ ```
63
+
64
+ ### devcontainer.patch.json
65
+
66
+ Set `runArgs` for AMD GPU device passthrough:
67
+
68
+ ```json
69
+ {
70
+ "runArgs": ["--device=/dev/kfd", "--device=/dev/dri", "--group-add=video", "--group-add=render"]
71
+ }
72
+ ```
73
+
74
+ - `/dev/kfd` — AMD Kernel Fusion Driver; required for ROCm compute
75
+ - `/dev/dri` — Direct Rendering Infrastructure; gives access to GPU render nodes
76
+ - `--group-add=video` and `--group-add=render` — add the container user to the groups that own the GPU device nodes
77
+
78
+ ### setup.sh
79
+
80
+ - Check whether `rocm-smi` or `rocminfo` is reachable inside the container.
81
+ - Print a helpful message if neither is found (host driver / ROCm not configured).
82
+
83
+ ### verify.sh
84
+
85
+ - Assert `rocm-smi` exits 0 (used by the `doctor` command).
86
+
87
+ ### README.md
88
+
89
+ Must include:
90
+
91
+ - Prominent prerequisites section
92
+ - Known limitations (kernel version coupling, device node names may vary)
93
+ - ROCm framework wheels (PyTorch ROCm, TensorFlow ROCm)
94
+ - Troubleshooting section
95
+ - Link to ROCm compatibility matrix
96
+ - Clear note that this overlay does not replace host drivers
97
+
98
+ ## Relationship to CUDA Overlay
99
+
100
+ - `cuda` and `rocm` must list each other in `conflicts` (bidirectional, per project rules)
101
+ - The `cuda` overlay already declares `rocm` in its `conflicts`
102
+ - CUDA is considered the primary GPU path; ROCm is a supported secondary path
103
+
104
+ ## Known Constraints and Caveats
105
+
106
+ - ROCm version support is tightly coupled to kernel and driver versions
107
+ - Device node names (`/dev/dri/renderD128`) may differ per host
108
+ - Some frameworks publish separate ROCm wheels
109
+ - Less forgiving than CUDA during setup — detailed troubleshooting is essential
@@ -0,0 +1,66 @@
1
+ # Feature Specification: `init --project-file`
2
+
3
+ **Feature Branch**: `copilot/sub-pr-121`
4
+ **Created**: 2026-03-23
5
+ **Status**: Final
6
+ **Input**: Extend the `init` command with a `--project-file` flag that persists the chosen init configuration into a repository-root project config file (creating `.superposition.yml` by default or updating an existing supported project config), aligning init runs with the project-config workflow.
7
+
8
+ ## Review & Approval _(mandatory before implementation)_
9
+
10
+ - **Spec Path**: `docs/specs/007-init-project-file/spec.md`
11
+ - **Commit Status**: Committed
12
+ - **Review Status**: Approved
13
+ - **Implementation Gate**: No implementation code may begin until this spec is committed and reviewed.
14
+
15
+ ## Summary
16
+
17
+ Allow `container-superposition init` to optionally write a repository-root
18
+ project config file (`.superposition.yml` by default, or the existing supported
19
+ project config path when one already exists) alongside the normal init output.
20
+
21
+ ## Requirements
22
+
23
+ - `init` MUST accept a `--project-file` flag.
24
+ - When `--project-file` is set, `init` MUST write a repository-root project
25
+ config that reflects the final selected configuration for that run.
26
+ - If the repository already contains exactly one supported project config file,
27
+ `init --project-file` MUST update that file instead of creating a second one.
28
+ - If no project config file exists, `init --project-file` MUST write
29
+ `.superposition.yml` at the repository root.
30
+ - The written project config MUST include supported fields represented by the
31
+ final init answers, including stack, base image, overlays, output path,
32
+ target, minimal mode, editor profile, preset, and preset choices.
33
+ - `init --project-file` MUST continue to write `superposition.json` the same way
34
+ current `init` runs do.
35
+ - Project config write errors MUST NOT suppress devcontainer generation success; they MUST be reported separately.
36
+
37
+ ## User Scenarios & Testing _(mandatory)_
38
+
39
+ ### User Story 1 - Write project config alongside devcontainer generation (Priority: P1)
40
+
41
+ A developer wants to run `init` once and have both a `.devcontainer/` folder and a root-level project config file created, so they can commit the project config and regenerate consistently later.
42
+
43
+ **Why this priority**: The `--project-file` flag is the primary new capability. Without it working correctly for a fresh project, the feature has no value.
44
+
45
+ **Independent Test**: Run `init --project-file` in a directory with no existing project config, then confirm that `.superposition.yml` is created at the repo root and reflects the chosen stack and overlays.
46
+
47
+ **Acceptance Scenarios**:
48
+
49
+ 1. **Given** a repository with no project config file, **When** the user runs `init --project-file`, **Then** `.superposition.yml` is created at the repository root with the selected stack, base image, overlays, and other init options.
50
+ 2. **Given** a repository with an existing `.superposition.yml`, **When** the user runs `init --project-file`, **Then** the existing file is updated (not a new file created) to reflect the newly selected configuration.
51
+ 3. **Given** the project config write fails (e.g., permission error), **When** `init --project-file` is run, **Then** the devcontainer generation still completes successfully and a clear error message is shown for the project-file failure only.
52
+
53
+ ---
54
+
55
+ ### User Story 2 - Update existing project config (Priority: P2)
56
+
57
+ A developer has an existing `superposition.yml` and wants to update it to reflect a changed overlay selection after re-running `init`.
58
+
59
+ **Why this priority**: Round-trip consistency (init → project config → regen) is the main value of the project-config workflow.
60
+
61
+ **Independent Test**: Create a `superposition.yml`, run `init --project-file` with different overlays, and confirm that the file is updated rather than a second file being created.
62
+
63
+ **Acceptance Scenarios**:
64
+
65
+ 1. **Given** a repository with exactly one supported project config file, **When** the user runs `init --project-file` with new overlay selections, **Then** only that existing file is updated and no second project config is created.
66
+ 2. **Given** two supported project config files exist simultaneously, **When** the user runs `init --project-file`, **Then** the command prints an error explaining that only one project config file should exist and does not proceed with the write.
@@ -0,0 +1,126 @@
1
+ # Feature Specification: Target-Aware Generation
2
+
3
+ **Feature Branch**: `copilot/feat-target-aware-generation`
4
+ **Created**: 2026-03-23
5
+ **Status**: Final
6
+ **Input**: Issue [feat] Target-aware generation — produce workspace artifacts and guidance for codespaces, gitpod, and devpod
7
+
8
+ ## Review & Approval _(mandatory before implementation)_
9
+
10
+ - **Spec Path**: `docs/specs/007-target-aware-generation/spec.md`
11
+ - **Commit Status**: Committed
12
+ - **Review Status**: APPROVED
13
+ - **Implementation Gate**: No implementation code may begin until this spec is committed and reviewed.
14
+
15
+ ## User Scenarios & Testing _(mandatory)_
16
+
17
+ ### User Story 1 — Generate codespaces artifacts (Priority: P1)
18
+
19
+ A user generates with `--target codespaces` and expects to receive Codespaces-specific files and
20
+ guidance alongside the normal devcontainer output.
21
+
22
+ **Acceptance:**
23
+
24
+ 1. `--target codespaces` → `devcontainer.json` extended with `hostRequirements`, `CODESPACES.md` written to `.devcontainer/`.
25
+ 2. `--target local` or no `--target` → no `CODESPACES.md`, no `hostRequirements` in devcontainer.
26
+
27
+ ### User Story 2 — Generate gitpod artifacts (Priority: P1)
28
+
29
+ A user generates with `--target gitpod` and expects a `.gitpod.yml` in the project root and
30
+ setup guidance inside `.devcontainer/`.
31
+
32
+ **Acceptance:**
33
+
34
+ 1. `--target gitpod` → `.gitpod.yml` at project root with tasks and port exposures from selected overlays; `GITPOD.md` written to `.devcontainer/`.
35
+ 2. `--target local` → no `.gitpod.yml`, no `GITPOD.md`.
36
+
37
+ ### User Story 3 — Generate devpod artifacts (Priority: P1)
38
+
39
+ A user generates with `--target devpod` and expects a `devpod.yaml` at the project root and
40
+ setup guidance inside `.devcontainer/`.
41
+
42
+ **Acceptance:**
43
+
44
+ 1. `--target devpod` → `devpod.yaml` at project root; `DEVPOD.md` written to `.devcontainer/`.
45
+ 2. `--target local` → no `devpod.yaml`, no `DEVPOD.md`.
46
+
47
+ ### User Story 4 — Local generation unchanged (Priority: P1)
48
+
49
+ When a user generates without specifying a target, or with `--target local`, the output must
50
+ not contain any non-local artifacts.
51
+
52
+ **Acceptance:**
53
+
54
+ 1. No `--target` flag → output identical to current behavior; no new files written.
55
+ 2. `--target local` (explicit) → same output as omitting `--target`.
56
+
57
+ ### User Story 5 — Regeneration from manifest with target (Priority: P2)
58
+
59
+ A user regenerates from an existing `superposition.json` that includes `"target": "gitpod"` and
60
+ expects the same Gitpod-specific artifacts without being prompted again.
61
+
62
+ **Acceptance:**
63
+
64
+ 1. Manifest with `target: gitpod` → regen produces `.gitpod.yml` and `GITPOD.md`.
65
+ 2. Manifest with no `target` or `target: local` → regen produces no target-specific artifacts.
66
+
67
+ ### User Story 6 — Target switching cleans up stale artifacts (Priority: P2)
68
+
69
+ A user regenerates with a different `--target` value and expects the previous target's
70
+ project-root artifacts to be removed.
71
+
72
+ **Acceptance:**
73
+
74
+ 1. Previous run was `--target gitpod` (`.gitpod.yml` exists); regeneration with `--target codespaces` → `.gitpod.yml` removed, `CODESPACES.md` written.
75
+ 2. Previous run was `--target devpod`; regeneration with `--target local` → `devpod.yaml` removed.
76
+
77
+ ## Technical Design
78
+
79
+ ### `TargetRule` interface
80
+
81
+ A `TargetRule` encapsulates everything about generating artifacts for one deployment target:
82
+
83
+ ```typescript
84
+ interface TargetRule {
85
+ target: DeploymentTarget;
86
+ /** Extra fields merged into devcontainer.json */
87
+ devcontainerPatch(context: TargetRuleContext): Partial<DevContainer>;
88
+ /** Files to write; keys are relative to outputPath, '../<name>' writes to project root */
89
+ generateFiles(context: TargetRuleContext): Map<string, string>;
90
+ /** All relative paths owned by this rule (for stale-cleanup on target switch) */
91
+ ownedFiles(): string[];
92
+ }
93
+ ```
94
+
95
+ ### Per-target rules
96
+
97
+ | Target | devcontainer.json change | Files in `.devcontainer/` | Files at project root |
98
+ | ------------ | ------------------------ | ------------------------- | --------------------- |
99
+ | `local` | none | none | none |
100
+ | `codespaces` | `hostRequirements` | `CODESPACES.md` | none |
101
+ | `gitpod` | none | `GITPOD.md` | `.gitpod.yml` |
102
+ | `devpod` | none | `DEVPOD.md` | `devpod.yaml` |
103
+
104
+ ### `SuperpositionManifest` update
105
+
106
+ Add `target?: DeploymentTarget` so regeneration reproduces the correct artifacts without
107
+ re-prompting.
108
+
109
+ ### Stale-artifact cleanup
110
+
111
+ On each generation, before writing new target artifacts:
112
+
113
+ 1. Read existing `superposition.json` from `outputPath` (if it exists).
114
+ 2. If `manifest.target !== answers.target`, identify previous target's owned project-root
115
+ files (e.g., `.gitpod.yml`) and remove them from the project root.
116
+
117
+ The `.devcontainer/`-local files are already handled by `cleanupStaleFiles` via `FileRegistry`.
118
+
119
+ ## Functional Requirements (from issue)
120
+
121
+ - **FR-001**: Target is a real generation input that changes produced artifacts.
122
+ - **FR-002**: `codespaces`, `gitpod`, `devpod` produce target-specific workspace artifacts.
123
+ - **FR-003**: `local` (explicit or default) produces no additional artifacts.
124
+ - **FR-009**: Regeneration from manifest reproduces target-aware output automatically.
125
+ - **FR-010**: Target switch between runs removes stale artifacts from the previous target.
126
+ - **FR-011**: Backward compatible — manifests without `target` or with `target: local` unchanged.
@@ -0,0 +1,83 @@
1
+ ---
2
+ Feature Branch: copilot/make-superposition-yml-canonical-input
3
+ Created: 2026-03-26
4
+ Status: Implementing
5
+ Input: GitHub issue #134
6
+ ---
7
+
8
+ # Spec: Make superposition.yml the Canonical Input
9
+
10
+ ## Overview
11
+
12
+ Make `superposition.yml` (the project config file) the required, canonical input for all
13
+ generation and regeneration flows. `superposition.json` (the manifest) becomes an output-only
14
+ artifact — a generated receipt, not an input source.
15
+
16
+ ## Motivation
17
+
18
+ Three entry points currently disagree on which file is authoritative, creating user confusion
19
+ and dead code paths. The newest code path (`generate`) already writes `superposition.yml`
20
+ first. This spec promotes that pattern to all entry points.
21
+
22
+ ## Behavioral Changes
23
+
24
+ ### `init` — Always writes `superposition.yml`
25
+
26
+ - Remove `--project-file` flag; writing the project config is now the default.
27
+ - Add `--no-scaffold` flag to skip generating `.devcontainer/` (for project-file-only runs).
28
+ - Scaffold (`.devcontainer/` generation) remains the default for backward compatibility.
29
+ - The project file is written before scaffolding; a scaffold failure does not lose the config.
30
+
31
+ ### `regen` — Reads `superposition.yml` only
32
+
33
+ - Default input: the project config file auto-discovered in the repository root.
34
+ - `--from-manifest <path>` is retained as a **deprecated hidden flag** that emits a warning
35
+ pointing toward `cs migrate`. Existing CI scripts that rely on it will still work but
36
+ receive a deprecation notice.
37
+ - If no project file exists and `superposition.json` is present: error with actionable
38
+ migration guidance: `Run 'cs migrate' to create a project file from your existing manifest.`
39
+ - If neither file exists: error with creation guidance.
40
+
41
+ ### `superposition.json` — Output only
42
+
43
+ - Still written by `composeDevContainer` / `generateManifestOnly` as before.
44
+ - No longer read as a generation input in the standard flow.
45
+ - Still read by `doctor` for diagnostics and drift detection.
46
+
47
+ ## New Commands
48
+
49
+ ### `cs migrate`
50
+
51
+ One-time migration from manifest-only repositories:
52
+
53
+ 1. Discovers or accepts `--from-manifest <path>` to locate `superposition.json`.
54
+ 2. Loads and validates the manifest (with auto-migration for old versions).
55
+ 3. Converts manifest to `ProjectConfigSelection` via the existing
56
+ `buildAnswersFromManifest → mergeAnswers → buildProjectConfigSelectionFromAnswers` pipeline.
57
+ 4. Discovers the output path for the project file (uses existing file if present, otherwise
58
+ defaults to `.superposition.yml`); `--force` to overwrite.
59
+ 5. Writes the project config YAML.
60
+ 6. Prints a success message with next-step guidance (`regen` to regenerate).
61
+
62
+ ## `doctor` Drift Detection
63
+
64
+ Once the project file is canonical, `doctor` can compare the two files:
65
+
66
+ - Load project file overlays (via `loadProjectConfig`).
67
+ - Load last-generated manifest overlays (via existing manifest loading).
68
+ - Report a new `project-file-drift` finding when the overlay sets differ.
69
+ - Suggest `regen` to reconcile.
70
+
71
+ ## Migration Considerations
72
+
73
+ | Repo state | Impact | Action |
74
+ | ----------------------------- | --------------------------------- | -------------------------------- |
75
+ | Has `superposition.yml` only | None — already correct | — |
76
+ | Has `superposition.json` only | `regen` errors | Run `cs migrate` once |
77
+ | Has both (consistent) | None — regen prefers project file | — |
78
+ | CI using `--from-manifest` | Warning on each run | Switch to `cs migrate` + `regen` |
79
+
80
+ ## Review & Approval Gate
81
+
82
+ Implementation proceeds with this spec committed. No further approval required for the
83
+ behavioral changes listed above.
@@ -0,0 +1,147 @@
1
+ # Feature Specification: Unified Project-Level Environment Variables
2
+
3
+ **Feature Branch**: `codex/project-env`
4
+ **Created**: 2026-03-29
5
+ **Status**: Implementing
6
+ **Input**: User request
7
+
8
+ ## Review & Approval _(mandatory before implementation)_
9
+
10
+ - **Spec Path**: `docs/specs/009-project-env/spec.md`
11
+ - **Commit Status**: Committed
12
+ - **Review Status**: Pending
13
+ - **Implementation Gate**: No implementation code may begin until this spec is committed and reviewed.
14
+
15
+ ## User Scenarios & Testing _(mandatory)_
16
+
17
+ ### User Story 1 — Define environment variables once for plain stack (Priority: P1)
18
+
19
+ A developer adds an `env:` block to `superposition.yml` on a `plain` stack and expects the
20
+ variables to appear in `devcontainer.json → remoteEnv` after regeneration.
21
+
22
+ **Why this priority**: The most common use case is a plain-stack project needing a handful of
23
+ environment variables visible inside the devcontainer without manually editing JSON files.
24
+
25
+ **Independent Test**: Create a `superposition.yml` with `stack: plain` and `env: {APP_NAME: my-app}`,
26
+ run `regen`, and confirm that `devcontainer.json` contains `"remoteEnv": {"APP_NAME": "my-app"}`.
27
+
28
+ **Acceptance Scenarios**:
29
+
30
+ 1. **Given** `superposition.yml` has `env: {APP_NAME: my-app}`, **When** generation runs with `stack: plain`, **Then** `devcontainer.json` includes `remoteEnv.APP_NAME: my-app`.
31
+ 2. **Given** `env:` uses the long form (`{value: "foo", target: auto}` — an object with a required `value` string and optional `target` routing hint), **When** generation runs with `stack: plain`, **Then** the variable is written to `remoteEnv` identical to the string shorthand.
32
+
33
+ ---
34
+
35
+ ### User Story 2 — Define environment variables once for compose stack (Priority: P1)
36
+
37
+ A developer adds an `env:` block to `superposition.yml` on a `compose` stack and expects the
38
+ variables to appear in `docker-compose.yml → services.devcontainer.environment` after regeneration.
39
+
40
+ **Why this priority**: Compose-stack users currently must split env configuration across
41
+ `customizations.devcontainerPatch.remoteEnv` and `customizations.dockerComposePatch`, which is
42
+ error-prone and hard to discover.
43
+
44
+ **Independent Test**: Create a `superposition.yml` with `stack: compose` and
45
+ `env: {DB_HOST: postgres}`, run `regen`, and confirm the variable appears under
46
+ `services.devcontainer.environment` in the generated `docker-compose.yml`.
47
+
48
+ **Acceptance Scenarios**:
49
+
50
+ 1. **Given** `superposition.yml` has `env: {DB_HOST: postgres}` on a compose stack, **When** generation runs, **Then** `docker-compose.yml` contains `services.devcontainer.environment.DB_HOST: postgres`.
51
+ 2. **Given** `target: composeEnv` is specified, **When** generation runs with `stack: plain`, **Then** generation errors with a clear message about compose-only targets.
52
+
53
+ ---
54
+
55
+ ### User Story 3 — Explicit target overrides auto-routing (Priority: P2)
56
+
57
+ A developer uses `target: remoteEnv` on a compose-stack project to force a variable into
58
+ `devcontainer.json` instead of `docker-compose.yml`.
59
+
60
+ **Why this priority**: Power users occasionally need fine-grained control over where a variable
61
+ lands, especially for VS Code-specific settings that must be in `remoteEnv`.
62
+
63
+ **Independent Test**: Set `target: remoteEnv` on a variable in a compose-stack project, run
64
+ `regen`, and confirm the variable is in `devcontainer.json → remoteEnv` (not in
65
+ `docker-compose.yml → services.devcontainer.environment`).
66
+
67
+ **Acceptance Scenarios**:
68
+
69
+ 1. **Given** `{value: "bar", target: remoteEnv}` in `env:` on a compose stack, **When** generation runs, **Then** the variable is written to `devcontainer.json → remoteEnv` only.
70
+
71
+ ---
72
+
73
+ ## Overview
74
+
75
+ Add a first-class `env` field to `superposition.yml` so a project can define
76
+ environment variables once and have them land in the correct generated output:
77
+
78
+ - `remoteEnv` for `plain` stacks
79
+ - `services.devcontainer.environment` in `docker-compose.yml` for `compose` stacks
80
+
81
+ This removes the need to split simple container environment variables across
82
+ `customizations.devcontainerPatch.remoteEnv` and
83
+ `customizations.dockerComposePatch`.
84
+
85
+ ## Project File Shape
86
+
87
+ ```yaml
88
+ env:
89
+ APP_NAME: my-app
90
+ API_BASE_URL:
91
+ value: ${API_BASE_URL:-http://localhost:3000}
92
+ target: auto
93
+ ```
94
+
95
+ Rules:
96
+
97
+ - `env` is a map keyed by variable name.
98
+ - A value may be:
99
+ - a string shorthand, equivalent to `{ value: "<string>", target: auto }`
100
+ - an object with:
101
+ - `value: string` required
102
+ - `target: auto | remoteEnv | composeEnv` optional, default `auto`
103
+
104
+ ## Generation Behavior
105
+
106
+ ### `target: auto`
107
+
108
+ - `plain` stack: write the variable to `devcontainer.json -> remoteEnv`
109
+ - `compose` stack: write the variable to
110
+ `docker-compose.yml -> services.devcontainer.environment`
111
+
112
+ ### Explicit targets
113
+
114
+ - `remoteEnv`: always write to `devcontainer.json -> remoteEnv`
115
+ - `composeEnv`: write to `docker-compose.yml -> services.devcontainer.environment`
116
+ and error on non-compose stacks
117
+
118
+ ### Precedence
119
+
120
+ - Project-level `env` is applied before `customizations.devcontainerPatch` and
121
+ `customizations.dockerComposePatch`.
122
+ - Custom patch files remain the escape hatch and may override project-level env.
123
+
124
+ ## Root `.env` Expansion Bridge
125
+
126
+ When a compose-targeted project env value references `${NAME}` or
127
+ `${NAME:-default}`, generation should preserve that expression in
128
+ `docker-compose.yml` and also mirror matching keys from the project root `.env`
129
+ into `.devcontainer/.env`.
130
+
131
+ This allows:
132
+
133
+ 1. the repository root `.env` to remain the human-edited source of truth
134
+ 2. Docker Compose to resolve variables from `.devcontainer/.env`
135
+ 3. generated `docker-compose.yml` to avoid embedding resolved secret values
136
+
137
+ Bridge rules:
138
+
139
+ - only referenced variable names are copied
140
+ - existing unrelated entries in `.devcontainer/.env` are preserved
141
+ - missing root variables are not invented; Docker Compose defaults still work
142
+
143
+ ## Non-Goals
144
+
145
+ - No new syntax for targeting arbitrary non-devcontainer services
146
+ - No replacement for advanced compose patches; those remain under
147
+ `customizations.dockerComposePatch`