container-superposition 0.1.5 โ†’ 0.1.7

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 (155) hide show
  1. package/README.md +3 -1
  2. package/dist/scripts/init.js +24 -4
  3. package/dist/scripts/init.js.map +1 -1
  4. package/dist/tool/commands/adopt.d.ts +3 -2
  5. package/dist/tool/commands/adopt.d.ts.map +1 -1
  6. package/dist/tool/commands/adopt.js +378 -67
  7. package/dist/tool/commands/adopt.js.map +1 -1
  8. package/dist/tool/commands/doctor.d.ts +3 -0
  9. package/dist/tool/commands/doctor.d.ts.map +1 -1
  10. package/dist/tool/commands/doctor.js +932 -69
  11. package/dist/tool/commands/doctor.js.map +1 -1
  12. package/dist/tool/commands/explain.d.ts.map +1 -1
  13. package/dist/tool/commands/explain.js +9 -0
  14. package/dist/tool/commands/explain.js.map +1 -1
  15. package/dist/tool/questionnaire/composer.d.ts.map +1 -1
  16. package/dist/tool/questionnaire/composer.js +212 -11
  17. package/dist/tool/questionnaire/composer.js.map +1 -1
  18. package/dist/tool/schema/overlay-loader.d.ts.map +1 -1
  19. package/dist/tool/schema/overlay-loader.js +1 -0
  20. package/dist/tool/schema/overlay-loader.js.map +1 -1
  21. package/dist/tool/schema/project-config.d.ts +3 -1
  22. package/dist/tool/schema/project-config.d.ts.map +1 -1
  23. package/dist/tool/schema/project-config.js +164 -13
  24. package/dist/tool/schema/project-config.js.map +1 -1
  25. package/dist/tool/schema/types.d.ts +85 -11
  26. package/dist/tool/schema/types.d.ts.map +1 -1
  27. package/dist/tool/utils/merge.d.ts.map +1 -1
  28. package/dist/tool/utils/merge.js +9 -0
  29. package/dist/tool/utils/merge.js.map +1 -1
  30. package/docs/adopt.md +20 -14
  31. package/docs/creating-overlays.md +151 -2
  32. package/docs/overlay-imports.md +125 -102
  33. package/docs/overlays.md +59 -6
  34. package/docs/quick-reference.md +99 -0
  35. package/docs/specs/002-superposition-config-file/plan.md +6 -1
  36. package/docs/specs/002-superposition-config-file/spec.md +6 -0
  37. package/docs/specs/002-superposition-config-file/tasks.md +2 -0
  38. package/docs/specs/003-mkdocs2-overlay/spec.md +114 -0
  39. package/docs/specs/004-doctor-fix/spec.md +70 -0
  40. package/docs/specs/005-cuda-overlay/spec.md +101 -0
  41. package/docs/specs/006-rocm-overlay/spec.md +109 -0
  42. package/docs/team-workflow.md +7 -1
  43. package/docs/workflows.md +3 -0
  44. package/features/cross-distro-packages/README.md +18 -0
  45. package/features/cross-distro-packages/devcontainer-feature.json +3 -3
  46. package/features/cross-distro-packages/install.sh +49 -7
  47. package/overlays/.shared/README.md +80 -21
  48. package/overlays/.shared/compose/common-healthchecks.md +60 -0
  49. package/overlays/.shared/vscode/recommended-extensions.json +15 -11
  50. package/overlays/alertmanager/setup.sh +4 -19
  51. package/overlays/alertmanager/verify.sh +8 -9
  52. package/overlays/all/README.md +43 -0
  53. package/overlays/all/devcontainer.patch.json +6 -0
  54. package/overlays/all/overlay.yml +14 -0
  55. package/overlays/amp/setup.sh +5 -0
  56. package/overlays/bun/setup.sh +10 -1
  57. package/overlays/bun/verify.sh +6 -1
  58. package/overlays/claude-code/setup.sh +5 -0
  59. package/overlays/cloudflared/setup.sh +9 -12
  60. package/overlays/codex/README.md +9 -6
  61. package/overlays/codex/devcontainer.patch.json +7 -1
  62. package/overlays/codex/setup.sh +5 -0
  63. package/overlays/codex/verify.sh +8 -0
  64. package/overlays/commitlint/setup.sh +5 -0
  65. package/overlays/cuda/README.md +179 -0
  66. package/overlays/cuda/devcontainer.patch.json +7 -0
  67. package/overlays/cuda/overlay.yml +17 -0
  68. package/overlays/cuda/setup.sh +32 -0
  69. package/overlays/cuda/verify.sh +38 -0
  70. package/overlays/devcontainer-cli/README.md +50 -0
  71. package/overlays/devcontainer-cli/devcontainer.patch.json +13 -0
  72. package/overlays/devcontainer-cli/overlay.yml +16 -0
  73. package/overlays/devcontainer-cli/setup.sh +14 -0
  74. package/overlays/direnv/devcontainer.patch.json +6 -0
  75. package/overlays/direnv/setup.sh +7 -6
  76. package/overlays/dotnet/setup.sh +14 -7
  77. package/overlays/duckdb/devcontainer.patch.json +1 -2
  78. package/overlays/gcloud/devcontainer.patch.json +0 -6
  79. package/overlays/gcloud/setup.sh +51 -0
  80. package/overlays/gemini-cli/setup.sh +5 -0
  81. package/overlays/git-helpers/devcontainer.patch.json +2 -1
  82. package/overlays/go/setup.sh +15 -14
  83. package/overlays/jaeger/overlay.yml +2 -0
  84. package/overlays/just/setup.sh +5 -17
  85. package/overlays/keycloak/docker-compose.yml +6 -4
  86. package/overlays/keycloak/verify.sh +4 -3
  87. package/overlays/kind/devcontainer.patch.json +1 -2
  88. package/overlays/kind/setup.sh +8 -17
  89. package/overlays/minio/setup.sh +10 -18
  90. package/overlays/mkdocs/overlay.yml +2 -1
  91. package/overlays/mkdocs2/README.md +135 -0
  92. package/overlays/mkdocs2/devcontainer.patch.json +19 -0
  93. package/overlays/mkdocs2/overlay.yml +17 -0
  94. package/overlays/mkdocs2/setup.sh +67 -0
  95. package/overlays/mkdocs2/verify.sh +35 -0
  96. package/overlays/modern-cli-tools/devcontainer.patch.json +7 -1
  97. package/overlays/modern-cli-tools/setup.sh +21 -71
  98. package/overlays/mongodb/devcontainer.patch.json +0 -6
  99. package/overlays/mongodb/setup.sh +59 -0
  100. package/overlays/mysql/verify.sh +4 -3
  101. package/overlays/nats/.env.example +1 -1
  102. package/overlays/nats/README.md +1 -1
  103. package/overlays/nats/docker-compose.yml +1 -1
  104. package/overlays/ngrok/setup.sh +9 -6
  105. package/overlays/nodejs/setup.sh +5 -0
  106. package/overlays/openapi-tools/devcontainer.patch.json +1 -2
  107. package/overlays/openapi-tools/setup.sh +9 -8
  108. package/overlays/opencode/setup.sh +5 -0
  109. package/overlays/otel-collector/overlay.yml +2 -0
  110. package/overlays/otel-collector/setup.sh +3 -16
  111. package/overlays/otel-demo-nodejs/verify.sh +8 -9
  112. package/overlays/otel-demo-python/verify.sh +16 -10
  113. package/overlays/pandoc/README.md +286 -0
  114. package/overlays/pandoc/devcontainer.patch.json +18 -0
  115. package/overlays/pandoc/overlay.yml +19 -0
  116. package/overlays/pandoc/setup.sh +293 -0
  117. package/overlays/pandoc/verify.sh +25 -0
  118. package/overlays/playwright/devcontainer.patch.json +3 -1
  119. package/overlays/playwright/setup.sh +37 -0
  120. package/overlays/postgres/docker-compose.yml +6 -0
  121. package/overlays/powershell/setup.sh +49 -13
  122. package/overlays/pre-commit/setup.sh +12 -3
  123. package/overlays/prometheus/overlay.yml +2 -0
  124. package/overlays/promtail/verify.sh +16 -10
  125. package/overlays/pulumi/devcontainer.patch.json +1 -1
  126. package/overlays/python/setup.sh +28 -9
  127. package/overlays/python/verify.sh +4 -2
  128. package/overlays/redpanda/docker-compose.yml +3 -5
  129. package/overlays/rocm/README.md +227 -0
  130. package/overlays/rocm/devcontainer.patch.json +4 -0
  131. package/overlays/rocm/overlay.yml +17 -0
  132. package/overlays/rocm/setup.sh +45 -0
  133. package/overlays/rocm/verify.sh +47 -0
  134. package/overlays/rust/setup.sh +11 -18
  135. package/overlays/spec-kit/setup.sh +7 -3
  136. package/overlays/sqlite/setup.sh +14 -14
  137. package/overlays/sqlserver/docker-compose.yml +3 -3
  138. package/overlays/sqlserver/verify.sh +22 -5
  139. package/overlays/tempo/verify.sh +16 -10
  140. package/overlays/tilt/devcontainer.patch.json +1 -2
  141. package/overlays/tilt/setup.sh +14 -4
  142. package/overlays/windsurf-cli/setup.sh +27 -4
  143. package/overlays/windsurf-cli/verify.sh +13 -3
  144. package/package.json +2 -1
  145. package/templates/scripts/setup-utils.sh +228 -0
  146. package/tool/schema/config.schema.json +110 -8
  147. package/tool/schema/overlay-manifest.schema.json +5 -0
  148. package/overlays/.shared/compose/common-healthchecks.yml +0 -38
  149. /package/overlays/otel-demo-nodejs/{Dockerfile-otel-demo-nodejs โ†’ Dockerfile} +0 -0
  150. /package/overlays/otel-demo-nodejs/{package-otel-demo-nodejs.json โ†’ package.json} +0 -0
  151. /package/overlays/otel-demo-nodejs/{server-otel-demo-nodejs.js โ†’ server.js} +0 -0
  152. /package/overlays/otel-demo-nodejs/{tracing-otel-demo-nodejs.js โ†’ tracing.js} +0 -0
  153. /package/overlays/otel-demo-python/{Dockerfile-otel-demo-python โ†’ Dockerfile} +0 -0
  154. /package/overlays/otel-demo-python/{app-otel-demo-python.py โ†’ app.py} +0 -0
  155. /package/overlays/otel-demo-python/{requirements-otel-demo-python.txt โ†’ requirements.txt} +0 -0
