container-superposition 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) 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/doctor.d.ts.map +1 -1
  13. package/dist/tool/commands/doctor.js +141 -6
  14. package/dist/tool/commands/doctor.js.map +1 -1
  15. package/dist/tool/commands/explain.d.ts.map +1 -1
  16. package/dist/tool/commands/explain.js +9 -0
  17. package/dist/tool/commands/explain.js.map +1 -1
  18. package/dist/tool/commands/migrate.d.ts +7 -0
  19. package/dist/tool/commands/migrate.d.ts.map +1 -0
  20. package/dist/tool/commands/migrate.js +52 -0
  21. package/dist/tool/commands/migrate.js.map +1 -0
  22. package/dist/tool/questionnaire/answers.d.ts +16 -0
  23. package/dist/tool/questionnaire/answers.d.ts.map +1 -0
  24. package/dist/tool/questionnaire/answers.js +102 -0
  25. package/dist/tool/questionnaire/answers.js.map +1 -0
  26. package/dist/tool/questionnaire/composer.d.ts +3 -3
  27. package/dist/tool/questionnaire/composer.d.ts.map +1 -1
  28. package/dist/tool/questionnaire/composer.js +691 -27
  29. package/dist/tool/questionnaire/composer.js.map +1 -1
  30. package/dist/tool/questionnaire/presets.d.ts +60 -0
  31. package/dist/tool/questionnaire/presets.d.ts.map +1 -0
  32. package/dist/tool/questionnaire/presets.js +164 -0
  33. package/dist/tool/questionnaire/presets.js.map +1 -0
  34. package/dist/tool/questionnaire/questionnaire.d.ts +10 -0
  35. package/dist/tool/questionnaire/questionnaire.d.ts.map +1 -0
  36. package/dist/tool/questionnaire/questionnaire.js +580 -0
  37. package/dist/tool/questionnaire/questionnaire.js.map +1 -0
  38. package/dist/tool/schema/manifest-migrations.d.ts +5 -0
  39. package/dist/tool/schema/manifest-migrations.d.ts.map +1 -1
  40. package/dist/tool/schema/manifest-migrations.js +45 -0
  41. package/dist/tool/schema/manifest-migrations.js.map +1 -1
  42. package/dist/tool/schema/overlay-loader.d.ts.map +1 -1
  43. package/dist/tool/schema/overlay-loader.js +24 -0
  44. package/dist/tool/schema/overlay-loader.js.map +1 -1
  45. package/dist/tool/schema/project-config.d.ts +13 -1
  46. package/dist/tool/schema/project-config.d.ts.map +1 -1
  47. package/dist/tool/schema/project-config.js +183 -9
  48. package/dist/tool/schema/project-config.js.map +1 -1
  49. package/dist/tool/schema/target-rules.d.ts +78 -0
  50. package/dist/tool/schema/target-rules.d.ts.map +1 -0
  51. package/dist/tool/schema/target-rules.js +367 -0
  52. package/dist/tool/schema/target-rules.js.map +1 -0
  53. package/dist/tool/schema/types.d.ts +38 -1
  54. package/dist/tool/schema/types.d.ts.map +1 -1
  55. package/dist/tool/utils/parameters.d.ts +76 -0
  56. package/dist/tool/utils/parameters.d.ts.map +1 -0
  57. package/dist/tool/utils/parameters.js +125 -0
  58. package/dist/tool/utils/parameters.js.map +1 -0
  59. package/dist/tool/utils/paths.d.ts +2 -0
  60. package/dist/tool/utils/paths.d.ts.map +1 -0
  61. package/dist/tool/utils/paths.js +31 -0
  62. package/dist/tool/utils/paths.js.map +1 -0
  63. package/docs/deployment-targets.md +88 -56
  64. package/docs/examples.md +20 -17
  65. package/docs/filesystem-contract.md +5 -0
  66. package/docs/minimal-and-editor.md +65 -5
  67. package/docs/overlay-imports.md +92 -14
  68. package/docs/overlays.md +113 -28
  69. package/docs/specs/007-init-project-file/spec.md +66 -0
  70. package/docs/specs/007-target-aware-generation/spec.md +126 -0
  71. package/docs/specs/008-project-file-canonical/spec.md +83 -0
  72. package/docs/specs/009-project-env/spec.md +147 -0
  73. package/docs/specs/010-compose-env-materialization/spec.md +130 -0
  74. package/docs/specs/011-overlay-parameters/spec.md +235 -0
  75. package/overlays/.shared/README.md +27 -2
  76. package/overlays/.shared/compose/nvidia-gpu-devcontainer.yml +22 -0
  77. package/overlays/comfyui/.env.example +34 -0
  78. package/overlays/comfyui/README.md +342 -0
  79. package/overlays/comfyui/devcontainer.patch.json +15 -0
  80. package/overlays/comfyui/docker-compose.yml +39 -0
  81. package/overlays/comfyui/overlay.yml +20 -0
  82. package/overlays/comfyui/setup.sh +36 -0
  83. package/overlays/comfyui/verify.sh +103 -0
  84. package/overlays/k3d/README.md +201 -0
  85. package/overlays/k3d/devcontainer.patch.json +9 -0
  86. package/overlays/k3d/overlay.yml +19 -0
  87. package/overlays/k3d/setup.sh +34 -0
  88. package/overlays/k3d/verify.sh +38 -0
  89. package/overlays/ollama/.env.example +14 -0
  90. package/overlays/ollama/README.md +325 -0
  91. package/overlays/ollama/devcontainer.patch.json +14 -0
  92. package/overlays/ollama/docker-compose.yml +24 -0
  93. package/overlays/ollama/overlay.yml +22 -0
  94. package/overlays/ollama/setup.sh +106 -0
  95. package/overlays/ollama/verify.sh +99 -0
  96. package/overlays/open-webui/.env.example +5 -0
  97. package/overlays/open-webui/README.md +162 -0
  98. package/overlays/open-webui/devcontainer.patch.json +14 -0
  99. package/overlays/open-webui/docker-compose.yml +23 -0
  100. package/overlays/open-webui/overlay.yml +38 -0
  101. package/overlays/pgvector/.env.example +6 -0
  102. package/overlays/pgvector/README.md +215 -0
  103. package/overlays/pgvector/devcontainer.patch.json +23 -0
  104. package/overlays/pgvector/docker-compose.yml +32 -0
  105. package/overlays/pgvector/overlay.yml +44 -0
  106. package/overlays/postgres/.env.example +5 -5
  107. package/overlays/postgres/devcontainer.patch.json +4 -4
  108. package/overlays/postgres/docker-compose.yml +10 -6
  109. package/overlays/postgres/overlay.yml +19 -1
  110. package/overlays/qdrant/.env.example +4 -0
  111. package/overlays/qdrant/README.md +216 -0
  112. package/overlays/qdrant/devcontainer.patch.json +20 -0
  113. package/overlays/qdrant/docker-compose.yml +25 -0
  114. package/overlays/qdrant/overlay.yml +40 -0
  115. package/overlays/skaffold/README.md +256 -0
  116. package/overlays/skaffold/devcontainer.patch.json +9 -0
  117. package/overlays/skaffold/overlay.yml +20 -0
  118. package/overlays/skaffold/setup.sh +33 -0
  119. package/overlays/skaffold/verify.sh +24 -0
  120. package/package.json +3 -2
  121. package/tool/schema/config.schema.json +31 -1
  122. package/tool/schema/overlay-manifest.schema.json +33 -0
