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
@@ -4,25 +4,28 @@ Overlays can import shared configuration fragments from `overlays/.shared/` to r
4
4
 
5
5
  ## Overview
6
6
 
7
- Import functionality allows overlays to reference common configuration files instead of duplicating them in every overlay. This promotes DRY (Don't Repeat Yourself) principles and makes it easier to maintain consistent patterns.
7
+ The import mechanism allows overlays to reference common configuration files instead of duplicating them. This promotes DRY principles and makes it easier to maintain consistent patterns.
8
+
9
+ Imports are declared in the overlay's `overlay.yml` manifest and applied **before** the overlay's own `devcontainer.patch.json`, so each overlay can specialize on top of a shared baseline.
8
10
 
9
11
  ## Shared Directory Structure
10
12
 
11
13
  ```
12
14
  overlays/
13
15
  ├── .shared/
14
- │ ├── otel/ # OpenTelemetry configurations
15
- ├── otel-base-config.yaml # Base OTEL collector config
16
- │ │ └── instrumentation.env # Common env vars for instrumentation
17
- ├── compose/ # Docker Compose patterns
18
- │ └── common-healthchecks.yml # Standard healthcheck configurations
19
- │ └── vscode/ # VS Code extension sets
20
- └── recommended-extensions.json # Commonly recommended extensions
16
+ │ ├── README.md
17
+ │ ├── otel/
18
+ │ │ ├── instrumentation.env # OTEL SDK env vars imported by otel-collector, prometheus, jaeger
19
+ │ └── otel-base-config.yaml # Base OTEL collector pipeline config
20
+ ├── compose/
21
+ └── common-healthchecks.yml # Standard Docker Compose healthcheck patterns
22
+ └── vscode/
23
+ │ └── recommended-extensions.json # Commonly recommended VS Code extensions (devcontainer patch format)
21
24
  ├── prometheus/
22
- │ ├── overlay.yml # Can import from .shared/
25
+ │ ├── overlay.yml # imports: [.shared/otel/instrumentation.env]
23
26
  │ └── devcontainer.patch.json
24
27
  └── jaeger/
25
- ├── overlay.yml # Can import from .shared/
28
+ ├── overlay.yml # imports: [.shared/otel/instrumentation.env]
26
29
  └── devcontainer.patch.json
27
30
  ```
28
31
 
@@ -48,101 +51,128 @@ ports:
48
51
  - 9090
49
52
  imports:
50
53
  - .shared/otel/instrumentation.env
51
- - .shared/compose/common-healthchecks.yml
52
54
  ```
53
55
 
54
- ## Supported File Types
56
+ **Rules:**
57
+
58
+ - All paths **must** begin with `.shared/` — references outside `.shared/` are rejected (path traversal prevention)
59
+ - Paths are relative to `overlays/`
60
+ - Order is significant — fragments are applied in declaration order, then the overlay's own `devcontainer.patch.json`
61
+ - Missing files, unsupported types, or path traversal attempts cause generation to fail with a message identifying the overlay and the broken reference
55
62
 
56
- ### JSON Files (`.json`)
63
+ ## Supported File Types and Merge Behavior
57
64
 
58
- Merged as devcontainer patches, just like `devcontainer.patch.json`.
65
+ | Extension | How it is merged |
66
+ | ---------------- | ------------------------------------------------------------------------------ |
67
+ | `.json` | Deep-merged into `devcontainer.json` patch (same as `devcontainer.patch.json`) |
68
+ | `.yaml` / `.yml` | Loaded and deep-merged into `devcontainer.json` patch |
69
+ | `.env` | Concatenated into `.env.example` with a `# from .shared/…` comment header |
70
+ | Anything else | Rejected with a clear unsupported-type error |
59
71
 
60
- **Example: `.shared/vscode/recommended-extensions.json`**
72
+ ### JSON import example
61
73
 
62
- ```json
74
+ ```jsonc
75
+ // overlays/.shared/vscode/recommended-extensions.json
63
76
  {
77
+ "$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.base.schema.json",
64
78
  "customizations": {
65
79
  "vscode": {
66
80
  "extensions": [
67
81
  "streetsidesoftware.code-spell-checker",
68
82
  "usernamehw.errorlens",
69
- "editorconfig.editorconfig"
70
- ]
71
- }
72
- }
83
+ "eamodio.gitlens",
84
+ ],
85
+ },
86
+ },
73
87
  }