@@ -0,0 +1,114 @@
1
+ # Feature Specification: MkDocs 2.x Overlay
2
+
3
+ **Feature Branch**: `copilot/add-mkdocs2-overlay`
4
+ **Created**: 2026-03-16
5
+ **Status**: Final
6
+ **Input**: Add a new `mkdocs2` overlay that installs MkDocs 2.x with the Material theme via direct `pip` install, keeping the existing `mkdocs` (MkDocs 1.x) overlay untouched for backward compatibility.
7
+
8
+ ## Review & Approval _(mandatory before implementation)_
9
+
10
+ - **Spec Path**: `docs/specs/003-mkdocs2-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 - Use MkDocs 2.x in a devcontainer (Priority: P1)
18
+
19
+ A developer wants to write documentation using MkDocs 2.x with the Material theme inside a devcontainer without manually managing Python packages.
20
+
21
+ **Why this priority**: MkDocs 2.x is the currently maintained release. Users starting new documentation projects need a working overlay that installs the supported version.
22
+
23
+ **Independent Test**: Select the `mkdocs2` overlay (with `python` as a required dependency), rebuild the container, and confirm that `mkdocs --version` reports a 2.x release, `mkdocs new .` succeeds, and `mkdocs serve` starts the dev server on port 8000.
24
+
25
+ **Acceptance Scenarios**:
26
+
27
+ 1. **Given** a user selects the `mkdocs2` overlay, **When** the devcontainer is built, **Then** `mkdocs --version` reports a version matching `2.x`.
28
+ 2. **Given** the container is running, **When** the user runs `mkdocs serve`, **Then** the development server starts on port 8000 and VS Code forwards the port automatically.
29
+ 3. **Given** a `mkdocs.yml` with `theme: {name: material}`, **When** the user runs `mkdocs build`, **Then** the site is generated without errors into the `site/` directory.
30
+
31
+ ---
32
+
33
+ ### User Story 2 - Conflict enforcement between mkdocs and mkdocs2 (Priority: P1)
34
+
35
+ A user selects both `mkdocs` (1.x) and `mkdocs2` (2.x) and expects the tool to report a conflict.
36
+
37
+ **Why this priority**: Both overlays install incompatible versions of the `mkdocs` command into the same environment. Allowing both would produce unpredictable results.
38
+
39
+ **Independent Test**: Attempt to generate a devcontainer with both `mkdocs` and `mkdocs2` selected and confirm the tool surfaces a conflict and blocks generation.
40
+
41
+ **Acceptance Scenarios**:
42
+
43
+ 1. **Given** a user selects `mkdocs` and `mkdocs2` simultaneously, **When** the questionnaire processes the selection, **Then** a conflict is reported and the user is prompted to choose one.
44
+ 2. **Given** `mkdocs` conflicts with `mkdocs2` in `overlays/mkdocs/overlay.yml`, **When** the overlay loader reads both manifests, **Then** the conflict is recognised bidirectionally.
45
+
46
+ ---
47
+
48
+ ### User Story 3 - Backward compatibility for existing mkdocs users (Priority: P2)
49
+
50
+ An existing user who already has the `mkdocs` overlay selected is unaffected by the addition of the new overlay.
51
+
52
+ **Why this priority**: Introducing a new overlay must not break users who rely on the existing one.
53
+
54
+ **Independent Test**: Generate a devcontainer using only the `mkdocs` overlay and confirm the output is identical to what it was before `mkdocs2` was added.
55
+
56
+ **Acceptance Scenarios**:
57
+
58
+ 1. **Given** a user's `superposition.json` references only `mkdocs`, **When** they run `regen`, **Then** the output is identical to before and contains no `mkdocs2`-related changes.
59
+
60
+ ---
61
+
62
+ ## Design
63
+
64
+ ### Installation Method
65
+
66
+ The `mkdocs2` overlay installs packages via `pip` directly into the workspace
67
+ `.venv` virtual environment (created by the `python` overlay, which is a hard
68
+ dependency). The overlay's `setup.sh` creates the `.venv` if it does not exist
69
+ yet, so it is self-contained even when run before the `python` overlay's setup
70
+ script completes.
71
+
72
+ ```bash
73
+ pip install --no-cache-dir \
74
+ "mkdocs>=2.0,<3.0" \
75
+ "mkdocs-material>=9.0" \
76
+ "mkdocs-minify-plugin" \
77
+ "mkdocs-redirects" \
78
+ "pymdown-extensions"
79
+ ```
80
+
81
+ This approach is preferred over the `ghcr.io/devcontainers-extra/features/mkdocs:2`
82
+ devcontainer feature because it gives precise version control and installs into
83
+ the same virtual environment used by the rest of the project.
84
+
85
+ ### Category
86
+
87
+ `dev` โ€” MkDocs is a documentation tool, not a language runtime. This differs
88
+ from the legacy `mkdocs` overlay which uses `language` for historical reasons.
89
+
90
+ ### Conflict Model
91
+
92
+ `mkdocs` โ†” `mkdocs2` conflict is bidirectional:
93
+
94
+ - `overlays/mkdocs/overlay.yml`: `conflicts: [mkdocs2]`
95
+ - `overlays/mkdocs2/overlay.yml`: `conflicts: [mkdocs]`
96
+
97
+ ### TypeScript Type
98
+
99
+ `mkdocs2` is added to the `DevTool` union in `tool/schema/types.ts`, making it
100
+ part of the `OverlayId` union used throughout the type system.
101
+
102
+ ---
103
+
104
+ ## Files
105
+
106
+ | File | Description |
107
+ | ------------------------------------------ | -------------------------------------------------- |
108
+ | `overlays/mkdocs2/overlay.yml` | Overlay manifest |
109
+ | `overlays/mkdocs2/devcontainer.patch.json` | Port 8000 forwarding + VS Code Markdown extensions |
110
+ | `overlays/mkdocs2/setup.sh` | Pip install into `.venv` |
111
+ | `overlays/mkdocs2/verify.sh` | Confirms MkDocs 2.x is installed |
112
+ | `overlays/mkdocs2/README.md` | User documentation |
113
+ | `overlays/mkdocs/overlay.yml` | Updated to add bidirectional conflict |
114
+ | `tool/schema/types.ts` | Adds `mkdocs2` to `DevTool` |
@@ -0,0 +1,70 @@
1
+ # Feature Specification: `doctor --fix` โ€” Interactive Auto-Repair
2
+
3
+ **Feature Branch**: `004-doctor-fix`
4
+ **Created**: 2026-03-19
5
+ **Status**: Final
6
+ **Input**: GitHub issue: Implement `doctor --fix` โ€” interactive auto-repair for environment issues
7
+
8
+ ## Review & Approval _(mandatory before implementation)_
9
+
10
+ - **Spec Path**: `docs/specs/004-doctor-fix/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
+ The `doctor` command validates the environment. The `--fix` path was a placeholder. This spec
18
+ describes the full implementation of an interactive, safe, deterministic auto-repair flow for
19
+ common environment issues.
20
+
21
+ ## Initial Auto-Fix Scope
22
+
23
+ | # | Issue class | Automation condition |
24
+ | --- | ------------------------------------------------------------- | ----------------------------------------------------------------- |
25
+ | 1 | Stale or legacy `superposition.json` metadata | Always supported (manifest migration) |
26
+ | 2 | Derived `.devcontainer/` drift or missing generated artifacts | Supported when a valid manifest is present (regeneration) |
27
+ | 3 | Unsupported Node runtime | Supported only when `nvm`, `fnm`, or `volta` is already available |
28
+ | 4 | Docker / Compose tooling drift | Supported only when a known safe host repair command is available |
29
+
30
+ ## Outcome Vocabulary
31
+
32
+ Every finding evaluated by the fix flow resolves to exactly one of:
33
+
34
+ - **`fixed`** โ€” tool changed the environment and targeted re-check now passes
35
+ - **`already compliant`** โ€” fix path found no change was needed
36
+ - **`skipped`** โ€” not attempted because an earlier failure or prerequisite blocked it
37
+ - **`requires manual action`** โ€” issue remains; automation is unsafe or unavailable
38
+
39
+ ## Data Model
40
+
41
+ ### `DiagnosticFinding`
42
+
43
+ Fields: `id`, `category`, `name`, `status`, `message`, `details?`, `fixEligibility`, `remediationKey?`, `recheckScope`
44
+
45
+ ### `RemediationAction`
46
+
47
+ Fields: `key`, `findingId`, `safetyClass`, `executionKind`, `preconditions`, `plannedChanges`, `manualFallback`
48
+
49
+ ### `FixExecution`
50
+
51
+ Fields: `findingId`, `remediationKey`, `attempted`, `outcome`, `reason`, `commands?`, `changedFiles?`, `backupPath?`, `rechecked`
52
+
53
+ ### `FixRun`
54
+
55
+ Fields: `outputPath`, `requestedJson`, `initialFindings`, `executions`, `finalFindings`, `summary`, `exitDisposition`
56
+
57
+ ## CLI Contract
58
+
59
+ - `doctor` without `--fix` โ€” no change to current diagnostics behavior
60
+ - `doctor --fix` โ€” diagnose โ†’ remediate in stable order โ†’ re-check โ†’ print summary
61
+ - `doctor --fix --json` โ€” same flow, machine-readable JSON output
62
+
63
+ ## Remediation Ordering
64
+
65
+ Prerequisites before dependents:
66
+
67
+ 1. Stale manifest migration (must complete before regeneration)
68
+ 2. Missing artifacts / devcontainer drift (regeneration from manifest)
69
+ 3. Node version fix (only if version manager available)
70
+ 4. Docker tooling fix (only if repair command available)
@@ -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
@@ -44,6 +44,9 @@ npx container-superposition adopt --dry-run
44
44
 
