container-superposition 0.1.7 → 0.1.9

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 (242) hide show
  1. package/README.md +24 -15
  2. package/dist/scripts/init.js +1 -1537
  3. package/dist/scripts/init.js.map +1 -1
  4. package/dist/tool/cli/args.d.ts +20 -0
  5. package/dist/tool/cli/args.d.ts.map +1 -0
  6. package/dist/tool/cli/args.js +325 -0
  7. package/dist/tool/cli/args.js.map +1 -0
  8. package/dist/tool/cli/run.d.ts +2 -0
  9. package/dist/tool/cli/run.d.ts.map +1 -0
  10. package/dist/tool/cli/run.js +318 -0
  11. package/dist/tool/cli/run.js.map +1 -0
  12. package/dist/tool/commands/adopt.js +1 -1
  13. package/dist/tool/commands/adopt.js.map +1 -1
  14. package/dist/tool/commands/doctor.d.ts +1 -0
  15. package/dist/tool/commands/doctor.d.ts.map +1 -1
  16. package/dist/tool/commands/doctor.js +1510 -78
  17. package/dist/tool/commands/doctor.js.map +1 -1
  18. package/dist/tool/commands/explain.d.ts.map +1 -1
  19. package/dist/tool/commands/explain.js +9 -0
  20. package/dist/tool/commands/explain.js.map +1 -1
  21. package/dist/tool/commands/migrate.d.ts +7 -0
  22. package/dist/tool/commands/migrate.d.ts.map +1 -0
  23. package/dist/tool/commands/migrate.js +52 -0
  24. package/dist/tool/commands/migrate.js.map +1 -0
  25. package/dist/tool/questionnaire/answers.d.ts +16 -0
  26. package/dist/tool/questionnaire/answers.d.ts.map +1 -0
  27. package/dist/tool/questionnaire/answers.js +102 -0
  28. package/dist/tool/questionnaire/answers.js.map +1 -0
  29. package/dist/tool/questionnaire/composer.d.ts +6 -4
  30. package/dist/tool/questionnaire/composer.d.ts.map +1 -1
  31. package/dist/tool/questionnaire/composer.js +778 -45
  32. package/dist/tool/questionnaire/composer.js.map +1 -1
  33. package/dist/tool/questionnaire/presets.d.ts +60 -0
  34. package/dist/tool/questionnaire/presets.d.ts.map +1 -0
  35. package/dist/tool/questionnaire/presets.js +165 -0
  36. package/dist/tool/questionnaire/presets.js.map +1 -0
  37. package/dist/tool/questionnaire/questionnaire.d.ts +10 -0
  38. package/dist/tool/questionnaire/questionnaire.d.ts.map +1 -0
  39. package/dist/tool/questionnaire/questionnaire.js +582 -0
  40. package/dist/tool/questionnaire/questionnaire.js.map +1 -0
  41. package/dist/tool/schema/manifest-migrations.d.ts +5 -0
  42. package/dist/tool/schema/manifest-migrations.d.ts.map +1 -1
  43. package/dist/tool/schema/manifest-migrations.js +45 -0
  44. package/dist/tool/schema/manifest-migrations.js.map +1 -1
  45. package/dist/tool/schema/overlay-loader.d.ts.map +1 -1
  46. package/dist/tool/schema/overlay-loader.js +24 -0
  47. package/dist/tool/schema/overlay-loader.js.map +1 -1
  48. package/dist/tool/schema/project-config.d.ts +13 -1
  49. package/dist/tool/schema/project-config.d.ts.map +1 -1
  50. package/dist/tool/schema/project-config.js +188 -10
  51. package/dist/tool/schema/project-config.js.map +1 -1
  52. package/dist/tool/schema/target-rules.d.ts +78 -0
  53. package/dist/tool/schema/target-rules.d.ts.map +1 -0
  54. package/dist/tool/schema/target-rules.js +367 -0
  55. package/dist/tool/schema/target-rules.js.map +1 -0
  56. package/dist/tool/schema/types.d.ts +42 -3
  57. package/dist/tool/schema/types.d.ts.map +1 -1
  58. package/dist/tool/utils/parameters.d.ts +76 -0
  59. package/dist/tool/utils/parameters.d.ts.map +1 -0
  60. package/dist/tool/utils/parameters.js +125 -0
  61. package/dist/tool/utils/parameters.js.map +1 -0
  62. package/dist/tool/utils/paths.d.ts +2 -0
  63. package/dist/tool/utils/paths.d.ts.map +1 -0
  64. package/dist/tool/utils/paths.js +31 -0
  65. package/dist/tool/utils/paths.js.map +1 -0
  66. package/docs/deployment-targets.md +88 -56
  67. package/docs/examples.md +20 -17
  68. package/docs/filesystem-contract.md +5 -0
  69. package/docs/minimal-and-editor.md +65 -5
  70. package/docs/overlay-imports.md +92 -14
  71. package/docs/overlays.md +231 -135
  72. package/docs/specs/001-verbose-plan-graph/spec.md +5 -12
  73. package/docs/specs/002-superposition-config-file/spec.md +5 -12
  74. package/docs/specs/003-mkdocs2-overlay/spec.md +2 -9
  75. package/docs/specs/004-doctor-fix/spec.md +1 -8
  76. package/docs/specs/005-cuda-overlay/spec.md +2 -9
  77. package/docs/specs/006-rocm-overlay/spec.md +3 -10
  78. package/docs/specs/007-target-aware-generation/spec.md +119 -0
  79. package/docs/specs/008-project-file-canonical/spec.md +82 -0
  80. package/docs/specs/009-project-env/spec.md +140 -0
  81. package/docs/specs/010-compose-env-materialization/spec.md +123 -0
  82. package/docs/specs/011-overlay-parameters/spec.md +228 -0
  83. package/docs/specs/012-ollama-cli-overlay/spec.md +47 -0
  84. package/docs/specs/013-doctor-dependency-check/spec.md +250 -0
  85. package/docs/specs/014-doctor-compose-port-cross-validation/spec.md +276 -0
  86. package/docs/specs/015-doctor-env-example-drift/spec.md +248 -0
  87. package/docs/specs/016-doctor-reproducibility-check/spec.md +276 -0
  88. package/docs/specs/017-doctor-dry-run/spec.md +276 -0
  89. package/docs/specs/018-init-project-file/spec.md +59 -0
  90. package/docs/specs/taxonomy.md +186 -0
  91. package/overlays/.presets/full-observability.yml +113 -0
  92. package/overlays/.presets/k8s-dev.yml +174 -0
  93. package/overlays/.presets/local-llm.yml +105 -0
  94. package/overlays/.presets/vector-ai.yml +150 -0
  95. package/overlays/.shared/README.md +27 -2
  96. package/overlays/.shared/compose/nvidia-gpu-devcontainer.yml +22 -0
  97. package/overlays/.shared/vscode/js-ts-settings.json +19 -0
  98. package/overlays/.shared/vscode/markdown-extensions.json +8 -0
  99. package/overlays/alertmanager/devcontainer.patch.json +0 -1
  100. package/overlays/alertmanager/docker-compose.yml +8 -0
  101. package/overlays/alertmanager/overlay.yml +1 -0
  102. package/overlays/amp/devcontainer.patch.json +4 -1
  103. package/overlays/bun/devcontainer.patch.json +1 -10
  104. package/overlays/bun/overlay.yml +8 -1
  105. package/overlays/claude-code/devcontainer.patch.json +6 -1
  106. package/overlays/codex/devcontainer.patch.json +5 -0
  107. package/overlays/comfyui/.env.example +34 -0
  108. package/overlays/comfyui/README.md +342 -0
  109. package/overlays/comfyui/devcontainer.patch.json +15 -0
  110. package/overlays/comfyui/docker-compose.yml +40 -0
  111. package/overlays/comfyui/overlay.yml +24 -0
  112. package/overlays/comfyui/setup.sh +36 -0
  113. package/overlays/comfyui/verify.sh +103 -0
  114. package/overlays/commitlint/devcontainer.patch.json +1 -6
  115. package/overlays/docker-sock/overlay.yml +1 -0
  116. package/overlays/dotnet/overlay.yml +4 -1
  117. package/overlays/fuseki/.env.example +5 -0
  118. package/overlays/fuseki/README.md +173 -0
  119. package/overlays/fuseki/devcontainer.patch.json +18 -0
  120. package/overlays/fuseki/docker-compose.yml +29 -0
  121. package/overlays/fuseki/overlay.yml +42 -0
  122. package/overlays/fuseki/verify.sh +58 -0
  123. package/overlays/gemini-cli/devcontainer.patch.json +4 -1
  124. package/overlays/go/overlay.yml +6 -1
  125. package/overlays/grafana/devcontainer.patch.json +0 -1
  126. package/overlays/grafana/docker-compose.yml +8 -2
  127. package/overlays/grafana/overlay.yml +6 -1
  128. package/overlays/jaeger/.env.example +11 -0
  129. package/overlays/jaeger/README.md +33 -4
  130. package/overlays/jaeger/devcontainer.patch.json +9 -1
  131. package/overlays/jaeger/docker-compose.yml +17 -0
  132. package/overlays/jaeger/overlay.yml +1 -12
  133. package/overlays/java/overlay.yml +6 -1
  134. package/overlays/jupyter/docker-compose.yml +1 -0
  135. package/overlays/jupyter/overlay.yml +1 -0
  136. package/overlays/k3d/README.md +201 -0
  137. package/overlays/k3d/devcontainer.patch.json +9 -0
  138. package/overlays/k3d/overlay.yml +19 -0
  139. package/overlays/k3d/setup.sh +34 -0
  140. package/overlays/k3d/verify.sh +38 -0
  141. package/overlays/keycloak/devcontainer.patch.json +0 -1
  142. package/overlays/keycloak/docker-compose.yml +1 -0
  143. package/overlays/keycloak/overlay.yml +15 -0
  144. package/overlays/localstack/docker-compose.yml +1 -0
  145. package/overlays/localstack/overlay.yml +19 -1
  146. package/overlays/loki/devcontainer.patch.json +0 -1
  147. package/overlays/loki/docker-compose.yml +8 -0
  148. package/overlays/loki/overlay.yml +1 -0
  149. package/overlays/mailpit/docker-compose.yml +1 -0
  150. package/overlays/mailpit/overlay.yml +1 -0
  151. package/overlays/minio/devcontainer.patch.json +1 -1
  152. package/overlays/minio/docker-compose.yml +1 -0
  153. package/overlays/minio/overlay.yml +23 -2
  154. package/overlays/mkdocs/devcontainer.patch.json +1 -5
  155. package/overlays/mkdocs/overlay.yml +3 -1
  156. package/overlays/mkdocs2/devcontainer.patch.json +1 -5
  157. package/overlays/mkdocs2/overlay.yml +2 -0
  158. package/overlays/mongodb/docker-compose.yml +2 -0
  159. package/overlays/mongodb/overlay.yml +26 -2
  160. package/overlays/mysql/docker-compose.yml +2 -0
  161. package/overlays/mysql/overlay.yml +36 -2
  162. package/overlays/nats/docker-compose.yml +1 -0
  163. package/overlays/nats/overlay.yml +18 -2
  164. package/overlays/nodejs/devcontainer.patch.json +1 -12
  165. package/overlays/nodejs/overlay.yml +8 -1
  166. package/overlays/ollama/.env.example +14 -0
  167. package/overlays/ollama/README.md +326 -0
  168. package/overlays/ollama/devcontainer.patch.json +14 -0
  169. package/overlays/ollama/docker-compose.yml +25 -0
  170. package/overlays/ollama/overlay.yml +27 -0
  171. package/overlays/ollama/verify.sh +76 -0
  172. package/overlays/ollama-cli/README.md +90 -0
  173. package/overlays/ollama-cli/devcontainer.patch.json +3 -0
  174. package/overlays/ollama-cli/overlay.yml +19 -0
  175. package/overlays/ollama-cli/setup.sh +103 -0
  176. package/overlays/ollama-cli/verify.sh +49 -0
  177. package/overlays/open-webui/.env.example +5 -0
  178. package/overlays/open-webui/README.md +162 -0
  179. package/overlays/open-webui/devcontainer.patch.json +14 -0
  180. package/overlays/open-webui/docker-compose.yml +24 -0
  181. package/overlays/open-webui/overlay.yml +45 -0
  182. package/overlays/opencode/devcontainer.patch.json +4 -1
  183. package/overlays/otel-collector/README.md +4 -0
  184. package/overlays/otel-collector/devcontainer.patch.json +4 -1
  185. package/overlays/otel-collector/docker-compose.yml +8 -4
  186. package/overlays/otel-collector/overlay.yml +1 -0
  187. package/overlays/otel-demo-nodejs/devcontainer.patch.json +0 -1
  188. package/overlays/otel-demo-nodejs/docker-compose.yml +1 -0
  189. package/overlays/otel-demo-nodejs/overlay.yml +9 -1
  190. package/overlays/otel-demo-python/devcontainer.patch.json +0 -1
  191. package/overlays/otel-demo-python/docker-compose.yml +1 -0
  192. package/overlays/otel-demo-python/overlay.yml +6 -1
  193. package/overlays/pandoc/README.md +10 -0
  194. package/overlays/pandoc/devcontainer.patch.json +0 -5
  195. package/overlays/pandoc/overlay.yml +2 -0
  196. package/overlays/pandoc/setup.sh +10 -0
  197. package/overlays/pgvector/.env.example +6 -0
  198. package/overlays/pgvector/README.md +215 -0
  199. package/overlays/pgvector/devcontainer.patch.json +29 -0
  200. package/overlays/pgvector/docker-compose.yml +33 -0
  201. package/overlays/pgvector/overlay.yml +47 -0
  202. package/overlays/playwright/devcontainer.patch.json +0 -5
  203. package/overlays/playwright/overlay.yml +2 -1
  204. package/overlays/postgres/.env.example +5 -5
  205. package/overlays/postgres/devcontainer.patch.json +4 -4
  206. package/overlays/postgres/docker-compose.yml +11 -6
  207. package/overlays/postgres/overlay.yml +23 -2
  208. package/overlays/pre-commit/devcontainer.patch.json +1 -7
  209. package/overlays/prometheus/devcontainer.patch.json +0 -1
  210. package/overlays/prometheus/docker-compose.yml +8 -0
  211. package/overlays/prometheus/overlay.yml +1 -0
  212. package/overlays/promtail/devcontainer.patch.json +1 -2
  213. package/overlays/promtail/docker-compose.yml +8 -0
  214. package/overlays/promtail/overlay.yml +1 -0
  215. package/overlays/qdrant/.env.example +4 -0
  216. package/overlays/qdrant/README.md +216 -0
  217. package/overlays/qdrant/devcontainer.patch.json +20 -0
  218. package/overlays/qdrant/docker-compose.yml +26 -0
  219. package/overlays/qdrant/overlay.yml +44 -0
  220. package/overlays/rabbitmq/docker-compose.yml +1 -0
  221. package/overlays/rabbitmq/overlay.yml +25 -2
  222. package/overlays/redis/docker-compose.yml +7 -0
  223. package/overlays/redis/overlay.yml +15 -1
  224. package/overlays/redpanda/docker-compose.yml +1 -0
  225. package/overlays/redpanda/overlay.yml +15 -3
  226. package/overlays/rocm/overlay.yml +2 -1
  227. package/overlays/rust/overlay.yml +3 -1
  228. package/overlays/skaffold/README.md +256 -0
  229. package/overlays/skaffold/devcontainer.patch.json +9 -0
  230. package/overlays/skaffold/overlay.yml +20 -0
  231. package/overlays/skaffold/setup.sh +33 -0
  232. package/overlays/skaffold/verify.sh +24 -0
  233. package/overlays/sqlserver/docker-compose.yml +1 -0
  234. package/overlays/sqlserver/overlay.yml +17 -0
  235. package/overlays/tempo/devcontainer.patch.json +0 -1
  236. package/overlays/tempo/docker-compose.yml +8 -0
  237. package/overlays/tempo/overlay.yml +1 -0
  238. package/overlays/windsurf-cli/devcontainer.patch.json +4 -1
  239. package/package.json +3 -2
  240. package/tool/schema/config.schema.json +31 -1
  241. package/tool/schema/overlay-manifest.schema.json +33 -0
  242. package/overlays/.shared/otel/otel-base-config.yaml +0 -30
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Overlay parameter resolution and {{cs.PARAM_NAME}} substitution engine.
3
+ *
4
+ * Syntax: {{cs.PARAM_NAME}} — chosen because it:
5
+ * - does NOT collide with Docker Compose ${VAR} / ${VAR:-default}
6
+ * - does NOT collide with shell $VAR / ${VAR} / ${VAR:-x}
7
+ * - does NOT collide with VS Code ${localWorkspaceFolder} / ${env:VAR}
8
+ * - does NOT collide with GitHub Actions ${{ github.* }}
9
+ * - is consistent with the existing preset {{parameters.<key>.id}} convention
10
+ *
11
+ * This module deliberately has NO parser, NO AST, NO conditionals.
12
+ * If string.replace() can't do it, it doesn't belong here.
13
+ */
14
+ import type { OverlayMetadata, OverlayParameterDefinition } from '../schema/types.js';
15
+ /**
16
+ * A parameter declaration enriched with the overlay that declared it.
17
+ */
18
+ export interface DeclaredParameter extends OverlayParameterDefinition {
19
+ overlayId: string;
20
+ }
21
+ /**
22
+ * Result of parameter resolution.
23
+ */
24
+ export interface ResolvedParameters {
25
+ /** Key → resolved value map ready for substitution. */
26
+ values: Record<string, string>;
27
+ /** Parameters that are required but have no value — generation must fail. */
28
+ missingRequired: string[];
29
+ /** User-supplied parameter keys not declared by any selected overlay (warnings only). */
30
+ unknownSupplied: string[];
31
+ }
32
+ /**
33
+ * Collect all parameter declarations from the selected overlay set.
34
+ * Returns a map of parameter name → declaration enriched with the declaring overlay.
35
+ *
36
+ * When two overlays declare the same parameter name, the first declaration wins
37
+ * (overlays are processed in composition order).
38
+ */
39
+ export declare function collectOverlayParameters(overlayIds: string[], allOverlayDefs: OverlayMetadata[]): Record<string, DeclaredParameter>;
40
+ /**
41
+ * Resolve parameter values by applying the resolution order:
42
+ * 1. Supplied values (from project file or CLI — highest priority)
43
+ * 2. Overlay defaults (lowest priority)
44
+ *
45
+ * Returns resolved values, any missing-required errors, and unknown-supplied warnings.
46
+ */
47
+ export declare function resolveParameters(declared: Record<string, DeclaredParameter>, supplied: Record<string, string>): ResolvedParameters;
48
+ /**
49
+ * Replace all {{cs.KEY}} tokens in `content` with the corresponding resolved value.
50
+ * Tokens for keys not present in `resolved` are left intact (to be caught by validation).
51
+ *
52
+ * Docker Compose ${VAR}, shell $VAR, VS Code ${env:VAR}, and GitHub Actions ${{ }}
53
+ * expressions are NEVER touched — only the {{cs.KEY}} pattern is matched.
54
+ */
55
+ export declare function substituteParameters(content: string, resolved: Record<string, string>): string;
56
+ /**
57
+ * Recursively substitute {{cs.KEY}} tokens in all string fields of an object.
58
+ * This is preferred over substituting into JSON.stringify() output because it
59
+ * avoids producing invalid JSON when parameter values contain JSON-special
60
+ * characters (quotes, backslashes, newlines, etc.).
61
+ *
62
+ * Non-string values (numbers, booleans, arrays, nested objects) are traversed
63
+ * but their non-string leaves are returned unchanged.
64
+ */
65
+ export declare function substituteParametersInObject(obj: unknown, resolved: Record<string, string>): unknown;
66
+ /**
67
+ * Validate that no unresolved {{cs.*}} tokens remain in `content`.
68
+ * Returns a list of unresolved token strings (empty = valid).
69
+ */
70
+ export declare function findUnresolvedTokens(content: string): string[];
71
+ /**
72
+ * Redact sensitive parameter values for display (e.g. in plan output).
73
+ * Non-sensitive values are returned as-is.
74
+ */
75
+ export declare function redactSensitiveValues(values: Record<string, string>, declared: Record<string, DeclaredParameter>): Record<string, string>;
76
+ //# sourceMappingURL=parameters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parameters.d.ts","sourceRoot":"","sources":["../../../tool/utils/parameters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAKtF;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,0BAA0B;IACjE,SAAS,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAC/B,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,6EAA6E;IAC7E,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,yFAAyF;IACzF,eAAe,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACpC,UAAU,EAAE,MAAM,EAAE,EACpB,cAAc,EAAE,eAAe,EAAE,GAClC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAgBnC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,EAC3C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,kBAAkB,CAmBpB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAI9F;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CACxC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,OAAO,CAeT;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ9D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAC5C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMxB"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Overlay parameter resolution and {{cs.PARAM_NAME}} substitution engine.
3
+ *
4
+ * Syntax: {{cs.PARAM_NAME}} — chosen because it:
5
+ * - does NOT collide with Docker Compose ${VAR} / ${VAR:-default}
6
+ * - does NOT collide with shell $VAR / ${VAR} / ${VAR:-x}
7
+ * - does NOT collide with VS Code ${localWorkspaceFolder} / ${env:VAR}
8
+ * - does NOT collide with GitHub Actions ${{ github.* }}
9
+ * - is consistent with the existing preset {{parameters.<key>.id}} convention
10
+ *
11
+ * This module deliberately has NO parser, NO AST, NO conditionals.
12
+ * If string.replace() can't do it, it doesn't belong here.
13
+ */
14
+ /** Regex matching ALL {{cs.KEY}} tokens (used for substitution and validation). */
15
+ const CS_PARAM_REGEX = /\{\{cs\.([A-Z0-9_]+)\}\}/g;
16
+ /**
17
+ * Collect all parameter declarations from the selected overlay set.
18
+ * Returns a map of parameter name → declaration enriched with the declaring overlay.
19
+ *
20
+ * When two overlays declare the same parameter name, the first declaration wins
21
+ * (overlays are processed in composition order).
22
+ */
23
+ export function collectOverlayParameters(overlayIds, allOverlayDefs) {
24
+ const declared = {};
25
+ const overlayById = new Map(allOverlayDefs.map((o) => [o.id, o]));
26
+ for (const id of overlayIds) {
27
+ const overlay = overlayById.get(id);
28
+ if (!overlay?.parameters)
29
+ continue;
30
+ for (const [key, def] of Object.entries(overlay.parameters)) {
31
+ if (!(key in declared)) {
32
+ declared[key] = { ...def, overlayId: id };
33
+ }
34
+ }
35
+ }
36
+ return declared;
37
+ }
38
+ /**
39
+ * Resolve parameter values by applying the resolution order:
40
+ * 1. Supplied values (from project file or CLI — highest priority)
41
+ * 2. Overlay defaults (lowest priority)
42
+ *
43
+ * Returns resolved values, any missing-required errors, and unknown-supplied warnings.
44
+ */
45
+ export function resolveParameters(declared, supplied) {
46
+ const values = {};
47
+ const missingRequired = [];
48
+ // Resolve each declared parameter
49
+ for (const [key, def] of Object.entries(declared)) {
50
+ if (key in supplied) {
51
+ values[key] = supplied[key];
52
+ }
53
+ else if (def.default !== undefined) {
54
+ values[key] = def.default;
55
+ }
56
+ else {
57
+ missingRequired.push(key);
58
+ }
59
+ }
60
+ // Identify unknown supplied parameters (not declared by any overlay)
61
+ const unknownSupplied = Object.keys(supplied).filter((key) => !(key in declared));
62
+ return { values, missingRequired, unknownSupplied };
63
+ }
64
+ /**
65
+ * Replace all {{cs.KEY}} tokens in `content` with the corresponding resolved value.
66
+ * Tokens for keys not present in `resolved` are left intact (to be caught by validation).
67
+ *
68
+ * Docker Compose ${VAR}, shell $VAR, VS Code ${env:VAR}, and GitHub Actions ${{ }}
69
+ * expressions are NEVER touched — only the {{cs.KEY}} pattern is matched.
70
+ */
71
+ export function substituteParameters(content, resolved) {
72
+ return content.replace(CS_PARAM_REGEX, (match, key) => {
73
+ return key in resolved ? resolved[key] : match;
74
+ });
75
+ }
76
+ /**
77
+ * Recursively substitute {{cs.KEY}} tokens in all string fields of an object.
78
+ * This is preferred over substituting into JSON.stringify() output because it
79
+ * avoids producing invalid JSON when parameter values contain JSON-special
80
+ * characters (quotes, backslashes, newlines, etc.).
81
+ *
82
+ * Non-string values (numbers, booleans, arrays, nested objects) are traversed
83
+ * but their non-string leaves are returned unchanged.
84
+ */
85
+ export function substituteParametersInObject(obj, resolved) {
86
+ if (typeof obj === 'string') {
87
+ return substituteParameters(obj, resolved);
88
+ }
89
+ if (Array.isArray(obj)) {
90
+ return obj.map((item) => substituteParametersInObject(item, resolved));
91
+ }
92
+ if (obj !== null && typeof obj === 'object') {
93
+ const result = {};
94
+ for (const [k, v] of Object.entries(obj)) {
95
+ result[k] = substituteParametersInObject(v, resolved);
96
+ }
97
+ return result;
98
+ }
99
+ return obj;
100
+ }
101
+ /**
102
+ * Validate that no unresolved {{cs.*}} tokens remain in `content`.
103
+ * Returns a list of unresolved token strings (empty = valid).
104
+ */
105
+ export function findUnresolvedTokens(content) {
106
+ const found = [];
107
+ let match;
108
+ const regex = new RegExp(CS_PARAM_REGEX.source, 'g');
109
+ while ((match = regex.exec(content)) !== null) {
110
+ found.push(match[0]);
111
+ }
112
+ return found;
113
+ }
114
+ /**
115
+ * Redact sensitive parameter values for display (e.g. in plan output).
116
+ * Non-sensitive values are returned as-is.
117
+ */
118
+ export function redactSensitiveValues(values, declared) {
119
+ const result = {};
120
+ for (const [key, value] of Object.entries(values)) {
121
+ result[key] = declared[key]?.sensitive ? '***' : value;
122
+ }
123
+ return result;
124
+ }
125
+ //# sourceMappingURL=parameters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parameters.js","sourceRoot":"","sources":["../../../tool/utils/parameters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,mFAAmF;AACnF,MAAM,cAAc,GAAG,2BAA2B,CAAC;AAqBnD;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CACpC,UAAoB,EACpB,cAAiC;IAEjC,MAAM,QAAQ,GAAsC,EAAE,CAAC;IACvD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAElE,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,OAAO,EAAE,UAAU;YAAE,SAAS;QAEnC,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YAC1D,IAAI,CAAC,CAAC,GAAG,IAAI,QAAQ,CAAC,EAAE,CAAC;gBACrB,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;YAC9C,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC7B,QAA2C,EAC3C,QAAgC;IAEhC,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,MAAM,eAAe,GAAa,EAAE,CAAC;IAErC,kCAAkC;IAClC,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChD,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;YAClB,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;aAAM,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC;QAC9B,CAAC;aAAM,CAAC;YACJ,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;IACL,CAAC;IAED,qEAAqE;IACrE,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC;IAElF,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,eAAe,EAAE,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,QAAgC;IAClF,OAAO,OAAO,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,GAAW,EAAE,EAAE;QAC1D,OAAO,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACnD,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,4BAA4B,CACxC,GAAY,EACZ,QAAgC;IAEhC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,oBAAoB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,4BAA4B,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC1C,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAA8B,CAAC,EAAE,CAAC;YAClE,MAAM,CAAC,CAAC,CAAC,GAAG,4BAA4B,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAChD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,KAA6B,CAAC;IAClC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACrD,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACjC,MAA8B,EAC9B,QAA2C;IAE3C,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3D,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function resolveRepoPath(relativePath: string, anchor: string): string;
2
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../tool/utils/paths.ts"],"names":[],"mappings":"AAiBA,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAiB5E"}
@@ -0,0 +1,31 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ /**
4
+ * Resolve a repo-relative path from an anchor directory, handling both
5
+ * source (scripts/) and compiled (dist/scripts/) locations.
6
+ *
7
+ * Walks up from the anchor directory collecting candidate paths:
8
+ * anchor/relative, anchor/../relative, anchor/../../relative, ...
9
+ * Returns the first that exists, or the first candidate as a fallback.
10
+ */
11
+ // Maximum number of parent directories to walk up when searching for repo-relative paths.
12
+ // 5 levels is sufficient to cover source (<repo>/tool/questionnaire) and compiled
13
+ // (<repo>/dist/tool/questionnaire) layouts without walking too far up the filesystem.
14
+ const MAX_DIRECTORY_WALK_DEPTH = 5;
15
+ export function resolveRepoPath(relativePath, anchor) {
16
+ const candidates = [];
17
+ let currentAnchor = anchor;
18
+ // Walk up from the anchor directory, collecting candidate paths like:
19
+ // anchor/relative, anchor/../relative, anchor/../../relative, ...
20
+ // Stop after MAX_DIRECTORY_WALK_DEPTH levels or when reaching the filesystem root.
21
+ for (let i = 0; i < MAX_DIRECTORY_WALK_DEPTH; i++) {
22
+ candidates.push(path.join(currentAnchor, relativePath));
23
+ const parent = path.dirname(currentAnchor);
24
+ if (parent === currentAnchor) {
25
+ break;
26
+ }
27
+ currentAnchor = parent;
28
+ }
29
+ return candidates.find((c) => fs.existsSync(c)) ?? candidates[0];
30
+ }
31
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../tool/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;;;;GAOG;AAEH,0FAA0F;AAC1F,kFAAkF;AAClF,sFAAsF;AACtF,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAEnC,MAAM,UAAU,eAAe,CAAC,YAAoB,EAAE,MAAc;IAChE,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,IAAI,aAAa,GAAG,MAAM,CAAC;IAE3B,sEAAsE;IACtE,kEAAkE;IAClE,mFAAmF;IACnF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,wBAAwB,EAAE,CAAC,EAAE,EAAE,CAAC;QAChD,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC;QACxD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QAC3C,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;YAC3B,MAAM;QACV,CAAC;QACD,aAAa,GAAG,MAAM,CAAC;IAC3B,CAAC;IAED,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC"}
@@ -1,16 +1,24 @@
1
1
  # Deployment Target Support