74
88
  ```
75
89
 
76
- ### YAML Files (`.yaml`, `.yml`)
77
-
78
- Loaded and merged as devcontainer patches. Useful for complex configurations.
79
-
80
- **Example: `.shared/otel/otel-base-config.yaml`**
90
+ ### YAML import example
81
91
 
82
92
  ```yaml
83
- receivers:
84
- otlp:
85
- protocols:
86
- grpc:
87
- endpoint: 0.0.0.0:4317
88
- http:
89
- endpoint: 0.0.0.0:4318
93
+ # overlays/.shared/otel/otel-base-config.yaml
94
+ remoteEnv:
95
+ OTEL_SERVICE_NAME: my-service
96
+ OTEL_EXPORTER_OTLP_ENDPOINT: http://otel-collector:4317
90
97
  ```
91
98
 
92
- ### Environment Files (`.env`)
99
+ ### ENV import example
93
100
 
94
- Merged into `.env.example` with a comment indicating the import source.
101
+ ```bash
102
+ # overlays/.shared/otel/instrumentation.env
103
+ # OpenTelemetry SDK Configuration
104
+ OTEL_SERVICE_NAME=my-service
105
+ OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
106
+ OTEL_EXPORTER_OTLP_PROTOCOL=grpc
107
+ OTEL_TRACES_SAMPLER=always_on
108
+ OTEL_TRACES_EXPORTER=otlp
109
+ OTEL_METRICS_EXPORTER=otlp
110
+ OTEL_LOGS_EXPORTER=otlp
111
+ ```
95
112
 
96
- **Example: `.shared/otel/instrumentation.env`**
113
+ When this `.env` fragment is imported, the generated `.env.example` will contain:
97
114
 
98
115
  ```bash
99
- # OpenTelemetry Configuration
116
+ # from .shared/otel/instrumentation.env
100
117
  OTEL_SERVICE_NAME=my-service
101
118
  OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
102
- OTEL_TRACES_SAMPLER=always_on
119
+ ...
103
120
  ```
104
121
 
105
- ## How Imports Work
122
+ ## Import Ordering and Conflict Resolution
106
123
 
107
- 1. **Resolution**: Imports are resolved relative to the `overlays/` directory
108
- 2. **Order**: Imports are applied in the order listed, then the overlay's own files
109
- 3. **Merging**:
110
- - JSON/YAML: Deep merged into devcontainer configuration
111
- - ENV: Concatenated into `.env.example` with source comments
112
- 4. **Validation**: Doctor command validates that all imports exist and are valid
124
+ Imports are applied in declaration order, then the overlay's own `devcontainer.patch.json` is applied last:
113
125
 
114
- ## Benefits
126
+ ```
127
+ [import 1] → [import 2] → … → [import N] → [overlay own patch]
128
+ ```
115
129
 
116
- ### Reduced Duplication
130
+ - The **second** import wins over the first on key conflict
131
+ - The **overlay's own patch always wins** over any shared fragment
117
132
 
118
- Before imports:
133
+ This means overlays can intentionally override shared defaults by setting the same key in their `devcontainer.patch.json`.
119
134
 
120
- ```
121
- prometheus/devcontainer.patch.json (200 lines with OTEL config)
122
- jaeger/devcontainer.patch.json (200 lines with OTEL config)
123
- grafana/devcontainer.patch.json (200 lines with OTEL config)
135
+ ## Worked Example: OTEL Instrumentation
136
+
137
+ Many observability overlays need OTEL environment variables. With imports, these are defined once:
138
+
139
+ **`overlays/.shared/otel/instrumentation.env`** — shared once
140
+
141
+ **`overlays/otel-collector/overlay.yml`:**
142
+
143
+ ```yaml
144
+ imports:
145
+ - .shared/otel/instrumentation.env
124
146
  ```
125
147
 
126
- After imports:
148
+ **`overlays/prometheus/overlay.yml`:**
127
149
 