45
45
  # Run the adoption (writes superposition.json and custom/ patches)
46
46
  npx container-superposition adopt
47
+
48
+ # Or also emit a repository-root project file for project-config workflows
49
+ npx container-superposition adopt --project-file
47
50
  ```
48
51
 
49
52
  `adopt` reads every feature URI, VS Code extension, and Docker Compose service
@@ -54,7 +57,10 @@ mounts, unmatched environment variables, โ€ฆ) is written to
54
57
 
55
58
  `superposition.json` is written to the **project root** (not inside
56
59
  `.devcontainer/`), so it can be committed alongside your application code and
57
- shared with the rest of the team โ€” matching the standard team workflow.
60
+ shared with the rest of the team โ€” matching the standard team workflow. If you
61
+ pass `--project-file`, `adopt` also writes a repository-root `.superposition.yml`
62
+ using the same inferred stack, overlays, output path, and supported
63
+ customizations.
58
64
 
59
65
  See the [Adopt Command guide](adopt.md) for full details.
60
66
 
package/docs/workflows.md CHANGED
@@ -68,6 +68,9 @@ npx container-superposition regen
68
68
  # Or select the project file explicitly
69
69
  npx container-superposition regen --from-project
70
70
 
71
+ # Or run from another directory while targeting a repository root
72
+ npx container-superposition regen --from-project --project-root ../my-project
73
+
71
74
  # Falls back to manifest discovery when no project file exists
72
75
  npx container-superposition regen
73
76
  ```