2
2
 
3
- Container Superposition validates overlay compatibility with different deployment environments using the `--target` flag.
3
+ Container Superposition generates workspace artifacts and setup guidance tailored to the
4
+ selected deployment environment using the `--target` flag.
4
5
 
5
6
  ## Quick Start
6
7
 
7
8
  ```bash
8
- # Specify deployment target
9
+ # Default local development (no additional files)
10
+ npx container-superposition init --stack compose --language nodejs
11
+
12
+ # GitHub Codespaces (adds hostRequirements + CODESPACES.md)
9
13
  npx container-superposition init --target codespaces
14
+
15
+ # Gitpod (adds .gitpod.yml + GITPOD.md)
10
16
  npx container-superposition init --target gitpod
11
- npx container-superposition init --target local # default
12
17
 
13
- # With specific configuration
18
+ # DevPod (adds devpod.yaml + DEVPOD.md)
19
+ npx container-superposition init --target devpod
20
+
21
+ # Full example for Codespaces
14
22
  npx container-superposition init \
15
23
  --stack compose \
16
24
  --language nodejs \
@@ -21,24 +29,52 @@ npx container-superposition init \
21
29
 
22
30
  ## Supported Deployment Targets
23
31
 
24
- | Target | Description | Docker Support | Auto Port Forward |
25
- | -------------- | --------------------------------- | -------------- | ----------------- |
26
- | **local** | Local machine with Docker Desktop | ✅ Host Docker | No |
27
- | **codespaces** | GitHub Codespaces (cloud IDE) | ⚠️ DinD only | Yes |
28
- | **gitpod** | Gitpod workspaces | ⚠️ DinD only | Yes |
29
- | **devpod** | DevPod client-only environments | ✅ Host Docker | No |
32
+ | Target | Description | Docker Support | Auto Port Forward | Extra Artifacts |
33
+ | -------------- | --------------------------------- | -------------- | ----------------- | -------------------------------------------------------- |
34
+ | **local** | Local machine with Docker Desktop | ✅ Host Docker | No | None (current behavior) |
35
+ | **codespaces** | GitHub Codespaces (cloud IDE) | ⚠️ DinD only | Yes | `hostRequirements` in devcontainer.json; `CODESPACES.md` |
36
+ | **gitpod** | Gitpod workspaces | ⚠️ DinD only | Yes | `.gitpod.yml` at project root; `GITPOD.md` |
37
+ | **devpod** | DevPod client-only environments | ✅ Host Docker | No | `devpod.yaml` at project root; `DEVPOD.md` |
30
38
 
31
- ## How It Works
39
+ ## Target-Specific Artifact Inventory
32
40
 
33
- ### Interactive Mode
41
+ ### `--target codespaces`
42
+
43
+ | File | Location | Purpose |
44
+ | ------------------- | ---------------- | --------------------------------------------------------------------------------- |
45
+ | `devcontainer.json` | `.devcontainer/` | Extended with `hostRequirements` (cpu/memory/storage recommendation) |
46
+ | `CODESPACES.md` | `.devcontainer/` | How to open the repo in a Codespace; machine-type guidance; port forwarding notes |
47
+
48
+ **Machine size recommendation** is determined automatically from the overlays selected:
49
+
50
+ - 0–1 service overlays → 2-core (default)
51
+ - 2–3 service overlays → 4-core recommended
52
+ - 4+ service overlays → 8-core recommended
53
+
54
+ ### `--target gitpod`
55
+
56
+ | File | Location | Purpose |
57
+ | ------------- | ---------------- | ----------------------------------------------------------------------------------- |
58
+ | `.gitpod.yml` | **Project root** | Gitpod workspace config; references devcontainer; declares tasks and port exposures |
59
+ | `GITPOD.md` | `.devcontainer/` | One-click open badge; Gitpod-specific usage notes |
34
60
 
35
- If you select incompatible overlays (e.g., `docker-sock` for Codespaces), the tool will:
61
+ ### `--target devpod`
36
62
 
37
- - Show which overlays won't work in your target environment
38
- - Suggest compatible alternatives
39
- - Let you choose your deployment target with informed guidance
63
+ | File | Location | Purpose |
64
+ | ------------- | ---------------- | ---------------------------------------------------- |
65
+ | `devpod.yaml` | **Project root** | DevPod workspace descriptor; references devcontainer |
66
+ | `DEVPOD.md` | `.devcontainer/` | `devpod up` instructions; provider examples |
40
67
 
41
- **Example interaction:**
68
+ ### `--target local` / no `--target`
69
+
70
+ No additional files are written. Output is identical to the current local-first workflow.
71
+
72
+ ## How It Works
73
+
74
+ ### Interactive Mode
75
+
76
+ If you select overlays that may not work in a cloud environment (e.g. `docker-sock`), the tool
77
+ prompts you to choose a target so it can warn about incompatibilities:
42
78
 
43
79
  ```