@@ -0,0 +1,318 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import chalk from 'chalk';
4
+ import boxen from 'boxen';
5
+ import ora from 'ora';
6
+ import { composeDevContainer, generateManifestOnly } from '../questionnaire/composer.js';
7
+ import { loadManifest } from '../schema/manifest-migrations.js';
8
+ import { printSummary } from '../utils/summary.js';
9
+ import { buildAnswersFromManifest, buildAnswersFromProjectConfig, buildProjectConfigSelectionFromAnswers, findManifestFile, findDefaultRegenManifest, findProjectConfig, loadProjectConfig, writeProjectConfig, writeProjectConfigCustomizations, } from '../schema/project-config.js';
10
+ import { isInsideGitRepo, createBackup, ensureBackupPatternsInGitignore } from '../utils/backup.js';
11
+ import { buildAnswersFromCliArgs, mergeAnswers } from '../questionnaire/answers.js';
12
+ import { applyPresetSelections } from '../questionnaire/presets.js';
13
+ import { runQuestionnaire, loadOverlaysConfigWrapper, PRESETS_DIR, } from '../questionnaire/questionnaire.js';
14
+ import { parseCliArgs } from './args.js';
15
+ export async function main() {
16
+ try {
17
+ const cliArgs = await parseCliArgs();
18
+ const initialCwd = process.cwd();
19
+ if (cliArgs?.projectRoot) {
20
+ const resolvedProjectRoot = path.resolve(initialCwd, cliArgs.projectRoot);
21
+ if (!fs.existsSync(resolvedProjectRoot)) {
22
+ console.error(chalk.red(`✗ Project root not found: ${resolvedProjectRoot}`));
23
+ process.exit(1);
24
+ }
25
+ if (!fs.statSync(resolvedProjectRoot).isDirectory()) {
26
+ console.error(chalk.red(`✗ Project root is not a directory: ${resolvedProjectRoot}`));
27
+ process.exit(1);
28
+ }
29
+ process.chdir(resolvedProjectRoot);
30
+ }
31
+ let projectFileOutputPath;
32
+ let existingProjectFileDetected = false;
33
+ if (cliArgs?.commandName === 'init' || cliArgs?.commandName === undefined) {
34
+ const discoveredProjectFiles = findProjectConfig(process.cwd());
35
+ if (discoveredProjectFiles.length > 1) {
36
+ console.error(chalk.red('✗ Found both .superposition.yml and superposition.yml in the repository root. Keep only one.'));
37
+ console.error(chalk.gray(' Recommended: keep .superposition.yml (dotfile) to keep the root tidy; delete superposition.yml.'));
38
+ process.exit(1);
39
+ }
40
+ if (discoveredProjectFiles.length === 1) {
41
+ existingProjectFileDetected = true;
42
+ }
43
+ projectFileOutputPath =
44
+ discoveredProjectFiles[0]?.path ?? path.join(process.cwd(), '.superposition.yml');
45
+ }
46
+ let projectConfig = undefined;
47
+ let projectConfigAnswers;
48
+ if (!cliArgs?.manifestPath) {
49
+ const overlaysConfigForProject = loadOverlaysConfigWrapper();
50
+ projectConfig = loadProjectConfig(overlaysConfigForProject, process.cwd()) ?? undefined;
51
+ if (projectConfig) {
52
+ projectConfigAnswers = await applyPresetSelections(buildAnswersFromProjectConfig(projectConfig.selection, overlaysConfigForProject), overlaysConfigForProject, PRESETS_DIR);
53
+ }
54
+ }
55
+ let manifest;
56
+ let manifestDir;
57
+ let backupDir;
58
+ let useManifestOnly = false;
59
+ let useProjectOnly = false;
60
+ if (cliArgs?.commandName === 'regen' && !cliArgs.manifestPath && !cliArgs.fromProject) {
61
+ if (projectConfigAnswers) {
62
+ useProjectOnly = true;
63
+ }
64
+ else {
65
+ const discoveredManifestPath = findDefaultRegenManifest(cliArgs?.config?.outputPath || './.devcontainer');
66
+ if (discoveredManifestPath) {
67
+ console.error(chalk.red('✗ Error: No project file found'));
68
+ console.error(chalk.cyan(' Found superposition.json but no superposition.yml project file.'));
69
+ console.error(chalk.gray(' Run `cs migrate` to create a project file from your existing manifest, then run `regen` again.'));
70
+ }
71
+ else {
72
+ console.error(chalk.red('✗ Error: No project file found'));
73
+ console.error(chalk.gray(' Create .superposition.yml or superposition.yml in your repository root.'));
74
+ console.error(chalk.dim(' Or run `cs init` to create a new configuration interactively.'));
75
+ }
76
+ process.exit(1);
77
+ }
78
+ }
79
+ if (cliArgs?.commandName === 'regen' && cliArgs?.manifestPath) {
80
+ console.warn(chalk.yellow('⚠️ --from-manifest is deprecated for regen. Run `cs migrate` to create a project file, then use `regen` without this flag.'));
81
+ }
82
+ if (cliArgs?.manifestPath) {
83
+ const manifestPath = findManifestFile(cliArgs.manifestPath);
84
+ if (!manifestPath) {
85
+ console.error(chalk.red('✗ Could not find manifest file'));
86
+ console.error(chalk.red(` Searched for: ${cliArgs.manifestPath}`));
87
+ process.exit(1);
88
+ }
89
+ manifestDir = path.dirname(manifestPath);
90
+ const loadedManifest = loadManifest(manifestPath);
91
+ if (!loadedManifest) {
92
+ process.exit(1);
93
+ }
94
+ manifest = loadedManifest;
95
+ if (cliArgs.backupDir) {
96
+ backupDir = cliArgs.backupDir;
97
+ }
98
+ if (cliArgs.noInteractive) {
99
+ useManifestOnly = true;
100
+ }
101
+ }
102
+ if (cliArgs?.fromProject) {
103
+ if (!projectConfigAnswers || !projectConfig) {
104
+ console.error(chalk.red('✗ Could not find project file'));
105
+ console.error(chalk.red(' Searched for: .superposition.yml, superposition.yml'));
106
+ process.exit(1);
107
+ }
108
+ useProjectOnly = cliArgs.noInteractive || cliArgs.commandName === 'regen';
109
+ }
110
+ if (cliArgs?.noInteractive && !cliArgs?.manifestPath && !projectConfigAnswers) {
111
+ console.error(chalk.red('✗ Error: --no-interactive requires persisted input'));
112
+ console.error(chalk.dim(' Use --from-project or run from a repository with .superposition.yml or superposition.yml'));
113
+ process.exit(1);
114
+ }
115
+ const resolvedOutputPath = cliArgs?.config?.outputPath ||
116
+ projectConfigAnswers?.outputPath ||
117
+ manifestDir ||
118
+ './.devcontainer';
119
+ const backupCheckPath = path.resolve(resolvedOutputPath);
120
+ const inGitRepo = isInsideGitRepo(backupCheckPath);
121
+ let shouldBackup;
122
+ if (cliArgs?.backupOverride === true) {
123
+ shouldBackup = true;
124
+ }
125
+ else if (cliArgs?.backupOverride === false) {
126
+ shouldBackup = false;
127
+ }
128
+ else {
129
+ shouldBackup = !inGitRepo;
130
+ if (!shouldBackup) {
131
+ console.log(chalk.dim('ℹ Skipping backup — git repo detected (use --backup to force one)\n'));
132
+ }
133
+ }
134
+ const isReplayMode = cliArgs?.commandName === 'regen' || useManifestOnly || useProjectOnly;
135
+ let actualBackupPath;
136
+ if (shouldBackup && isReplayMode) {
137
+ const outputPath = resolvedOutputPath;
138
+ const backupPath = await createBackup(outputPath, backupDir);
139
+ if (backupPath) {
140
+ actualBackupPath = backupPath;
141
+ console.log(chalk.green(`✓ Backup created: ${backupPath}\n`));
142
+ ensureBackupPatternsInGitignore(outputPath);
143
+ }
144
+ }
145
+ const mainOverlaysConfig = loadOverlaysConfigWrapper();
146
+ let answers;
147
+ const hasCliOverrides = cliArgs &&
148
+ Object.keys(cliArgs.config).some((key) => key !== 'outputPath' &&
149
+ key !== 'preset' &&
150
+ key !== 'presetChoices' &&
151
+ !(key === 'target' && cliArgs.config.target === 'local') &&
152
+ !(key === 'editor' && cliArgs.config.editor === 'vscode') &&
153
+ cliArgs.config[key] !== undefined);
154
+ const hasAnyCliConfig = cliArgs &&
155
+ Object.entries(cliArgs.config).some(([key, value]) => value !== undefined &&
156
+ !(key === 'target' && value === 'local') &&
157
+ !(key === 'editor' && value === 'vscode'));
158
+ if (useManifestOnly && manifest && !hasCliOverrides) {
159
+ const manifestAnswers = buildAnswersFromManifest(manifest, mainOverlaysConfig, manifestDir);
160
+ answers = mergeAnswers(manifestAnswers);
161
+ console.log('\n' +
162
+ boxen(chalk.bold.cyan('Regenerating from Manifest (No Interactive)\n\n') +
163
+ chalk.white('Configuration:\n') +
164
+ chalk.gray(` Template: ${manifest.baseTemplate}\n`) +
165
+ chalk.gray(` Base Image: ${manifest.baseImage}\n`) +
166
+ (manifest.containerName
167
+ ? chalk.gray(` Container: ${manifest.containerName}\n`)
168
+ : '') +
169
+ chalk.gray(` Overlays: ${manifest.overlays.join(', ')}\n`) +
170
+ (manifest.preset ? chalk.gray(` Preset: ${manifest.preset}\n`) : '') +
171
+ (manifest.portOffset
172
+ ? chalk.gray(` Port offset: ${manifest.portOffset}\n`)
173
+ : '') +
174
+ chalk.gray(` Output: ${answers.outputPath}`), { padding: 1, borderColor: 'cyan', borderStyle: 'round', margin: 1 }));
175
+ }
176
+ else if (useProjectOnly && projectConfigAnswers && !hasCliOverrides) {
177
+ const projectFileName = projectConfig?.file.fileName ?? '.superposition.yml';
178
+ answers = mergeAnswers(projectConfigAnswers, {
179
+ outputPath: cliArgs?.config?.outputPath ||
180
+ projectConfigAnswers.outputPath ||
181
+ './.devcontainer',
182
+ minimal: cliArgs?.config?.minimal,
183
+ editor: cliArgs?.config?.editor,
184
+ });
185
+ console.log('\n' +
186
+ boxen(chalk.bold.cyan('Regenerating from Project File (No Interactive)\n\n') +
187
+ chalk.white('Configuration:\n') +
188
+ chalk.gray(` Project file: ${projectFileName}\n`) +
189
+ chalk.gray(` Output: ${answers.outputPath}`), {
190
+ padding: 1,
191
+ borderColor: 'cyan',
192
+ borderStyle: 'round',
193
+ margin: 1,
194
+ }));
195
+ }
196
+ else if ((cliArgs && (cliArgs.config.stack || hasCliOverrides)) ||
197
+ (projectConfigAnswers && (cliArgs?.noInteractive || hasAnyCliConfig))) {
198
+ const cliAnswers = buildAnswersFromCliArgs(cliArgs.config);
199
+ const manifestAnswers = manifest
200
+ ? buildAnswersFromManifest(manifest, mainOverlaysConfig, manifestDir)
201
+ : undefined;
202
+ answers = mergeAnswers(projectConfigAnswers, manifestAnswers, cliAnswers, {
203
+ outputPath: cliAnswers.outputPath || projectConfigAnswers?.outputPath || './.devcontainer',
204
+ });
205
+ const modeLabel = useManifestOnly && hasCliOverrides
206
+ ? 'Regenerating from Manifest with Overrides'
207
+ : useProjectOnly && projectConfigAnswers
208
+ ? 'Regenerating from Project File with Overrides'
209
+ : projectConfigAnswers && !manifest
210
+ ? 'Running from Project Config'
211
+ : 'Running in CLI mode';
212
+ console.log('\n' +
213
+ boxen(chalk.bold(modeLabel), {
214
+ padding: 0.5,
215
+ borderColor: 'blue',
216
+ borderStyle: 'round',
217
+ }));
218
+ if ((useManifestOnly || useProjectOnly) && hasCliOverrides) {
219
+ const overrides = [];
220
+ if (cliAnswers.minimal)
221
+ overrides.push('minimal mode');
222
+ if (cliAnswers.editor)
223
+ overrides.push(`editor: ${cliAnswers.editor}`);
224
+ if (overrides.length > 0) {
225
+ console.log(chalk.dim(` Overrides: ${overrides.join(', ')}`));
226
+ }
227
+ }
228
+ }
229
+ else {
230
+ const interactiveAnswers = await runQuestionnaire(manifest, manifestDir, cliArgs?.config.preset || projectConfigAnswers?.preset, cliArgs?.config.presetChoices || projectConfigAnswers?.presetChoices, projectConfigAnswers);
231
+ answers = mergeAnswers(projectConfigAnswers, interactiveAnswers);
232
+ }
233
+ if (!manifest && projectConfig?.selection.customizations) {
234
+ const materializedOutputPath = path.resolve(answers.outputPath);
235
+ if (!fs.existsSync(materializedOutputPath)) {
236
+ fs.mkdirSync(materializedOutputPath, { recursive: true });
237
+ }
238
+ writeProjectConfigCustomizations(materializedOutputPath, projectConfig.selection.customizations);
239
+ }
240
+ const summaryLines = [
241
+ chalk.bold.white('Configuration Summary\n'),
242
+ chalk.cyan('Base: ') + chalk.white(answers.stack),
243
+ ];
244
+ if (answers.language && answers.language.length > 0) {
245
+ summaryLines.push(chalk.cyan('Languages: ') + chalk.white(answers.language.join(', ')));
246
+ }
247
+ if (answers.database && answers.database.length > 0) {
248
+ summaryLines.push(chalk.cyan('Database: ') + chalk.white(answers.database.join(', ')));
249
+ }
250
+ summaryLines.push(chalk.cyan('Playwright: ') + chalk.white(answers.playwright ? 'Yes' : 'No'));
251
+ if (answers.observability && answers.observability.length > 0) {
252
+ summaryLines.push(chalk.cyan('Observability: ') + chalk.white(answers.observability.join(', ')));
253
+ }
254
+ if (answers.cloudTools && answers.cloudTools.length > 0) {
255
+ summaryLines.push(chalk.cyan('Cloud tools: ') + chalk.white(answers.cloudTools.join(', ')));
256
+ }
257
+ if (projectConfig?.file && !manifest) {
258
+ summaryLines.push(chalk.cyan('Project config: ') + chalk.white(projectConfig.file.fileName));
259
+ }
260
+ summaryLines.push(chalk.cyan('Output: ') + chalk.white(answers.outputPath));
261
+ console.log('\n' +
262
+ boxen(summaryLines.join('\n'), {
263
+ padding: 1,
264
+ borderColor: 'green',
265
+ borderStyle: 'round',
266
+ margin: { top: 0, bottom: 1 },
267
+ }));
268
+ if (existingProjectFileDetected && projectFileOutputPath) {
269
+ const relPath = path.relative(process.cwd(), projectFileOutputPath);
270
+ console.log(chalk.yellow(`⚠ Existing project file will be updated: ${relPath}\n Run \`cs regen\` instead to replay the existing configuration without changes.`));
271
+ }
272
+ if (projectFileOutputPath) {
273
+ try {
274
+ const projectSelection = buildProjectConfigSelectionFromAnswers(answers);
275
+ writeProjectConfig(projectFileOutputPath, projectSelection);
276
+ console.log(chalk.green(`✓ Project config written: ${path.relative(process.cwd(), projectFileOutputPath)}`));
277
+ }
278
+ catch (projectFileError) {
279
+ console.error(chalk.yellow(`⚠ Failed to write project config: ${projectFileError instanceof Error ? projectFileError.message : String(projectFileError)}`));
280
+ }
281
+ }
282
+ const isManifestOnly = cliArgs?.writeManifestOnly === true || cliArgs?.noScaffold === true;
283
+ const spinner = ora({
284
+ text: isManifestOnly
285
+ ? chalk.cyan('Generating manifest file...')
286
+ : chalk.cyan('Generating devcontainer configuration...'),
287
+ color: 'cyan',
288
+ }).start();
289
+ try {
290
+ let summary;
291
+ if (isManifestOnly) {
292
+ summary = await generateManifestOnly(answers, undefined, {
293
+ isRegen: isReplayMode,
294
+ });
295
+ spinner.succeed(chalk.green('Manifest created successfully!'));
296
+ }
297
+ else {
298
+ summary = await composeDevContainer(answers, undefined, { isRegen: isReplayMode });
299
+ spinner.succeed(chalk.green('DevContainer created successfully!'));
300
+ }
301
+ if (actualBackupPath) {
302
+ summary.backupPath = actualBackupPath;
303
+ }
304
+ printSummary(summary);
305
+ }
306
+ catch (error) {
307
+ spinner.fail(chalk.red(isManifestOnly ? 'Failed to create manifest' : 'Failed to create devcontainer'));
308
+ throw error;
309
+ }
310
+ }
311
+ catch (error) {
312
+ console.error('\n' +
313
+ boxen(chalk.bold.red('Error\n\n') +
314
+ chalk.white(error instanceof Error ? error.message : String(error)), { padding: 1, borderColor: 'red', borderStyle: 'round' }));
315
+ process.exit(1);
316
+ }
317
+ }
318
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../tool/cli/run.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../tool/commands/doctor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,OAAO,KAAK,EACR,cAAc,EAmBjB,MAAM,oBAAoB,CAAC;AAc5B,UAAU,aAAa;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAwxDD;;GAEG;AACH,wBAAsB,aAAa,CAC/B,cAAc,EAAE,cAAc,EAC9B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,aAAa,GACvB,OAAO,CAAC,IAAI,CAAC,CA0Jf"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../tool/commands/doctor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,OAAO,KAAK,EACR,cAAc,EAmBjB,MAAM,oBAAoB,CAAC;AAe5B,UAAU,aAAa;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAq7DD;;GAEG;AACH,wBAAsB,aAAa,CAC/B,cAAc,EAAE,cAAc,EAC9B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,aAAa,GACvB,OAAO,CAAC,IAAI,CAAC,CA6Jf"}
@@ -12,6 +12,7 @@ import { detectManifestVersion, isVersionSupported, needsMigration, migrateManif
12
12
  import { MERGE_STRATEGY } from '../utils/merge.js';
13
13
  import { extractPorts } from '../utils/port-utils.js';
14
14
  import { composeDevContainer } from '../questionnaire/composer.js';
15
+ import { mergeAnswers } from '../questionnaire/answers.js';
15
16
  import { loadProjectConfig } from '../schema/project-config.js';
16
17
  // ─── Remediation registry ─────────────────────────────────────────────────
17
18
  const REMEDIATION_REGISTRY = new Map([
@@ -418,6 +419,52 @@ function validateOverlayManifest(overlayDir, overlayId) {
418
419
  };
419
420
  }
420
421
  }
422
+ // Validate compose_imports if present
423
+ if (manifest.compose_imports && manifest.compose_imports.length > 0) {
424
+ const overlaysDir = path.dirname(overlayDir);
425
+ const sharedBase = path.resolve(overlaysDir, '.shared');
426
+ const missingImports = [];
427
+ const invalidImports = [];
428
+ const traversalImports = [];
429
+ for (const importPath of manifest.compose_imports) {
430
+ if (!importPath.startsWith('.shared/')) {
431
+ traversalImports.push(`${importPath} (must begin with '.shared/')`);
432
+ continue;
433
+ }
434
+ const resolved = path.resolve(overlaysDir, importPath);
435
+ if (!resolved.startsWith(sharedBase + path.sep) && resolved !== sharedBase) {
436
+ traversalImports.push(`${importPath} (resolves outside '.shared/' directory)`);
437
+ continue;
438
+ }
439
+ const fullImportPath = path.join(overlaysDir, importPath);
440
+ if (!fs.existsSync(fullImportPath)) {
441
+ missingImports.push(importPath);
442
+ continue;
443
+ }
444
+ const ext = path.extname(importPath).toLowerCase();
445
+ if (!['.yaml', '.yml'].includes(ext)) {
446
+ invalidImports.push(`${importPath} (must be .yml or .yaml for compose_imports)`);
447
+ }
448
+ }
449
+ if (traversalImports.length > 0 || missingImports.length > 0 || invalidImports.length > 0) {
450
+ const details = [];
451
+ if (traversalImports.length > 0) {
452
+ details.push(`Path traversal rejected: ${traversalImports.join(', ')}`);
453
+ }
454
+ if (missingImports.length > 0) {
455
+ details.push(`Missing compose_imports: ${missingImports.join(', ')}`);
456
+ }
457
+ if (invalidImports.length > 0) {
458
+ details.push(`Invalid compose_imports: ${invalidImports.join(', ')}`);
459
+ }
460
+ return {
461
+ name: `Overlay: ${overlayId}`,
462
+ status: 'warn',
463
+ message: 'compose_import validation issues',
464
+ details,
465
+ };
466
+ }
467
+ }
421
468
  return {
422
469
  name: `Overlay: ${overlayId}`,
423
470
  status: 'pass',
@@ -817,15 +864,84 @@ function checkMergeStrategy(outputPath) {
817
864
  return results;
818
865
  }
819
866
  /**
820
- * Generate doctor report
867
+ * Check for drift between the project config file and the last generated manifest.
868
+ * Reports a warning when the overlay lists differ so users know to run `regen`.
821
869
  */
822
- function generateReport(environmentChecks, overlayChecks, manifestChecks, mergeChecks, portChecks) {
870
+ function checkProjectFileDrift(overlaysConfig, workingDir, manifestPath) {
871
+ // Load project config — skip silently if not present
872
+ let projectConfig;
873
+ try {
874
+ projectConfig = loadProjectConfig(overlaysConfig, workingDir);
875
+ }
876
+ catch {
877
+ return [];
878
+ }
879
+ if (!projectConfig) {
880
+ return [];
881
+ }
882
+ // Load manifest — if not present while the project file exists, report it informatively
883
+ if (!fs.existsSync(manifestPath)) {
884
+ return [
885
+ {
886
+ name: 'Project file drift',
887
+ status: 'warn',
888
+ message: 'Project file found but no generated manifest — run `cs regen` to generate',
889
+ fixEligibility: 'not-applicable',
890
+ },
891
+ ];
892
+ }
893
+ let manifest;
894
+ try {
895
+ const raw = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
896
+ manifest = needsMigration(raw) ? migrateManifest(raw) : raw;
897
+ }
898
+ catch {
899
+ return [];
900
+ }
901
+ // Compare overlay sets (order-independent).
902
+ // Exclude auto-resolved dependencies from the manifest side — the project file only
903
+ // stores user-selected overlays; auto-resolved ones are re-calculated at generation time.
904
+ const autoResolvedAdded = new Set(manifest.autoResolved?.added ?? []);
905
+ const projectOverlays = new Set(projectConfig.selection.overlays ?? []);
906
+ const manifestBaseOverlays = new Set((manifest.overlays ?? []).filter((o) => !autoResolvedAdded.has(o)));
907
+ const inProjectNotManifest = [...projectOverlays].filter((o) => !manifestBaseOverlays.has(o));
908
+ const inManifestNotProject = [...manifestBaseOverlays].filter((o) => !projectOverlays.has(o));
909
+ if (inProjectNotManifest.length === 0 && inManifestNotProject.length === 0) {
910
+ return [
911
+ {
912
+ name: 'Project file drift',
913
+ status: 'pass',
914
+ message: 'Project file and generated manifest are consistent',
915
+ fixEligibility: 'not-applicable',
916
+ },
917
+ ];
918
+ }
919
+ const details = [];
920
+ if (inProjectNotManifest.length > 0) {
921
+ details.push(`In project file but not in manifest: ${inProjectNotManifest.join(', ')}`);
922
+ }
923
+ if (inManifestNotProject.length > 0) {
924
+ details.push(`In manifest but not in project file: ${inManifestNotProject.join(', ')}`);
925
+ }
926
+ details.push('Run "cs regen" to regenerate with the current project file configuration');
927
+ return [
928
+ {
929
+ name: 'Project file drift',
930
+ status: 'warn',
931
+ message: 'Project file and generated manifest have diverged',
932
+ details,
933
+ fixEligibility: 'manual-only',
934
+ },
935
+ ];
936
+ }
937
+ function generateReport(environmentChecks, overlayChecks, manifestChecks, mergeChecks, portChecks, driftChecks = []) {
823
938
  const allChecks = [
824
939
  ...environmentChecks,
825
940
  ...overlayChecks,
826
941
  ...manifestChecks,
827
942
  ...mergeChecks,
828
943
  ...portChecks,
944
+ ...driftChecks,
829
945
  ];
830
946
  const passed = allChecks.filter((c) => c.status === 'pass').length;
831
947
  const warnings = allChecks.filter((c) => c.status === 'warn').length;
@@ -837,6 +953,7 @@ function generateReport(environmentChecks, overlayChecks, manifestChecks, mergeC
837
953
  manifest: manifestChecks,
838
954
  merge: mergeChecks,
839
955
  ports: portChecks,
956
+ drift: driftChecks,
840
957
  summary: {
841
958
  passed,
842
959
  warnings,
@@ -913,6 +1030,20 @@ function formatAsText(report) {
913
1030
  lines.push(formatCheckResult(check));
914
1031
  }
915
1032
  }
1033
+ // Drift section
1034
+ if (report.drift.length > 0) {
1035
+ const failedDrift = report.drift.filter((c) => c.status !== 'pass');
1036
+ if (failedDrift.length > 0) {
1037
+ lines.push(chalk.bold('\nProject File:'));
1038
+ for (const check of failedDrift) {
1039
+ lines.push(formatCheckResult(check));
1040
+ }
1041
+ }
1042
+ else {
1043
+ lines.push(chalk.bold('\nProject File:'));
1044
+ lines.push(` ${chalk.green('✓')} ${chalk.white('Project file and manifest are consistent')}`);
1045
+ }
1046
+ }
916
1047
  // Summary
917
1048
  lines.push(chalk.bold('\nSummary:'));
918
1049
  lines.push(` ${chalk.green('✓')} ${report.summary.passed} passed`);
@@ -960,6 +1091,7 @@ function reportToFindings(report) {
960
1091
  ...checksToFindings(report.manifest, 'manifest', 'manifest'),
961
1092
  ...checksToFindings(report.merge, 'merge', 'devcontainer'),
962
1093
  ...checksToFindings(report.ports, 'ports', 'environment'),
1094
+ ...checksToFindings(report.drift, 'manifest', 'manifest'),
963
1095
  ];
964
1096
  }
965
1097
  /**
@@ -1202,7 +1334,7 @@ async function executeRegeneration(outputPath, overlaysConfig, overlaysDir, sile
1202
1334
  rechecked: false,
1203
1335
  };
1204
1336
  }
1205
- const answers = buildAnswersFromManifest(manifest, outputPath, overlaysConfig);
1337
+ const answers = mergeAnswers(buildAnswersFromManifest(manifest, outputPath, overlaysConfig));
1206
1338
  // Suppress console output during regeneration when in JSON mode
1207
1339
  const originalLog = console.log;
1208
1340
  if (silent) {
@@ -1439,7 +1571,7 @@ function determineExitDisposition(summary, finalFindings) {
1439
1571
  /**
1440
1572
  * Run the full fix flow: diagnose → narrate → remediate → re-check → summarise.
1441
1573
  */
1442
- async function executeFixRun(report, outputPath, overlaysConfig, overlaysDir, requestedJson, explicitManifestPath) {
1574
+ async function executeFixRun(report, outputPath, overlaysConfig, overlaysDir, requestedJson, explicitManifestPath, workingDir = process.cwd()) {
1443
1575
  const initialFindings = reportToFindings(report);
1444
1576
  // Separate automatic and manual-only fixable findings
1445
1577
  const autoFixable = initialFindings.filter((f) => f.fixEligibility === 'automatic' && f.status !== 'pass');
@@ -1500,12 +1632,14 @@ async function executeFixRun(report, outputPath, overlaysConfig, overlaysDir, re
1500
1632
  const overlayChecks = checkOverlays(overlaysDir);
1501
1633
  const finalManifestPath = explicitManifestPath ?? path.join(outputPath, 'superposition.json');
1502
1634
  const portChecks = checkPorts(overlaysConfig, finalManifestPath);
1635
+ const finalDriftChecks = checkProjectFileDrift(overlaysConfig, workingDir, finalManifestPath);
1503
1636
  const finalFindings = [
1504
1637
  ...checksToFindings(envChecks, 'environment', 'environment'),
1505
1638
  ...checksToFindings(manifestChecks, 'manifest', 'manifest'),
1506
1639
  ...checksToFindings(mergeChecks, 'merge', 'devcontainer'),
1507
1640
  ...checksToFindings(overlayChecks, 'overlay', 'full'),
1508
1641
  ...checksToFindings(portChecks, 'ports', 'environment'),
1642
+ ...checksToFindings(finalDriftChecks, 'manifest', 'manifest'),
1509
1643
  ];
1510
1644
  const summary = buildOutcomeSummary(executions);
1511
1645
  const exitDisposition = determineExitDisposition(summary, finalFindings);
@@ -1678,15 +1812,16 @@ export async function doctorCommand(overlaysConfig, overlaysDir, options) {
1678
1812
  const mergeChecks = checkMergeStrategy(outputPath);
1679
1813
  const manifestPath = explicitManifestPath ?? path.join(outputPath, 'superposition.json');
1680
1814
  const portChecks = checkPorts(overlaysConfig, manifestPath);
1815
+ const driftChecks = checkProjectFileDrift(overlaysConfig, workingDir, manifestPath);
1681
1816
  // Generate report
1682
- const report = generateReport(environmentChecks, overlayChecks, manifestChecks, mergeChecks, portChecks);
1817
+ const report = generateReport(environmentChecks, overlayChecks, manifestChecks, mergeChecks, portChecks, driftChecks);
1683
1818
  if (options.fix) {
1684
1819
  // ── Fix flow ──────────────────────────────────────────────────────────
1685
1820
  if (!options.json) {
1686
1821
  // Print diagnostic findings first (as normal)
1687
1822
  console.log(formatAsText(report));
1688
1823
  }
1689
- const fixRun = await executeFixRun(report, outputPath, overlaysConfig, overlaysDir, options.json ?? false, explicitManifestPath);
1824
+ const fixRun = await executeFixRun(report, outputPath, overlaysConfig, overlaysDir, options.json ?? false, explicitManifestPath, workingDir);
1690
1825
  if (options.json) {
1691
1826
  console.log(JSON.stringify(fixRun, null, 2));
1692
1827
  }