@@ -6,6 +6,7 @@ A devcontainer feature that installs system packages with automatic distribution
6
6
 
7
7
  - ๐Ÿ” **Auto-detection**: Automatically detects whether the container uses apt or apk
8
8
  - ๐Ÿ“ฆ **Distro-specific packages**: Specify different package names for each distribution
9
+ - ๐Ÿ” **Fallback package names**: Use `pkgA|pkgB` when Debian/Ubuntu variants expose different names
9
10
  - ๐Ÿงน **Clean installation**: Cleans up package manager caches to minimize image size
10
11
  - โšก **Fast**: No unnecessary updates or cache rebuilds
11
12
 
@@ -26,6 +27,19 @@ A devcontainer feature that installs system packages with automatic distribution
26
27
 
27
28
  ### Real-World Examples
28
29
 
30
+ **Fallback package names within apt-based distros:**
31
+
32
+ ```json
33
+ {
34
+ "features": {
35
+ "./features/cross-distro-packages": {
36
+ "apt": "fonts-carlito|fonts-crosextra-carlito",
37
+ "apk": ""
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
29
43
  **Node.js Build Tools:**
30
44
 
31
45
  ```json
@@ -85,6 +99,10 @@ A devcontainer feature that installs system packages with automatic distribution
85
99
  | `apt` | string | `""` | Space-separated list of packages for apt-based distributions (Debian, Ubuntu) |