44
80
  ⚠️ Deployment Target Compatibility Check:
@@ -56,76 +92,70 @@ Which environment are you targeting?
56
92
  📦 DevPod
57
93
  ```
58
94
 
59
- ### CLI Mode
60
-
61
- The target validates your selection and generates the configuration:
62
-
63
- - Incompatibilities are allowed (you know what you're doing)
64
- - Generated documentation notes any compatibility issues
95
+ After you confirm the target, the generator produces the appropriate workspace artifacts
96
+ alongside the standard `.devcontainer/` output.
65
97
 
66
- ## Example Configurations
98
+ ### CLI Mode
67
99
 
68
- ### Optimized for GitHub Codespaces
100
+ Pass `--target` directly the target is applied without interactive prompts:
69
101
 
70
102
  ```bash
71
103
  npx container-superposition init \
72
104
  --stack compose \
73
105
  --language nodejs \
74
- --database postgres \
75
106
  --dev-tools docker-in-docker \
76
- --target codespaces
107
+ --target gitpod
77
108
  ```
78
109
 
79
- ### Local Development
110
+ ### Regeneration
111
+
112
+ The selected target is saved in `superposition.json` as the `target` field. Regeneration
113
+ re-produces the correct artifacts automatically without re-prompting:
80
114
 
81
115
  ```bash