150
+ ```yaml
151
+ imports:
152
+ - .shared/otel/instrumentation.env
128
153
  ```
129
- .shared/otel/otel-base-config.yaml (50 lines, shared)
130
- prometheus/overlay.yml (imports: [.shared/otel/otel-base-config.yaml])
131
- jaeger/overlay.yml (imports: [.shared/otel/otel-base-config.yaml])
132
- grafana/overlay.yml (imports: [.shared/otel/otel-base-config.yaml])
154
+
155
+ **`overlays/jaeger/overlay.yml`:**
156
+
157
+ ```yaml
158
+ imports:
159
+ - .shared/otel/instrumentation.env
133
160
  ```
134
161
 
135
- ### Consistency
162
+ When any of these overlays is used, the generated `.env.example` will contain the OTEL environment variables with a comment indicating they came from the shared fragment.
163
+
164
+ ## Security: Path Traversal Prevention
136
165
 
137
- All overlays using the same shared config stay in sync automatically.
166
+ Import paths are validated before any file is read:
138
167
 
139
- ### Maintainability
168
+ 1. The path **must** begin with `.shared/`
169
+ 2. The resolved absolute path **must** remain inside `overlays/.shared/`
140
170
 
141
- Update shared configuration once, all importing overlays benefit.
171
+ Any import that fails either check causes generation to abort with an error identifying the overlay and the rejected path. References like `../secret.json`, `/etc/passwd`, or `other-overlay/file.json` are all rejected.
142
172
 
143
- ## Validation
173
+ ## Validation via Doctor
144
174
 
145
- The `doctor` command validates imports:
175
+ The `doctor` command validates all imports for every overlay:
146
176
 
147
177
  ```bash
148
178
  container-superposition doctor
@@ -150,60 +180,53 @@ container-superposition doctor
150
180
 
151
181
  Checks performed:
152
182
 
153
- - Import files exist
154
- - File types are supported (`.json`, `.yaml`, `.yml`, `.env`)
155
- - No broken import references
156
-
157
- ## Creating Shared Configurations
158
-
159
- 1. **Identify common patterns** across overlays
160
- 2. **Extract to `.shared/` subdirectory** with descriptive path
161
- 3. **Update overlays** to import the shared file
162
- 4. **Test** that composition works correctly
163
- 5. **Document** the shared file's purpose in `.shared/README.md`
183
+ - Import path starts with `.shared/` (path traversal check)
184
+ - Import path resolves within `overlays/.shared/` (traversal check)
185
+ - Import file exists on disk
186
+ - File type is one of `.json`, `.yaml`, `.yml`, `.env`
164
187
 
165
- ## Example: OTEL Instrumentation
188
+ Broken references are reported with the overlay ID and the bad path so maintainers can fix them quickly.
166
189
 
167
- Many observability overlays need OTEL instrumentation. Instead of duplicating these environment variables:
190
+ ## Viewing Imports in `explain`
168
191
 
169
- **Create:** `overlays/.shared/otel/instrumentation.env`
192
+ When an overlay has imports, they are shown in the `explain` output:
170
193
 
171
194
  ```bash
172
- # OpenTelemetry SDK Configuration
173
- OTEL_SERVICE_NAME=my-service
174
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
175
- OTEL_EXPORTER_OTLP_PROTOCOL=grpc
176
- OTEL_RESOURCE_ATTRIBUTES=deployment.environment=development
177
- OTEL_TRACES_SAMPLER=always_on
178
- OTEL_TRACES_EXPORTER=otlp
179
- OTEL_METRICS_EXPORTER=otlp
180
- OTEL_LOGS_EXPORTER=otlp
195
+ container-superposition explain prometheus
181
196
  ```
182
197
 
183
- **Import in overlays:**
198
+ ```
199
+ Shared Imports:
200
+ (Fragments from overlays/.shared/ applied before this overlay)
201
+ 📎 .shared/otel/instrumentation.env
202
+ ```
184
203
 
185
- ```yaml
186
- # overlays/prometheus/overlay.yml
187
- imports:
188
- - .shared/otel/instrumentation.env
204
+ ## Creating Shared Configurations
189
205
 