86
100
  | `apk` | string | `""` | Space-separated list of packages for apk-based distributions (Alpine Linux) |
87
101
 
102
+ Package entries may include fallback candidates separated by `|`, for example
103
+ `fonts-carlito|fonts-crosextra-carlito`. The feature selects the first package
104
+ name that exists for the detected package manager.
105
+
88
106
  ## Package Name Differences
89
107
 
90
108
  Common packages that have different names across distributions:
@@ -2,18 +2,18 @@
2
2
  "id": "cross-distro-packages",
3
3
  "version": "1.0.0",
4
4
  "name": "Cross-Distribution Package Manager",
5
- "description": "Install system packages with automatic distribution detection (supports apt and apk)",
5
+ "description": "Install system packages with automatic distribution detection and fallback package-name support (supports apt and apk)",
6
6
  "documentationURL": "https://github.com/veggerby/container-superposition/tree/main/features/cross-distro-packages",
7
7
  "options": {
8
8
  "apt": {
9
9
  "type": "string",
10
10
  "default": "",
11
- "description": "Space-separated list of packages for apt-based distros (Debian, Ubuntu)"
11
+ "description": "Space-separated list of packages for apt-based distros (Debian, Ubuntu). Use pkgA|pkgB to try fallback names."
12
12
  },
13
13
  "apk": {
14
14
  "type": "string",
15
15
  "default": "",
16
- "description": "Space-separated list of packages for apk-based distros (Alpine)"
16
+ "description": "Space-separated list of packages for apk-based distros (Alpine). Use pkgA|pkgB to try fallback names."
17
17
  }
18
18
  },