82
- npx container-superposition init \
83
- --stack compose \
84
- --language nodejs \
85
- --database postgres \
86
- --dev-tools docker-sock \
87
- --target local
116
+ # superposition.json contains "target": "gitpod"
117
+ npx container-superposition regen # → .gitpod.yml and GITPOD.md reproduced
118
+ ```
119
+
120
+ To switch target on regeneration, pass `--target` explicitly:
121
+
122
+ ```bash
123
+ npx container-superposition regen --target codespaces
88
124
  ```
89
125
 
126
+ Stale artifacts from the previous target (e.g. `.gitpod.yml`) are **removed automatically**
127
+ before the new target's artifacts are written.
128
+
90
129
  ## Key Compatibility Rules
91
130
 
92
131
  - ⚠️ **docker-sock** requires host Docker → Use in `local` or `devpod` only
93
132
  - ✅ **docker-in-docker** works everywhere → Recommended for `codespaces` and `gitpod`
94
- - 🔄 Cloud targets auto-forward ports → No manual forwarding needed
133
+ - 🔄 Cloud targets auto-forward ports → No manual port forwarding needed
95
134
 
96
135
  ## Environment Differences
97
136
 
98
- Different environments have different capabilities:
99
-
100
- ### Codespaces/Gitpod
137
+ ### Codespaces / Gitpod
101
138
 
102
- - **No access to host Docker daemon** - Must use docker-in-docker
103
- - **Auto-forward ports** - Ports are automatically accessible
104
- - **Cloud-based** - Resources may be constrained
139
+ - **No access to host Docker daemon** Must use docker-in-docker
140
+ - **Auto-forward ports** Ports declared in devcontainer.json are automatically accessible
141
+ - **Cloud-based** Resources may be constrained; machine size matters
105
142
 
106
143
  ### Local
107
144
 
108
- - **Full access to host Docker** - Can use docker-sock for better performance
109
- - **Faster builds** - Shared cache with host
110
- - **Manual port forwarding** - Need to expose ports explicitly
145
+ - **Full access to host Docker** Can use docker-sock for better performance
146
+ - **Faster builds** Shared cache with host
147
+ - **Manual port forwarding** Expose ports explicitly when needed
111
148
 
112
149
  ### DevPod
113
150
 
114
- - **Client-managed** - Runs on your infrastructure
115
- - **Can access host Docker** - Depending on setup
116
- - **Flexible** - Configure based on your needs
117
-
118
- ## Why Deployment Targets?
119
-
120
- The target system ensures you get warnings about incompatibilities before deploying. This prevents:
121
-
122
- - Wasted time debugging environment-specific issues
123
- - Confusion about why overlays don't work in cloud IDEs
124
- - Having to manually research compatibility
151
+ - **Client-managed** Runs on your infrastructure (local Docker, cloud VM, etc.)
152
+ - **Can access host Docker** Depending on provider configuration
153
+ - **Flexible** Provider chosen at `devpod up` time, not at generation time
125
154
 
126
155
  ## Configuration
127
156
 
128
- Target configurations are stored in `overlays/.registry/deployment-targets.yml`. To add a new target, simply add an entry to this file:
157
+ Deployment target configurations (compatibility rules, port forwarding defaults) are stored in
158
+ `overlays/.registry/deployment-targets.yml`. To add a new target entry:
129
159
 
130
160
  ```yaml