190
- # overlays/jaeger/overlay.yml
191
- imports:
192
- - .shared/otel/instrumentation.env
193
- ```
206
+ 1. **Identify common patterns** across multiple overlays
207
+ 2. **Create `overlays/.shared/<category>/<name>.<ext>`** — use descriptive paths, one concern per file
208
+ 3. **Update overlays** to reference the fragment via `imports:` in their `overlay.yml`
209
+ 4. **Update `.shared/README.md`** to document the fragment's purpose and which overlays use it
210
+ 5. **Test** with `npm test` and `container-superposition doctor` to verify
211
+
212
+ ## Downstream Impact Awareness
213
+
214
+ A single change to a shared fragment affects every overlay that imports it. Before editing a shared fragment:
194
215
 
195
- Now all OTEL-compatible overlays share the same instrumentation configuration!
216
+ - Check `.shared/README.md` to see which overlays import it
217
+ - Use `grep -r "fragment-name" overlays/*/overlay.yml` to find all importers
218
+ - Run the full test suite after any shared fragment change
196
219
 
197
220
  ## Best Practices
198
221
 
199
- 1. **Keep shared files focused** - One concern per file
200
- 2. **Use descriptive paths** - `.shared/otel/instrumentation.env` not `.shared/env1.env`
201
- 3. **Document shared files** - Add comments explaining purpose and usage
202
- 4. **Version carefully** - Changes to shared files affect all importing overlays
203
- 5. **Test imports** - Verify overlay composition works after adding imports
222
+ 1. **One concern per file** `instrumentation.env` not `all-the-things.env`
223
+ 2. **Descriptive category paths** `.shared/otel/` not `.shared/misc/`
224
+ 3. **Comment your fragments** explain purpose and usage at the top of each file
225
+ 4. **Keep fragments small** big shared files create tight coupling
226
+ 5. **Overlay-specific overrides are fine** an overlay's own patch always wins; diverging from a shared baseline is expected and supported
204
227
 
205
228
  ## See Also
206
229
 
207
230
  - [Creating Overlays](creating-overlays.md)
208
- - [Overlay Metadata](overlay-metadata-archive.md)
209
- - [Doctor Command](../README.md#doctor-command)
231
+ - `overlays/.shared/README.md` — shared fragment catalogue with usage details
232
+ - CONTRIBUTING.md — overlay authoring guide
package/docs/overlays.md CHANGED
@@ -69,12 +69,13 @@ Jupyter notebook server for interactive computing and data science
69
69
 
70
70
  Material for MkDocs - professional documentation generator
71
71
 
72
- | Property | Value |
73
- | ------------ | ----------------------------------- |
74
- | **Category** | language |
75
- | **Requires** | `python` |
76
- | **Tags** | `documentation`, `mkdocs`, `python` |
77
- | **Ports** | 8000 |
72
+ | Property | Value |
73
+ | ------------- | ----------------------------------- |
74
+ | **Category** | language |
75
+ | **Requires** | `python` |
76
+ | **Conflicts** | `mkdocs2` |
77
+ | **Tags** | `documentation`, `mkdocs`, `python` |
78
+ | **Ports** | 8000 |
78
79
 
79
80
  ### Node.js (`nodejs`)
80
81
 
@@ -452,6 +453,16 @@ Specify CLI for Spec-Driven Development with any AI coding agent
452
453
  | **Suggests** | `python`, `codex` |
453
454
  | **Tags** | `dev`, `ai`, `sdd`, `spec-driven`, `specify`, `spec-kit` |
454
455
 
456
+ ### Pandoc PDF (`pandoc`)
457
+
458
+ Pandoc with XeLaTeX, Mermaid diagrams, and quality fonts for Markdown-to-PDF export
459
+
460
+ | Property | Value |
461
+ | ------------ | -------------------------------------------------------------- |
462
+ | **Category** | dev |
463
+ | **Suggests** | `nodejs` |
464
+ | **Tags** | `dev`, `pandoc`, `pdf`, `latex`, `markdown`, `docs`, `mermaid` |
465
+
455
466
  ### Amp (`amp`)
456
467
 
457
468
  Sourcegraph Amp CLI for AI-powered code generation and assistance
@@ -503,6 +514,26 @@ Conventional commits validation for automated releases
503
514
  | **Suggests** | `pre-commit` |
504
515
  | **Tags** | `dev`, `git`, `commits`, `semantic-release` |
505
516
 
517
+ ### CUDA (NVIDIA GPU) (`cuda`)
518
+
519
+ NVIDIA CUDA libraries and GPU passthrough for containerized ML/inference workloads
520
+
521
+ | Property | Value |
522
+ | ------------- | ------------------------------------------------- |
523
+ | **Category** | dev |
524
+ | **Conflicts** | `rocm` |
525
+ | **Tags** | `dev`, `gpu`, `cuda`, `nvidia`, `ml`, `inference` |
526
+
527
+ ### Dev Container CLI (`devcontainer-cli`)
528
+
529
+ Official devcontainer CLI for building and testing devcontainer configurations
530
+
531
+ | Property | Value |
532
+ | ------------ | --------------------------------------- |
533
+ | **Category** | dev |
534
+ | **Suggests** | `docker-sock`, `docker-in-docker` |
535
+ | **Tags** | `dev`, `devcontainer`, `cli`, `testing` |
536
+
506
537
  ### direnv (`direnv`)
507
538
 
508
539
  Per-directory environment variable management
@@ -592,6 +623,18 @@ Email testing tool with web UI and SMTP server
592
623
  | **Tags** | `dev`, `email`, `smtp`, `testing` |
593
624
  | **Ports** | [object Object], [object Object] |
594
625
 
626
+ ### MkDocs 2 (`mkdocs2`)
627
+
628
+ MkDocs 2.0 pre-release (encode/mkdocs) — smart, simple website design tool
629
+
630
+ | Property | Value |
631
+ | ------------- | ------------------------------------------ |
632
+ | **Category** | dev |
633
+ | **Requires** | `python` |
634
+ | **Conflicts** | `mkdocs` |
635
+ | **Tags** | `dev`, `documentation`, `mkdocs`, `python` |
636
+ | **Ports** | 8000 |
637
+
595
638
  ### Modern CLI Tools (`modern-cli-tools`)
596
639
 
597
640
  jq, yq, ripgrep, fd, bat - Essential modern command-line tools
@@ -652,6 +695,16 @@ Automated code quality gates with pre-commit hooks
652
695
  | **Suggests** | `commitlint` |
653
696
  | **Tags** | `dev`, `git`, `quality`, `hooks` |
654
697
 
698
+ ### ROCm (AMD GPU) (`rocm`)
699
+
700
+ AMD ROCm libraries and GPU passthrough for containerized ML/inference workloads
701
+
702
+ | Property | Value |
703
+ | ------------- | ---------------------------------------------- |
704
+ | **Category** | dev |
705
+ | **Conflicts** | `cuda` |
706
+ | **Tags** | `dev`, `gpu`, `rocm`, `amd`, `ml`, `inference` |
707
+
655
708
  ### Tilt (`tilt`)
656
709
 
657
710
  Live update and orchestration for Kubernetes development
@@ -162,6 +162,105 @@ npm run init -- \
162
162
  --cloud-tools aws-cli,azure-cli,kubectl-helm
163
163
  ```
164
164
 
165
+ ## Doctor Command
166
+
167
+ The `doctor` command validates the current environment and devcontainer configuration.
168
+
169
+ ### Basic Diagnostics
170
+
171
+ ```bash
172
+ # Run diagnostics against the default .devcontainer/
173
+ container-superposition doctor
174
+
175
+ # Specify a custom path
176
+ container-superposition doctor --output ./my-project/.devcontainer
177
+
178
+ # Point to a manifest file directly (outputPath is derived from the manifest)
179
+ container-superposition doctor --from-manifest ./superposition.json
180
+
181
+ # Load the output path from the repository project file (superposition.yml)
182
+ container-superposition doctor --from-project
183
+
184
+ # Run discovery relative to a different repository root
185
+ container-superposition doctor --project-root /path/to/repo
186
+
187
+ # Machine-readable JSON output
188
+ container-superposition doctor --json
189
+ ```
190
+
191
+ ### Auto-Repair with `--fix`
192
+
193
+ The `--fix` flag runs the full diagnosis and then attempts to automatically repair
194
+ any fixable issues:
195
+
196
+ ```bash
197
+ # Interactive auto-repair (text output)
198
+ container-superposition doctor --fix
199
+
200
+ # Machine-readable repair output (for CI/scripting)
201
+ container-superposition doctor --fix --json
202
+ ```
203
+
204
+ **Fix run output vocabulary:**
205
+
206
+ | Outcome | Meaning |
207
+ | ------------------------ | ---------------------------------------------------- |
208
+ | `fixed` | Tool changed the environment; re-check now passes |
209
+ | `already compliant` | No change needed — check already passed |
210
+ | `skipped` | Not attempted (prerequisite step failed) |
211
+ | `requires manual action` | Automation unsafe/unavailable; manual steps provided |
212
+
213
+ **Fixable issue classes:**
214
+
215
+ | Issue | Auto-fix condition |
216
+ | -------------------------------------------- | ---------------------------------------------------------- |
217
+ | Stale / legacy `superposition.json` manifest | Always — migrate to current schema |
218
+ | Missing or corrupt `devcontainer.json` | When a valid manifest is present — regenerate |
219
+ | Unsupported Node.js runtime | Only when `nvm`, `fnm`, or `volta` is installed |
220
+ | Docker daemon not accessible | Manual only — platform-specific restart instructions shown |
221
+
222
+ **Remediation ordering:** Manifest migration always runs before devcontainer regeneration.
223
+ If migration fails, regeneration is skipped and marked as `skipped`.
224
+
225
+ **Safety:** All file mutations use atomic write (write to `.tmp`, then rename).
226
+ A timestamped backup is created before any manifest is modified.
227
+
228
+ **Exit codes:**
229
+
230
+ - `0` — all findings resolved (success or already-compliant)
231
+ - `0` — some findings require manual action (`repaired-with-warnings`)
232
+ - `1` — unresolved failures remain after fix run
233
+
234
+ ### JSON Fix Run Structure
235
+
236
+ ```json
237
+ {
238
+ "outputPath": "./.devcontainer",
239
+ "requestedJson": true,
240
+ "initialFindings": [...],
241
+ "executions": [
242
+ {
243
+ "findingId": "manifest-version",
244
+ "remediationKey": "manifest-migration",
245
+ "attempted": true,
246
+ "outcome": "fixed",
247
+ "reason": "Manifest migrated to current schema version",
248
+ "changedFiles": [".devcontainer/superposition.json"],
249
+ "backupPath": ".devcontainer/superposition.json.backup-2026-03-19-..."
250
+ }
251
+ ],
252
+ "finalFindings": [...],
253
+ "summary": {
254
+ "fixed": 1,
255
+ "alreadyCompliant": 3,
256
+ "skipped": 0,
257
+ "requiresManualAction": 0,
258
+ "total": 4
259
+ },
260
+ "exitDisposition": "success"
261
+ }
262
+ ```
263
+
165
264
  ## Output Structure
166
265
 
167
266
  ### Minimal (plain + language)
@@ -17,7 +17,12 @@ The design extends the existing answer-merging flow instead of creating a second
17
17
  generation pipeline, introduces an explicit `--from-project` mode, allows
18
18
  implicit project-file use for `init --no-interactive` and default `regen` when
19
19
  no conflicting source or selection flags are supplied, and keeps explicit
20
- manifest-based regeneration as a separate persisted-input mode.
20
+ manifest-based regeneration as a separate persisted-input mode. The same schema
21
+ must also be writable from `adopt --project-file` so migration from an existing
22
+ `.devcontainer/` can produce a repository-root project config without inventing
23
+ a parallel declaration format. Persisted-input workflows must also support an
24
+ explicit repository-root override so users can run `init` or `regen` against a
25
+ different repository without first changing their shell working directory.
21
26
 
22
27
  ## Technical Context
23
28
 
@@ -29,6 +29,8 @@ A project maintainer defines the desired development environment in a single rep
29
29
 
30
30
  1. **Given** a repository with a valid project config file in its root that defines stack, overlay selections, output location, and supported customization settings, **When** a maintainer runs the generation flow from that repository root, **Then** the tool uses those values as the starting configuration for generation.
31
31
  2. **Given** a repository with a committed project config file, **When** a teammate clones the repository and runs the same generation flow from a fresh checkout, **Then** they receive the same effective project setup without needing the original author’s shell history or copied command examples.
32
+ 3. **Given** a repository with an existing hand-crafted `.devcontainer/`, **When** a maintainer runs `adopt --project-file`, **Then** the tool writes a repository-root project config that captures the inferred stack, overlay selections, output path, and supported customization inputs from the adopted setup.
33
+ 4. **Given** a maintainer is working outside the target repository, **When** they run `init --from-project --project-root <path>` or `regen --project-root <path>`, **Then** the tool resolves the project file and relative output paths from that selected repository root.
32
34
 
33
35
  ---
34
36
 
@@ -72,6 +74,8 @@ A contributor receives clear guidance when the project config file is invalid, i
72
74
  - How does the system handle supported customizations such as environment settings, custom container definitions, or additional generated features? Those values are treated as first-class generation inputs and must round-trip through the project config file without being dropped.
73
75
  - How does the system handle unsupported overlay IDs, invalid categories, or conflicting selections in the project config file? It fails validation before generation and explains the invalid entries.
74
76
  - How does the system handle both `.superposition.yml` and `superposition.yml` in one repository? It treats this as an error to avoid ambiguity.
77
+ - How does the system handle `adopt --project-file` when a repository already contains a supported project config file? It reuses that file path, and it must still stop on dual-file ambiguity so the source of truth stays deterministic.
78
+ - How does the system handle project-file or manifest discovery from outside the target repository? An explicit project-root option may redirect persisted-input discovery and relative output resolution to that repository root.
75
79
 
76
80
  ## Requirements _(mandatory)_
77
81
 
@@ -96,6 +100,8 @@ A contributor receives clear guidance when the project config file is invalid, i
96
100
  - **FR-017**: The system MUST allow `init --no-interactive` and `regen` to use the repository project file implicitly when a valid project config file exists and no other persisted-input source flag or clean-generation selection flags are supplied.
97
101
  - **FR-018**: The system MUST reject conflicting persisted-input source combinations before generation, including `--from-project` with `--from-manifest` and either source-selection mode combined with clean-generation selection flags such as stack, overlay, or preset selection.
98
102
  - **FR-019**: The system MUST document how teams create, commit, validate, and use the project config file in local development, regeneration, and automation workflows, including how parity with clean generation applies to supported customization inputs and how source-selection conflicts are resolved.
103
+ - **FR-020**: The system MUST allow `adopt --project-file` to write a repository-root project config that represents the inferred adopted setup using the same supported declaration surface as other project-config workflows.
104
+ - **FR-021**: The system MUST allow `init` and `regen` to resolve project-file and manifest discovery from an explicitly selected repository root so users can run persisted-input workflows without changing their shell working directory first.
99
105
 
100
106
  ### Key Entities _(include if feature involves data)_
101
107
 
@@ -60,6 +60,8 @@
60
60
  - [x] T016 [US1] Preserve supported customization inputs through generation and summary rendering in `scripts/init.ts`
61
61
  - [x] T017 [US1] Ensure project-config driven answers produce the same composed output as equivalent clean-generation input in `tool/questionnaire/composer.ts`
62
62
  - [x] T018 [US1] Keep generated run summaries accurate for project-config sourced generation in `tool/utils/summary.ts`
63
+ - [x] T018a [US1] Let `adopt --project-file` write a repository-root project config from inferred overlay selections and supported customizations in `tool/commands/adopt.ts` and `tool/schema/project-config.ts`
64
+ - [x] T018b [US1] Let `init` and `regen` target a different repository root for project-file and manifest discovery via `--project-root <path>` in `scripts/init.ts` and `tool/__tests__/commands.test.ts`
63
65
 
64
66
  **Checkpoint**: User Story 1 should now be fully functional and testable on its own
65
67