19
19
  "installsAfter": ["ghcr.io/devcontainers/features/common-utils"]
@@ -14,6 +14,50 @@ deduplicate_packages() {
14
14
  echo "$packages" | tr ' ' '\n' | sort -u | tr '\n' ' ' | sed 's/ $//'
15
15
  }
16
16
 
17
+ resolve_package_token() {
18
+ local manager="$1"
19
+ local token="$2"
20
+ local IFS='|'
21
+ read -r -a candidates <<< "$token"
22
+
23
+ for candidate in "${candidates[@]}"; do
24
+ if [ -z "$candidate" ]; then
25
+ continue
26
+ fi
27
+
28
+ if [ "$manager" = "apt" ]; then
29
+ if apt-cache show "$candidate" >/dev/null 2>&1; then
30
+ echo "$candidate"
31
+ return 0
32
+ fi
33
+ elif [ "$manager" = "apk" ]; then
34
+ if apk search -x "$candidate" >/dev/null 2>&1; then
35
+ echo "$candidate"
36
+ return 0
37
+ fi
38
+ fi
39
+ done
40
+
41
+ return 1
42
+ }
43
+
44
+ resolve_package_list() {
45
+ local manager="$1"
46
+ local packages="$2"
47
+ local resolved=()
48
+
49
+ for token in $packages; do
50
+ local selected=""
51
+ if ! selected=$(resolve_package_token "$manager" "$token"); then
52
+ echo "โŒ No package candidate found for \"$token\" using $manager" >&2
53
+ exit 1
54
+ fi
55
+ resolved+=("$selected")
56
+ done
57
+
58
+ deduplicate_packages "${resolved[*]}"
59
+ }
60
+
17
61
  # Exit early if no packages specified