131
161
  - id: new-target
@@ -144,6 +174,8 @@ Target configurations are stored in `overlays/.registry/deployment-targets.yml`.
144
174
  supportsPrivileged: true
145
175
  ```
146
176
 
177
+ Target-specific file generation rules are implemented in `tool/schema/target-rules.ts`.
178
+
147
179
  ## See Also
148
180
 
149
181
  - [Discovery Commands](discovery-commands.md) - Explore overlays before generating
package/docs/examples.md CHANGED
@@ -19,9 +19,11 @@ language:
19
19
  database:
20
20
  - postgres
21
21
  outputPath: ./.devcontainer
22
+ env:
23
+ APP_ENV: development
22
24
  customizations:
23
- environment:
24
- APP_ENV: development
25
+ envTemplate:
26
+ POSTGRES_PASSWORD: postgres
25
27
  devcontainerPatch:
26
28
  features:
27
29
  ghcr.io/devcontainers-extra/features/apt-get-packages:1:
@@ -171,24 +173,25 @@ All examples produce:
171
173
 
172
174
  ## Customization After Generation
173
175
 
174
- The output is plain JSON - edit directly:
176
+ Prefer editing `superposition.yml` and regenerating:
175
177
 
176
- ```jsonc
177
- // .devcontainer/devcontainer.json
178
- {
179
- "name": "My Custom Name", // Change this
180
- "features": {
181
- // Add/remove features
182
- "ghcr.io/devcontainers/features/go:1": {},
183
- },
184
- "forwardPorts": [3000, 8080], // Adjust ports
185
- "remoteEnv": {
186
- "MY_VAR": "value", // Add environment variables
187
- },
188
- }
178
+ ```yaml
179
+ # superposition.yml
180
+ containerName: My Custom Name
181
+ env:
182
+ MY_VAR: value
183
+ customizations:
184
+ devcontainerPatch:
185
+ forwardPorts:
186
+ - 3000
187
+ - 8080
189
188
  ```
