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.
- package/README.md +3 -1
- package/dist/scripts/init.js +24 -4
- package/dist/scripts/init.js.map +1 -1
- package/dist/tool/commands/adopt.d.ts +3 -2
- package/dist/tool/commands/adopt.d.ts.map +1 -1
- package/dist/tool/commands/adopt.js +378 -67
- package/dist/tool/commands/adopt.js.map +1 -1
- package/dist/tool/commands/doctor.d.ts +3 -0
- package/dist/tool/commands/doctor.d.ts.map +1 -1
- package/dist/tool/commands/doctor.js +932 -69
- package/dist/tool/commands/doctor.js.map +1 -1
- package/dist/tool/commands/explain.d.ts.map +1 -1
- package/dist/tool/commands/explain.js +9 -0
- package/dist/tool/commands/explain.js.map +1 -1
- package/dist/tool/questionnaire/composer.d.ts.map +1 -1
- package/dist/tool/questionnaire/composer.js +212 -11
- package/dist/tool/questionnaire/composer.js.map +1 -1
- package/dist/tool/schema/overlay-loader.d.ts.map +1 -1
- package/dist/tool/schema/overlay-loader.js +1 -0
- package/dist/tool/schema/overlay-loader.js.map +1 -1
- package/dist/tool/schema/project-config.d.ts +3 -1
- package/dist/tool/schema/project-config.d.ts.map +1 -1
- package/dist/tool/schema/project-config.js +164 -13
- package/dist/tool/schema/project-config.js.map +1 -1
- package/dist/tool/schema/types.d.ts +85 -11
- package/dist/tool/schema/types.d.ts.map +1 -1
- package/dist/tool/utils/merge.d.ts.map +1 -1
- package/dist/tool/utils/merge.js +9 -0
- package/dist/tool/utils/merge.js.map +1 -1
- package/docs/adopt.md +20 -14
- package/docs/creating-overlays.md +151 -2
- package/docs/overlay-imports.md +125 -102
- package/docs/overlays.md +59 -6
- package/docs/quick-reference.md +99 -0
- package/docs/specs/002-superposition-config-file/plan.md +6 -1
- package/docs/specs/002-superposition-config-file/spec.md +6 -0
- package/docs/specs/002-superposition-config-file/tasks.md +2 -0
- package/docs/specs/003-mkdocs2-overlay/spec.md +114 -0
- package/docs/specs/004-doctor-fix/spec.md +70 -0
- package/docs/specs/005-cuda-overlay/spec.md +101 -0
- package/docs/specs/006-rocm-overlay/spec.md +109 -0
- package/docs/team-workflow.md +7 -1
- package/docs/workflows.md +3 -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/.shared/README.md +80 -21
- package/overlays/.shared/compose/common-healthchecks.md +60 -0
- package/overlays/.shared/vscode/recommended-extensions.json +15 -11
- package/overlays/alertmanager/setup.sh +4 -19
- package/overlays/alertmanager/verify.sh +8 -9
- package/overlays/all/README.md +43 -0
- package/overlays/all/devcontainer.patch.json +6 -0
- package/overlays/all/overlay.yml +14 -0
- package/overlays/amp/setup.sh +5 -0
- package/overlays/bun/setup.sh +10 -1
- package/overlays/bun/verify.sh +6 -1
- package/overlays/claude-code/setup.sh +5 -0
- package/overlays/cloudflared/setup.sh +9 -12
- package/overlays/codex/README.md +9 -6
- package/overlays/codex/devcontainer.patch.json +7 -1
- package/overlays/codex/setup.sh +5 -0
- package/overlays/codex/verify.sh +8 -0
- package/overlays/commitlint/setup.sh +5 -0
- package/overlays/cuda/README.md +179 -0
- package/overlays/cuda/devcontainer.patch.json +7 -0
- package/overlays/cuda/overlay.yml +17 -0
- package/overlays/cuda/setup.sh +32 -0
- package/overlays/cuda/verify.sh +38 -0
- package/overlays/devcontainer-cli/README.md +50 -0
- package/overlays/devcontainer-cli/devcontainer.patch.json +13 -0
- package/overlays/devcontainer-cli/overlay.yml +16 -0
- package/overlays/devcontainer-cli/setup.sh +14 -0
- package/overlays/direnv/devcontainer.patch.json +6 -0
- package/overlays/direnv/setup.sh +7 -6
- package/overlays/dotnet/setup.sh +14 -7
- package/overlays/duckdb/devcontainer.patch.json +1 -2
- package/overlays/gcloud/devcontainer.patch.json +0 -6
- package/overlays/gcloud/setup.sh +51 -0
- package/overlays/gemini-cli/setup.sh +5 -0
- package/overlays/git-helpers/devcontainer.patch.json +2 -1
- package/overlays/go/setup.sh +15 -14
- package/overlays/jaeger/overlay.yml +2 -0
- package/overlays/just/setup.sh +5 -17
- package/overlays/keycloak/docker-compose.yml +6 -4
- package/overlays/keycloak/verify.sh +4 -3
- package/overlays/kind/devcontainer.patch.json +1 -2
- package/overlays/kind/setup.sh +8 -17
- package/overlays/minio/setup.sh +10 -18
- package/overlays/mkdocs/overlay.yml +2 -1
- package/overlays/mkdocs2/README.md +135 -0
- package/overlays/mkdocs2/devcontainer.patch.json +19 -0
- package/overlays/mkdocs2/overlay.yml +17 -0
- package/overlays/mkdocs2/setup.sh +67 -0
- package/overlays/mkdocs2/verify.sh +35 -0
- package/overlays/modern-cli-tools/devcontainer.patch.json +7 -1
- package/overlays/modern-cli-tools/setup.sh +21 -71
- package/overlays/mongodb/devcontainer.patch.json +0 -6
- package/overlays/mongodb/setup.sh +59 -0
- package/overlays/mysql/verify.sh +4 -3
- package/overlays/nats/.env.example +1 -1
- package/overlays/nats/README.md +1 -1
- package/overlays/nats/docker-compose.yml +1 -1
- package/overlays/ngrok/setup.sh +9 -6
- package/overlays/nodejs/setup.sh +5 -0
- package/overlays/openapi-tools/devcontainer.patch.json +1 -2
- package/overlays/openapi-tools/setup.sh +9 -8
- package/overlays/opencode/setup.sh +5 -0
- package/overlays/otel-collector/overlay.yml +2 -0
- package/overlays/otel-collector/setup.sh +3 -16
- package/overlays/otel-demo-nodejs/verify.sh +8 -9
- package/overlays/otel-demo-python/verify.sh +16 -10
- package/overlays/pandoc/README.md +286 -0
- package/overlays/pandoc/devcontainer.patch.json +18 -0
- package/overlays/pandoc/overlay.yml +19 -0
- package/overlays/pandoc/setup.sh +293 -0
- package/overlays/pandoc/verify.sh +25 -0
- package/overlays/playwright/devcontainer.patch.json +3 -1
- package/overlays/playwright/setup.sh +37 -0
- package/overlays/postgres/docker-compose.yml +6 -0
- package/overlays/powershell/setup.sh +49 -13
- package/overlays/pre-commit/setup.sh +12 -3
- package/overlays/prometheus/overlay.yml +2 -0
- package/overlays/promtail/verify.sh +16 -10
- package/overlays/pulumi/devcontainer.patch.json +1 -1
- package/overlays/python/setup.sh +28 -9
- package/overlays/python/verify.sh +4 -2
- package/overlays/redpanda/docker-compose.yml +3 -5
- package/overlays/rocm/README.md +227 -0
- package/overlays/rocm/devcontainer.patch.json +4 -0
- package/overlays/rocm/overlay.yml +17 -0
- package/overlays/rocm/setup.sh +45 -0
- package/overlays/rocm/verify.sh +47 -0
- package/overlays/rust/setup.sh +11 -18
- package/overlays/spec-kit/setup.sh +7 -3
- package/overlays/sqlite/setup.sh +14 -14
- package/overlays/sqlserver/docker-compose.yml +3 -3
- package/overlays/sqlserver/verify.sh +22 -5
- package/overlays/tempo/verify.sh +16 -10
- package/overlays/tilt/devcontainer.patch.json +1 -2
- package/overlays/tilt/setup.sh +14 -4
- package/overlays/windsurf-cli/setup.sh +27 -4
- package/overlays/windsurf-cli/verify.sh +13 -3
- package/package.json +2 -1
- package/templates/scripts/setup-utils.sh +228 -0
- package/tool/schema/config.schema.json +110 -8
- package/tool/schema/overlay-manifest.schema.json +5 -0
- package/overlays/.shared/compose/common-healthchecks.yml +0 -38
- /package/overlays/otel-demo-nodejs/{Dockerfile-otel-demo-nodejs โ Dockerfile} +0 -0
- /package/overlays/otel-demo-nodejs/{package-otel-demo-nodejs.json โ package.json} +0 -0
- /package/overlays/otel-demo-nodejs/{server-otel-demo-nodejs.js โ server.js} +0 -0
- /package/overlays/otel-demo-nodejs/{tracing-otel-demo-nodejs.js โ tracing.js} +0 -0
- /package/overlays/otel-demo-python/{Dockerfile-otel-demo-python โ Dockerfile} +0 -0
- /package/overlays/otel-demo-python/{app-otel-demo-python.py โ app.py} +0 -0
- /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
|
package/docs/team-workflow.md
CHANGED
|
@@ -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
|
-
|
|
30
|
-
|
|
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
|
-
|
|
43
|
-
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/*
|