18
62
  if [ -z "$APT_PACKAGES" ] && [ -z "$APK_PACKAGES" ]; then
19
63
  echo "โš ๏ธ No packages specified for installation"
@@ -26,9 +70,8 @@ echo "๐Ÿ“ฆ Installing cross-distro packages..."
26
70
  if command -v apk > /dev/null 2>&1; then
27
71
  # Alpine Linux (apk)
28
72
  if [ -n "$APK_PACKAGES" ]; then
29
- # Deduplicate package list
30
- APK_PACKAGES=$(deduplicate_packages "$APK_PACKAGES")
31
-
73
+ APK_PACKAGES=$(resolve_package_list "apk" "$APK_PACKAGES")
74
+
32
75
  echo " Detected: Alpine Linux (apk)"
33
76
  echo " Installing: $APK_PACKAGES"
34
77
  apk add --no-cache $APK_PACKAGES
@@ -39,12 +82,11 @@ if command -v apk > /dev/null 2>&1; then
39
82
  elif command -v apt-get > /dev/null 2>&1; then
40
83
  # Debian/Ubuntu (apt)
41
84
  if [ -n "$APT_PACKAGES" ]; then
42
- # Deduplicate package list
43
- APT_PACKAGES=$(deduplicate_packages "$APT_PACKAGES")
44
-
85
+ apt-get update
86
+ APT_PACKAGES=$(resolve_package_list "apt" "$APT_PACKAGES")
87
+
45
88
  echo " Detected: Debian/Ubuntu (apt)"
46
89
  echo " Installing: $APT_PACKAGES"
47
- apt-get update
48
90
  DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $APT_PACKAGES
49
91
  apt-get clean
50
92
  rm -rf /var/lib/apt/lists/*