190
189
 
191
- The tool gets you started—you customize from there.
190
+ Then regenerate:
191
+
192
+ ```bash
193
+ npx container-superposition regen
194
+ ```
192
195
 
193
196
  ## Help and Documentation
194
197
 
@@ -11,6 +11,9 @@ your-project/
11
11
  │ ├── docker-compose.yml # Services (compose stack only)
12
12
  │ ├── .env.example # Environment variable templates
13
13
  │ ├── ports.json # Port documentation and connection strings
14
+ │ ├── CODESPACES.md # Codespaces setup guidance (--target codespaces only)
15
+ │ ├── GITPOD.md # Gitpod setup guidance (--target gitpod only)
16
+ │ ├── DEVPOD.md # DevPod setup guidance (--target devpod only)
14
17
  │ ├── scripts/ # Setup and verification scripts
15
18
  │ │ ├── post-create.sh # Runs once when container is created
16
19
  │ │ └── post-start.sh # Runs every time container starts
@@ -18,6 +21,8 @@ your-project/
18
21
  │ ├── devcontainer.patch.json
19
22
  │ └── docker-compose.patch.yml
20
23
  ├── superposition.json # Manifest file (enables regeneration)
24
+ ├── .gitpod.yml # Gitpod workspace config (--target gitpod only)
25
+ ├── devpod.yaml # DevPod workspace descriptor (--target devpod only)
21
26
  └── .devcontainer.backup-*/ # Automatic backups (gitignored)
22
27
  ```
23
28
 
@@ -86,7 +86,7 @@ container-superposition init --editor vscode
86
86
  # None - CLI-only, no editor customizations
87
87
  container-superposition init --editor none
88
88
 
89
- # JetBrains - Skip VS Code customizations (reserved for future JetBrains support)
89
+ # JetBrains - Generate .idea/ project settings and run configurations
90
90
  container-superposition init --editor jetbrains
91
91
  ```
92
92
 
@@ -126,15 +126,61 @@ Removes all editor customizations. Useful for:
126
126
 
127
127
  #### jetbrains
128
128
 
129
- Removes VS Code customizations. Reserved for future JetBrains-specific settings (Gateway, Fleet, etc.).
129
+ Generates JetBrains IDE project artifacts and sets the appropriate IDE backend in
130
+ `devcontainer.json`. VS Code customizations are removed.
130
131
 
131
132
  ```json
132
133
  {
133
- // No vscode customizations
134
- // Future: JetBrains-specific settings could be added here
134
+ "customizations": {
135
+ "jetbrains": {
136
+ "backend": "WebStorm"
137
+ }
138
+ }
135
139
  }
136
140
  ```
137
141
 
142
+ The `backend` value is automatically selected based on the primary language overlay:
143
+
144
+ | Language overlay | JetBrains IDE |
145
+ | ------------------------- | --------------------------------- |
146
+ | `nodejs` / `bun` | `WebStorm` |
147
+ | `python` / `mkdocs` | `PyCharm` |
148
+ | `go` | `GoLand` |
149
+ | `dotnet` | `Rider` |
150
+ | `java` | `IntelliJIdea` |
151
+ | `rust` | `RustRover` |
152
+ | none / multiple / unknown | `IntelliJIdea` (generic fallback) |
153
+
154
+ ##### Generated artifacts
155
+
156
+ In addition to the `devcontainer.json` update, enabling JetBrains support generates the
157
+ following files in the **project root** (the parent of `.devcontainer/`):
158
+
159
+ ```
160
+ .idea/
161
+ .gitignore # shared workspace entries committed to VCS
162
+ runConfigurations/
163
+ npm_dev.xml # Node.js — npm run dev
164
+ python_main.xml # Python — python main.py
165
+ go_run.xml # Go — go run ./...
166
+ dotnet_run.xml # .NET — dotnet run
167
+ java_run.xml # Java — Application run
168
+ rust_run.xml # Rust — cargo run
169
+ ```
170
+
171
+ Only run configuration files matching the selected language overlays are created.
172
+
173
+ ##### Existing `.idea/` directory
174
+
175
+ If `.idea/` already exists (e.g., from a previous generation or user customisation),
176
+ existing files are **never overwritten**. Only files that are missing are written.
177
+
178
+ ##### Regenerating with a different editor profile
179
+
180
+ If you later regenerate with `--editor vscode` after a JetBrains generation, the `.idea/`
181
+ directory is **not removed** — it may contain user-created configurations. Switch back
182
+ to `--editor jetbrains` if you want to add new run configurations.
183
+
138
184
  ### When to Use Editor Profiles
139
185
 
140
186
  **Terminal Workflows:**
@@ -187,7 +233,7 @@ container-superposition regen --minimal
187
233
 
188
234
  # Step 3: Or regenerate for a different editor
189
235
  container-superposition regen --editor jetbrains
190
- # Removes VS Code customizations
236
+ # Adds JetBrains customizations and generates .idea/ artifacts
191
237
 
192
238
  # Step 4: Or both together
193
239
  container-superposition regen --minimal --editor none
@@ -237,6 +283,20 @@ container-superposition init \
237
283
 
238
284
  **Result:** Lean Codespaces environment with essential tools and VS Code extensions.
239
285
 
286
+ ### JetBrains IDE Setup
287
+
288
+ ```bash
289
+ container-superposition init \
290
+ --editor jetbrains \
291
+ --stack compose \
292
+ --language nodejs \
293
+ --database postgres
294
+ ```
295
+
296
+ **Result:** Node.js + PostgreSQL workspace with `.idea/` project settings, a `WebStorm`
297
+ backend in `devcontainer.json`, and an `npm run dev` run configuration ready to use. No
298
+ VS Code extensions included.
299
+
240
300
  ## Manifest Support
241
301
 
242
302
  Both settings are stored in `superposition.json`: