@tdk-landscape/tdk-cli-core 1.3.53 → 1.3.55

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 (392) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +1 -1
  3. package/cli/dist/commands/doctor.js +21 -3
  4. package/cli/dist/commands/upgrade.js +7 -7
  5. package/cli/dist/generator/extension-fetch.js +16 -9
  6. package/cli/dist/utils/spinner.js +39 -0
  7. package/cli/package.json +1 -2
  8. package/package.json +16 -2
  9. package/.claude/skills/layer-autoresearch/SKILL.md +0 -48
  10. package/.claude/skills/tdk-troubleshoot/SKILL.md +0 -222
  11. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -40
  12. package/.github/ISSUE_TEMPLATE/config.yml +0 -11
  13. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -18
  14. package/.github/ISSUE_TEMPLATE/premium_license.yml +0 -43
  15. package/.github/dependabot.yml +0 -33
  16. package/.github/pull_request_template.md +0 -5
  17. package/.github/workflows/ci.yml +0 -200
  18. package/.github/workflows/release-binaries.yml +0 -139
  19. package/.github/zizmor.yml +0 -9
  20. package/.pre-commit-config.yaml +0 -57
  21. package/CODE_OF_CONDUCT.md +0 -9
  22. package/CONTRIBUTING.md +0 -42
  23. package/Makefile +0 -92
  24. package/SECURITY.md +0 -17
  25. package/benchmarks/results/container-scale-2026-09-25T20-54-49-736Z.json +0 -45
  26. package/benchmarks/results/container-scale-2026-09-25T21-01-20-540Z.json +0 -150
  27. package/benchmarks/results/container-scale-2026-09-25T21-15-01-441Z.json +0 -73
  28. package/benchmarks/results/container-scale-2026-09-25T22-09-01-630Z.json +0 -77
  29. package/benchmarks/results/container-scale-2026-09-25T22-18-28-371Z.json +0 -202
  30. package/cli/AGENTS.md +0 -390
  31. package/cli/DESIGN.md +0 -735
  32. package/cli/README.md +0 -292
  33. package/cli/biome.json +0 -40
  34. package/cli/dependency-graph.svg +0 -1135
  35. package/cli/dist/cli.d.ts +0 -3
  36. package/cli/dist/cli.d.ts.map +0 -1
  37. package/cli/dist/cli.js.map +0 -1
  38. package/cli/dist/commands/completion.d.ts +0 -3
  39. package/cli/dist/commands/completion.d.ts.map +0 -1
  40. package/cli/dist/commands/completion.js.map +0 -1
  41. package/cli/dist/commands/config.d.ts +0 -3
  42. package/cli/dist/commands/config.d.ts.map +0 -1
  43. package/cli/dist/commands/config.js.map +0 -1
  44. package/cli/dist/commands/doctor.d.ts +0 -19
  45. package/cli/dist/commands/doctor.d.ts.map +0 -1
  46. package/cli/dist/commands/doctor.js.map +0 -1
  47. package/cli/dist/commands/down.d.ts +0 -3
  48. package/cli/dist/commands/down.d.ts.map +0 -1
  49. package/cli/dist/commands/down.js.map +0 -1
  50. package/cli/dist/commands/help.d.ts +0 -2
  51. package/cli/dist/commands/help.d.ts.map +0 -1
  52. package/cli/dist/commands/help.js.map +0 -1
  53. package/cli/dist/commands/networks.d.ts +0 -3
  54. package/cli/dist/commands/networks.d.ts.map +0 -1
  55. package/cli/dist/commands/networks.js.map +0 -1
  56. package/cli/dist/commands/project.d.ts +0 -9
  57. package/cli/dist/commands/project.d.ts.map +0 -1
  58. package/cli/dist/commands/project.js.map +0 -1
  59. package/cli/dist/commands/projects.d.ts +0 -3
  60. package/cli/dist/commands/projects.d.ts.map +0 -1
  61. package/cli/dist/commands/projects.js.map +0 -1
  62. package/cli/dist/commands/resource.d.ts +0 -69
  63. package/cli/dist/commands/resource.d.ts.map +0 -1
  64. package/cli/dist/commands/resource.js.map +0 -1
  65. package/cli/dist/commands/resources.d.ts +0 -3
  66. package/cli/dist/commands/resources.d.ts.map +0 -1
  67. package/cli/dist/commands/resources.js.map +0 -1
  68. package/cli/dist/commands/stack.d.ts +0 -3
  69. package/cli/dist/commands/stack.d.ts.map +0 -1
  70. package/cli/dist/commands/stack.js.map +0 -1
  71. package/cli/dist/commands/stacks.d.ts +0 -3
  72. package/cli/dist/commands/stacks.d.ts.map +0 -1
  73. package/cli/dist/commands/stacks.js.map +0 -1
  74. package/cli/dist/commands/status.d.ts +0 -3
  75. package/cli/dist/commands/status.d.ts.map +0 -1
  76. package/cli/dist/commands/status.js.map +0 -1
  77. package/cli/dist/commands/ui.d.ts +0 -3
  78. package/cli/dist/commands/ui.d.ts.map +0 -1
  79. package/cli/dist/commands/ui.js.map +0 -1
  80. package/cli/dist/commands/up.d.ts +0 -3
  81. package/cli/dist/commands/up.d.ts.map +0 -1
  82. package/cli/dist/commands/up.js.map +0 -1
  83. package/cli/dist/commands/upgrade.d.ts +0 -14
  84. package/cli/dist/commands/upgrade.d.ts.map +0 -1
  85. package/cli/dist/commands/upgrade.js.map +0 -1
  86. package/cli/dist/commands/version.d.ts +0 -3
  87. package/cli/dist/commands/version.d.ts.map +0 -1
  88. package/cli/dist/commands/version.js.map +0 -1
  89. package/cli/dist/components/Accessible.d.ts +0 -8
  90. package/cli/dist/components/Accessible.d.ts.map +0 -1
  91. package/cli/dist/components/Accessible.js.map +0 -1
  92. package/cli/dist/components/BaseTooltip.d.ts +0 -4
  93. package/cli/dist/components/BaseTooltip.d.ts.map +0 -1
  94. package/cli/dist/components/BaseTooltip.js.map +0 -1
  95. package/cli/dist/components/DetailPanel.d.ts +0 -4
  96. package/cli/dist/components/DetailPanel.d.ts.map +0 -1
  97. package/cli/dist/components/DetailPanel.js.map +0 -1
  98. package/cli/dist/components/FileTree.d.ts +0 -4
  99. package/cli/dist/components/FileTree.d.ts.map +0 -1
  100. package/cli/dist/components/FileTree.js.map +0 -1
  101. package/cli/dist/components/ResourceSelectInput.d.ts +0 -4
  102. package/cli/dist/components/ResourceSelectInput.d.ts.map +0 -1
  103. package/cli/dist/components/ResourceSelectInput.js.map +0 -1
  104. package/cli/dist/components/ResourceTable.d.ts +0 -4
  105. package/cli/dist/components/ResourceTable.d.ts.map +0 -1
  106. package/cli/dist/components/ResourceTable.js.map +0 -1
  107. package/cli/dist/components/TabBar.d.ts +0 -4
  108. package/cli/dist/components/TabBar.d.ts.map +0 -1
  109. package/cli/dist/components/TabBar.js.map +0 -1
  110. package/cli/dist/components/Tooltip.d.ts +0 -12
  111. package/cli/dist/components/Tooltip.d.ts.map +0 -1
  112. package/cli/dist/components/Tooltip.js.map +0 -1
  113. package/cli/dist/components/index.d.ts +0 -8
  114. package/cli/dist/components/index.d.ts.map +0 -1
  115. package/cli/dist/components/index.js.map +0 -1
  116. package/cli/dist/config/platform-standards.d.ts +0 -159
  117. package/cli/dist/config/platform-standards.d.ts.map +0 -1
  118. package/cli/dist/config/platform-standards.js.map +0 -1
  119. package/cli/dist/generator/extension-fetch.d.ts +0 -25
  120. package/cli/dist/generator/extension-fetch.d.ts.map +0 -1
  121. package/cli/dist/generator/extension-fetch.js.map +0 -1
  122. package/cli/dist/generator/template-engine.d.ts +0 -62
  123. package/cli/dist/generator/template-engine.d.ts.map +0 -1
  124. package/cli/dist/generator/template-engine.js.map +0 -1
  125. package/cli/dist/index.d.ts +0 -11
  126. package/cli/dist/index.d.ts.map +0 -1
  127. package/cli/dist/index.js.map +0 -1
  128. package/cli/dist/types/index.d.ts +0 -257
  129. package/cli/dist/types/index.d.ts.map +0 -1
  130. package/cli/dist/types/index.js.map +0 -1
  131. package/cli/dist/utils/cache.d.ts +0 -19
  132. package/cli/dist/utils/cache.d.ts.map +0 -1
  133. package/cli/dist/utils/cache.js.map +0 -1
  134. package/cli/dist/utils/command-helpers.d.ts +0 -17
  135. package/cli/dist/utils/command-helpers.d.ts.map +0 -1
  136. package/cli/dist/utils/command-helpers.js.map +0 -1
  137. package/cli/dist/utils/constants.d.ts +0 -53
  138. package/cli/dist/utils/constants.d.ts.map +0 -1
  139. package/cli/dist/utils/constants.js.map +0 -1
  140. package/cli/dist/utils/discovery-context.d.ts +0 -4
  141. package/cli/dist/utils/discovery-context.d.ts.map +0 -1
  142. package/cli/dist/utils/discovery-context.js.map +0 -1
  143. package/cli/dist/utils/docker.d.ts +0 -4
  144. package/cli/dist/utils/docker.d.ts.map +0 -1
  145. package/cli/dist/utils/docker.js.map +0 -1
  146. package/cli/dist/utils/doctor-runtime.d.ts +0 -81
  147. package/cli/dist/utils/doctor-runtime.d.ts.map +0 -1
  148. package/cli/dist/utils/doctor-runtime.js.map +0 -1
  149. package/cli/dist/utils/env-validator.d.ts +0 -15
  150. package/cli/dist/utils/env-validator.d.ts.map +0 -1
  151. package/cli/dist/utils/env-validator.js.map +0 -1
  152. package/cli/dist/utils/errors.d.ts +0 -31
  153. package/cli/dist/utils/errors.d.ts.map +0 -1
  154. package/cli/dist/utils/errors.js.map +0 -1
  155. package/cli/dist/utils/file-helpers.d.ts +0 -14
  156. package/cli/dist/utils/file-helpers.d.ts.map +0 -1
  157. package/cli/dist/utils/file-helpers.js.map +0 -1
  158. package/cli/dist/utils/formatting.d.ts +0 -30
  159. package/cli/dist/utils/formatting.d.ts.map +0 -1
  160. package/cli/dist/utils/formatting.js.map +0 -1
  161. package/cli/dist/utils/paths.d.ts +0 -3
  162. package/cli/dist/utils/paths.d.ts.map +0 -1
  163. package/cli/dist/utils/paths.js.map +0 -1
  164. package/cli/dist/utils/port-assignment.d.ts +0 -6
  165. package/cli/dist/utils/port-assignment.d.ts.map +0 -1
  166. package/cli/dist/utils/port-assignment.js.map +0 -1
  167. package/cli/dist/utils/project-features.d.ts +0 -23
  168. package/cli/dist/utils/project-features.d.ts.map +0 -1
  169. package/cli/dist/utils/project-features.js.map +0 -1
  170. package/cli/dist/utils/project-templates.d.ts +0 -7
  171. package/cli/dist/utils/project-templates.d.ts.map +0 -1
  172. package/cli/dist/utils/project-templates.js.map +0 -1
  173. package/cli/dist/utils/prompt.d.ts +0 -28
  174. package/cli/dist/utils/prompt.d.ts.map +0 -1
  175. package/cli/dist/utils/prompt.js.map +0 -1
  176. package/cli/dist/utils/resource-features.d.ts +0 -29
  177. package/cli/dist/utils/resource-features.d.ts.map +0 -1
  178. package/cli/dist/utils/resource-features.js.map +0 -1
  179. package/cli/dist/utils/service-urls.d.ts +0 -30
  180. package/cli/dist/utils/service-urls.d.ts.map +0 -1
  181. package/cli/dist/utils/service-urls.js.map +0 -1
  182. package/cli/dist/utils/services.d.ts +0 -18
  183. package/cli/dist/utils/services.d.ts.map +0 -1
  184. package/cli/dist/utils/services.js.map +0 -1
  185. package/cli/dist/utils/stack-features.d.ts +0 -22
  186. package/cli/dist/utils/stack-features.d.ts.map +0 -1
  187. package/cli/dist/utils/stack-features.js.map +0 -1
  188. package/cli/dist/utils/tar.d.ts +0 -7
  189. package/cli/dist/utils/tar.d.ts.map +0 -1
  190. package/cli/dist/utils/tar.js.map +0 -1
  191. package/cli/dist/utils/tilt.d.ts +0 -20
  192. package/cli/dist/utils/tilt.d.ts.map +0 -1
  193. package/cli/dist/utils/tilt.js.map +0 -1
  194. package/cli/dist/utils/validation.d.ts +0 -16
  195. package/cli/dist/utils/validation.d.ts.map +0 -1
  196. package/cli/dist/utils/validation.js.map +0 -1
  197. package/cli/knip.json +0 -6
  198. package/cli/pnpm-lock.yaml +0 -2305
  199. package/cli/pnpm-workspace.yaml +0 -2
  200. package/cli/src/cli.ts +0 -72
  201. package/cli/src/commands/__tests__/always-enabled-infra.test.ts +0 -109
  202. package/cli/src/commands/__tests__/config.test.ts +0 -146
  203. package/cli/src/commands/__tests__/doctor.test.ts +0 -730
  204. package/cli/src/commands/__tests__/error-handling.test.ts +0 -78
  205. package/cli/src/commands/__tests__/phases-model.test.ts +0 -161
  206. package/cli/src/commands/__tests__/project-resource-features-e2e.test.ts +0 -187
  207. package/cli/src/commands/__tests__/project.test.ts +0 -68
  208. package/cli/src/commands/__tests__/resource.test.ts +0 -226
  209. package/cli/src/commands/__tests__/saas-starter-integration.test.ts +0 -194
  210. package/cli/src/commands/__tests__/stack-features-e2e.test.ts +0 -135
  211. package/cli/src/commands/__tests__/upgrade.test.ts +0 -198
  212. package/cli/src/commands/completion.ts +0 -300
  213. package/cli/src/commands/config.ts +0 -299
  214. package/cli/src/commands/doctor.ts +0 -926
  215. package/cli/src/commands/down.ts +0 -37
  216. package/cli/src/commands/help.ts +0 -143
  217. package/cli/src/commands/networks-design.md +0 -80
  218. package/cli/src/commands/networks.ts +0 -332
  219. package/cli/src/commands/project.ts +0 -456
  220. package/cli/src/commands/projects.ts +0 -82
  221. package/cli/src/commands/resource.ts +0 -652
  222. package/cli/src/commands/resources.ts +0 -95
  223. package/cli/src/commands/stack.ts +0 -128
  224. package/cli/src/commands/stacks.ts +0 -52
  225. package/cli/src/commands/status.ts +0 -88
  226. package/cli/src/commands/ui.tsx +0 -843
  227. package/cli/src/commands/up.ts +0 -169
  228. package/cli/src/commands/upgrade.ts +0 -628
  229. package/cli/src/commands/version.ts +0 -9
  230. package/cli/src/components/Accessible.tsx +0 -21
  231. package/cli/src/components/BaseTooltip.tsx +0 -66
  232. package/cli/src/components/DetailPanel.tsx +0 -146
  233. package/cli/src/components/FileTree.tsx +0 -89
  234. package/cli/src/components/ResourceSelectInput.tsx +0 -30
  235. package/cli/src/components/ResourceTable.tsx +0 -78
  236. package/cli/src/components/TabBar.tsx +0 -53
  237. package/cli/src/components/Tooltip.tsx +0 -11
  238. package/cli/src/components/index.ts +0 -7
  239. package/cli/src/config/platform-standards.test.ts +0 -11
  240. package/cli/src/config/platform-standards.ts +0 -196
  241. package/cli/src/generator/__tests__/extension-fetch.test.ts +0 -242
  242. package/cli/src/generator/__tests__/template-engine.test.ts +0 -70
  243. package/cli/src/generator/extension-fetch.ts +0 -286
  244. package/cli/src/generator/template-engine.ts +0 -752
  245. package/cli/src/index.ts +0 -86
  246. package/cli/src/templates.d.ts +0 -4
  247. package/cli/src/types/index.ts +0 -353
  248. package/cli/src/utils/__tests__/cache.test.ts +0 -98
  249. package/cli/src/utils/__tests__/formatting.test.ts +0 -170
  250. package/cli/src/utils/__tests__/paths.test.ts +0 -180
  251. package/cli/src/utils/__tests__/port-assignment.test.ts +0 -121
  252. package/cli/src/utils/__tests__/service-urls.test.ts +0 -174
  253. package/cli/src/utils/__tests__/services.test.ts +0 -531
  254. package/cli/src/utils/__tests__/tilt.test.ts +0 -172
  255. package/cli/src/utils/__tests__/validation.test.ts +0 -148
  256. package/cli/src/utils/cache.ts +0 -76
  257. package/cli/src/utils/command-helpers.ts +0 -54
  258. package/cli/src/utils/constants.ts +0 -130
  259. package/cli/src/utils/discovery-context.ts +0 -49
  260. package/cli/src/utils/docker.ts +0 -20
  261. package/cli/src/utils/doctor-runtime.ts +0 -644
  262. package/cli/src/utils/env-validator.ts +0 -139
  263. package/cli/src/utils/errors.ts +0 -168
  264. package/cli/src/utils/file-helpers.ts +0 -62
  265. package/cli/src/utils/formatting.ts +0 -215
  266. package/cli/src/utils/paths.ts +0 -53
  267. package/cli/src/utils/port-assignment.ts +0 -106
  268. package/cli/src/utils/project-features.ts +0 -118
  269. package/cli/src/utils/project-templates.ts +0 -29
  270. package/cli/src/utils/prompt.ts +0 -128
  271. package/cli/src/utils/resource-features.ts +0 -215
  272. package/cli/src/utils/service-urls.ts +0 -124
  273. package/cli/src/utils/services.ts +0 -364
  274. package/cli/src/utils/stack-features.ts +0 -30
  275. package/cli/src/utils/tar.ts +0 -24
  276. package/cli/src/utils/tilt.ts +0 -133
  277. package/cli/src/utils/validation.ts +0 -67
  278. package/cli/tsconfig.json +0 -25
  279. package/cli/tsconfig.typecheck.json +0 -8
  280. package/docs/FEATURES.md +0 -281
  281. package/docs/demo.svg +0 -217
  282. package/engine/docs/AUTODISCOVERY_TEST.md +0 -182
  283. package/engine/docs/C4-ARCHITECTURE-operations.md +0 -396
  284. package/engine/docs/C4-ARCHITECTURE-overview.md +0 -284
  285. package/engine/docs/C4-ARCHITECTURE.md +0 -17
  286. package/engine/docs/GOLDEN_IMAGE_INTEGRATION.md +0 -349
  287. package/engine/docs/MANIFEST_DRIVEN_ARCHITECTURE.md +0 -357
  288. package/engine/docs/README.md +0 -284
  289. package/install.sh +0 -19
  290. package/knip.json +0 -10
  291. package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/.openspec.yaml +0 -2
  292. package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/design.md +0 -102
  293. package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/proposal.md +0 -31
  294. package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/specs/vscode-tdk-notifications/spec.md +0 -48
  295. package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/specs/vscode-tdk-orchestration/spec.md +0 -63
  296. package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/specs/vscode-tdk-troubleshooting/spec.md +0 -56
  297. package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/tasks.md +0 -61
  298. package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/.openspec.yaml +0 -2
  299. package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/design.md +0 -114
  300. package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/proposal.md +0 -32
  301. package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/specs/manifest-field-migration/spec.md +0 -20
  302. package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/specs/resource-terminology-standard/spec.md +0 -20
  303. package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/specs/stack-terminology-standard/spec.md +0 -20
  304. package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/tasks.md +0 -194
  305. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/.openspec.yaml +0 -2
  306. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/design.md +0 -111
  307. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/proposal.md +0 -33
  308. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/function-naming-alignment/spec.md +0 -12
  309. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/optional-parameter-patterns/spec.md +0 -18
  310. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/parameter-documentation/spec.md +0 -16
  311. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/parameter-naming-consistency/spec.md +0 -12
  312. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/parameter-ordering-standard/spec.md +0 -12
  313. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/tasks.md +0 -194
  314. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/.openspec.yaml +0 -2
  315. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/design.md +0 -84
  316. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/proposal.md +0 -31
  317. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/codebase-audit/spec.md +0 -27
  318. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/dead-code-cleanup/spec.md +0 -27
  319. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/test-gap-fill/spec.md +0 -23
  320. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/todo-resolution/spec.md +0 -27
  321. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/tasks.md +0 -39
  322. package/openspec/changes/archive/2026-06-25-landscape-consolidation/.openspec.yaml +0 -2
  323. package/openspec/changes/archive/2026-06-25-landscape-consolidation/design.md +0 -80
  324. package/openspec/changes/archive/2026-06-25-landscape-consolidation/proposal.md +0 -40
  325. package/openspec/changes/archive/2026-06-25-landscape-consolidation/spec.md +0 -52
  326. package/openspec/changes/archive/2026-06-25-landscape-consolidation/tasks.md +0 -51
  327. package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/.openspec.yaml +0 -2
  328. package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/design.md +0 -43
  329. package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/proposal.md +0 -29
  330. package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/specs/self-contained-generated-projects/spec.md +0 -67
  331. package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/tasks.md +0 -27
  332. package/openspec/changes/optimize-runtime-docker-layers/.openspec.yaml +0 -3
  333. package/openspec/changes/optimize-runtime-docker-layers/design.md +0 -81
  334. package/openspec/changes/optimize-runtime-docker-layers/proposal.md +0 -44
  335. package/openspec/changes/optimize-runtime-docker-layers/specs/runtime-container-footprint/spec.md +0 -79
  336. package/openspec/changes/optimize-runtime-docker-layers/tasks.md +0 -36
  337. package/openspec/changes/prioritized-cold-start/.openspec.yaml +0 -4
  338. package/openspec/changes/prioritized-cold-start/design.md +0 -137
  339. package/openspec/changes/prioritized-cold-start/proposal.md +0 -41
  340. package/openspec/changes/prioritized-cold-start/specs/on-demand-resource-startup/spec.md +0 -98
  341. package/openspec/changes/prioritized-cold-start/tasks.md +0 -69
  342. package/openspec/config.yaml +0 -1
  343. package/openspec/specs/manifest-field-migration/spec.md +0 -24
  344. package/openspec/specs/resource-terminology-standard/spec.md +0 -24
  345. package/openspec/specs/self-contained-generated-projects/spec.md +0 -67
  346. package/openspec/specs/stack-terminology-standard/spec.md +0 -24
  347. package/platform/services/platform/proxy/service.yaml +0 -14
  348. package/scripts/audit-codebase.sh +0 -213
  349. package/scripts/autoresearch/layer-eval.sh +0 -65
  350. package/scripts/benchmark/README.md +0 -25
  351. package/scripts/benchmark/container-scale.ts +0 -503
  352. package/scripts/benchmark/pre-release-gate.sh +0 -9
  353. package/scripts/install-git-hooks.sh +0 -14
  354. package/scripts/measure-idle-footprint.sh +0 -58
  355. package/scripts/record-demo.sh +0 -43
  356. package/scripts/release-binaries.sh +0 -97
  357. package/scripts/setup-pre-commit.sh +0 -33
  358. package/scripts/stage-npm-engine.sh +0 -36
  359. package/tests/tilt-engine/__init__.py +0 -5
  360. package/tests/tilt-engine/conftest.py +0 -182
  361. package/tests/tilt-engine/fixtures/appointment-frontend-service.json +0 -11
  362. package/tests/tilt-engine/fixtures/identity-backend-service.json +0 -12
  363. package/tests/tilt-engine/fixtures/invalid-service.json +0 -4
  364. package/tests/tilt-engine/test_agents_md_generator.py +0 -341
  365. package/tests/tilt-engine/test_agents_md_integration.py +0 -378
  366. package/tests/tilt-engine/test_cache_operations.py +0 -181
  367. package/tests/tilt-engine/test_cache_persistence.py +0 -142
  368. package/tests/tilt-engine/test_code_executor.py +0 -152
  369. package/tests/tilt-engine/test_code_viewer.py +0 -127
  370. package/tests/tilt-engine/test_compose_port_anchors.py +0 -310
  371. package/tests/tilt-engine/test_config_inspector.py +0 -162
  372. package/tests/tilt-engine/test_daemon_focus_mode.py +0 -89
  373. package/tests/tilt-engine/test_daemon_polling.py +0 -122
  374. package/tests/tilt-engine/test_daemon_registration.py +0 -115
  375. package/tests/tilt-engine/test_daemon_validation.py +0 -107
  376. package/tests/tilt-engine/test_docker_generator_bugs.py +0 -493
  377. package/tests/tilt-engine/test_docker_prune.py +0 -119
  378. package/tests/tilt-engine/test_dockerignore_path_bug.py +0 -82
  379. package/tests/tilt-engine/test_file_browser.py +0 -193
  380. package/tests/tilt-engine/test_frontend_basepath_manifest.py +0 -27
  381. package/tests/tilt-engine/test_health_dependencies.py +0 -130
  382. package/tests/tilt-engine/test_health_endpoints.py +0 -118
  383. package/tests/tilt-engine/test_health_tilt_ui.py +0 -85
  384. package/tests/tilt-engine/test_runtime_container_footprint.py +0 -162
  385. package/tests/tilt-engine/test_sablier_defer_start.py +0 -237
  386. package/tests/tilt-engine/test_safety_aliases.py +0 -84
  387. package/tests/tilt-engine/test_snapshot_diff.py +0 -136
  388. package/tests/tilt-engine/test_snapshot_persistence.py +0 -163
  389. package/tests/tilt-engine/test_snapshot_scanning.py +0 -123
  390. package/tests/tilt-engine/test_standalone_project_boot.py +0 -61
  391. package/tests/tilt-engine/test_standalone_traefik.py +0 -160
  392. package/tests/tilt-engine/test_traefik_static_wake_route.py +0 -187
@@ -1,926 +0,0 @@
1
- import { execSync } from "node:child_process";
2
- import { existsSync, readFileSync } from "node:fs";
3
- import { dirname, join, normalize } from "node:path";
4
- import chalk from "chalk";
5
- import { Command } from "commander";
6
- import type { CheckResult } from "../types/index.js";
7
- import {
8
- MASTER_CONFIG_FILES,
9
- QUICKSTART_DOCS_URL,
10
- REQUIRED_PACKAGE_SCRIPTS,
11
- } from "../utils/constants.js";
12
- import {
13
- checkIngressPorts,
14
- checkPrivateNpmRegistry,
15
- checkTiltResourceHealth,
16
- } from "../utils/doctor-runtime.js";
17
- import { validateEnvFile } from "../utils/env-validator.js";
18
- import { formatCount } from "../utils/formatting.js";
19
- import { findProjectRoot } from "../utils/paths.js";
20
- import { buildHealthTargets, pingHealthTargets } from "../utils/service-urls.js";
21
- import { discoverResourcesFromRoot } from "../utils/services.js";
22
-
23
- export {
24
- checkIngressPorts,
25
- checkPrivateNpmRegistry,
26
- checkTiltResourceHealth,
27
- summarizeTiltBuildError,
28
- } from "../utils/doctor-runtime.js";
29
-
30
- // A wedged Docker daemon makes `docker ps` block forever instead of failing,
31
- // and doctor is exactly the tool people run when their environment is broken.
32
- const EXEC_TIMEOUT_MS = 10_000;
33
-
34
- function isTimeout(err: unknown): boolean {
35
- return (err as NodeJS.ErrnoException | undefined)?.code === "ETIMEDOUT";
36
- }
37
-
38
- function createExecCheck(
39
- name: string,
40
- command: string,
41
- successMessage: string,
42
- failureMessage: string,
43
- fixInstructions: string,
44
- ): () => CheckResult {
45
- return () => {
46
- try {
47
- execSync(command, { stdio: "pipe", timeout: EXEC_TIMEOUT_MS });
48
- return {
49
- name,
50
- didPass: true,
51
- message: successMessage,
52
- };
53
- } catch {
54
- // Error details not needed - failure message tells user what to fix
55
- return {
56
- name,
57
- didPass: false,
58
- message: failureMessage,
59
- fix: fixInstructions,
60
- };
61
- }
62
- };
63
- }
64
-
65
- function checkDockerRuntime(): CheckResult {
66
- // Check for Docker
67
- try {
68
- execSync("docker ps", { stdio: "pipe", timeout: EXEC_TIMEOUT_MS });
69
- return {
70
- name: "Container Runtime",
71
- didPass: true,
72
- message: "Docker daemon is running",
73
- };
74
- } catch (err) {
75
- if (isTimeout(err)) {
76
- return {
77
- name: "Container Runtime",
78
- didPass: false,
79
- message: `Docker daemon is not responding (\`docker ps\` hung for ${EXEC_TIMEOUT_MS / 1000}s)`,
80
- fix: "Restart the runtime: quit and reopen Docker Desktop, or run `colima restart`",
81
- };
82
- }
83
- // Docker not running, check for Colima
84
- try {
85
- execSync("colima status", { stdio: "pipe", timeout: EXEC_TIMEOUT_MS });
86
- // Colima is running
87
- return {
88
- name: "Container Runtime",
89
- didPass: true,
90
- message: "Colima (Docker runtime) is running",
91
- };
92
- } catch {
93
- // Check if Colima is installed but not running
94
- try {
95
- execSync("which colima", { stdio: "pipe", timeout: EXEC_TIMEOUT_MS });
96
- return {
97
- name: "Container Runtime",
98
- didPass: false,
99
- message: "Colima is installed but not running",
100
- fix: "Start Colima: colima start",
101
- };
102
- } catch {
103
- // Check for Podman
104
- try {
105
- execSync("podman ps", { stdio: "pipe", timeout: EXEC_TIMEOUT_MS });
106
- return {
107
- name: "Container Runtime",
108
- didPass: true,
109
- message: "Podman is running",
110
- };
111
- } catch {
112
- // No container runtime found
113
- return {
114
- name: "Container Runtime",
115
- didPass: false,
116
- message: "No container runtime (Docker/Colima/Podman) is running",
117
- fix: `Start: colima start (recommended) OR open -a Docker (macOS) OR sudo systemctl start docker (Linux). Setup guide: ${QUICKSTART_DOCS_URL}`,
118
- };
119
- }
120
- }
121
- }
122
- }
123
- }
124
-
125
- const checkDockerCompose = createExecCheck(
126
- "Docker Compose",
127
- "docker compose version",
128
- "Docker Compose plugin available",
129
- "Docker Compose plugin not found",
130
- "Install Docker Compose: https://docs.docker.com/compose/install/",
131
- );
132
-
133
- // Generated healthchecks use `start_interval`, which older engines/compose reject.
134
- const MIN_DOCKER_ENGINE_VERSION = [25, 0, 0] as const;
135
- const MIN_DOCKER_COMPOSE_VERSION = [2, 20, 2] as const;
136
-
137
- function parseVersion(raw: string): number[] | null {
138
- const match = raw.trim().match(/(\d+)\.(\d+)(?:\.(\d+))?/);
139
- if (!match) {
140
- return null;
141
- }
142
- return [Number(match[1]), Number(match[2]), Number(match[3] ?? 0)];
143
- }
144
-
145
- function isAtLeast(version: number[], minimum: readonly number[]): boolean {
146
- for (const [index, required] of minimum.entries()) {
147
- const actual = version[index] ?? 0;
148
- if (actual !== required) {
149
- return actual > required;
150
- }
151
- }
152
- return true;
153
- }
154
-
155
- export function checkDockerVersions(exec: typeof execSync = execSync): CheckResult {
156
- const run = (command: string): string =>
157
- String(exec(command, { stdio: "pipe", encoding: "utf-8", timeout: EXEC_TIMEOUT_MS })).trim();
158
-
159
- let engineRaw: string;
160
- let composeRaw: string;
161
- try {
162
- engineRaw = run("docker version --format '{{.Server.Version}}'");
163
- composeRaw = run("docker compose version --short");
164
- } catch {
165
- return {
166
- name: "Docker Versions",
167
- didPass: true,
168
- isSkipped: true,
169
- message: "Could not read Docker Engine/Compose versions - skipped version check",
170
- };
171
- }
172
-
173
- const engine = parseVersion(engineRaw);
174
- const compose = parseVersion(composeRaw);
175
- if (!engine || !compose) {
176
- return {
177
- name: "Docker Versions",
178
- didPass: true,
179
- isSkipped: true,
180
- message: `Unrecognized Docker version output (engine "${engineRaw}", compose "${composeRaw}") - skipped version check`,
181
- };
182
- }
183
-
184
- const problems: string[] = [];
185
- if (!isAtLeast(engine, MIN_DOCKER_ENGINE_VERSION)) {
186
- problems.push(`Docker Engine ${engineRaw} (need 25.0+)`);
187
- }
188
- if (!isAtLeast(compose, MIN_DOCKER_COMPOSE_VERSION)) {
189
- problems.push(`Docker Compose ${composeRaw} (need 2.20.2+)`);
190
- }
191
-
192
- if (problems.length === 0) {
193
- return {
194
- name: "Docker Versions",
195
- didPass: true,
196
- message: `Docker Engine ${engineRaw} and Compose ${composeRaw} support generated healthchecks`,
197
- };
198
- }
199
-
200
- return {
201
- name: "Docker Versions",
202
- didPass: false,
203
- message: `Docker is too old for generated healthchecks (they use start_interval):\n ${problems.join("\n ")}`,
204
- fix: "Update Docker Desktop, or on Linux update docker-ce and the docker-compose-plugin package",
205
- };
206
- }
207
-
208
- const checkTilt = createExecCheck(
209
- "Tilt CLI",
210
- "tilt version",
211
- "Tilt CLI installed",
212
- "Tilt CLI not found",
213
- `Install Tilt: brew install tilt (macOS) or see https://docs.tilt.dev/install.html. Setup guide: ${QUICKSTART_DOCS_URL}`,
214
- );
215
-
216
- function checkEnvironmentVariables(): CheckResult {
217
- const projectRoot = findProjectRoot() ?? process.cwd();
218
- const validation = validateEnvFile(projectRoot);
219
-
220
- if (validation.missing.length > 0) {
221
- return {
222
- name: "Environment Variables",
223
- didPass: false,
224
- message: `Missing required env variables: ${validation.missing.join(", ")}`,
225
- fix: `Edit .env and set these values:\n ${validation.missing.map((v) => `${v}=<value>`).join("\n ")}`,
226
- };
227
- }
228
-
229
- if (validation.invalid.length > 0) {
230
- return {
231
- name: "Environment Variables",
232
- didPass: false,
233
- message: `Invalid env variables: ${validation.invalid.join(", ")}`,
234
- fix: "Edit .env and provide values for empty variables",
235
- };
236
- }
237
-
238
- return {
239
- name: "Environment Variables",
240
- didPass: true,
241
- message: "All required environment variables are set",
242
- };
243
- }
244
-
245
- function checkMasterConfigs(): CheckResult {
246
- // `tdk project` writes generated master configs to .tdk/.tdk-out/, not the
247
- // project root, so look there (and walk up to find the project root, same
248
- // as every other command that reads project state).
249
- const projectRoot = findProjectRoot() ?? process.cwd();
250
- const outDir = join(projectRoot, ".tdk", ".tdk-out");
251
-
252
- const missing = MASTER_CONFIG_FILES.filter((file) => !existsSync(join(outDir, file)));
253
-
254
- if (missing.length === 0) {
255
- return {
256
- name: "Master Configs",
257
- didPass: true,
258
- message: `${MASTER_CONFIG_FILES.join(", ")} found`,
259
- };
260
- }
261
-
262
- return {
263
- name: "Master Configs",
264
- didPass: false,
265
- message: `Master configs missing: ${missing.join(", ")}`,
266
- fix: "Run: tdk project",
267
- };
268
- }
269
-
270
- const REQUIRED_DOCKER_TEMPLATE_FILES = [
271
- "install-deps.sh",
272
- "bun-hoisted-symlink-fix.sh",
273
- "prisma-bun-client-link-fix.sh",
274
- "prisma-normalize-client.sh",
275
- "prisma-runtime-relink.sh",
276
- "infisical-entrypoint.sh",
277
- "migrate.sh",
278
- ] as const;
279
-
280
- export function checkGeneratedProjectRuntimeAssets(): CheckResult {
281
- const projectRoot = findProjectRoot() ?? process.cwd();
282
- const problems: string[] = [];
283
-
284
- if (!existsSync(join(projectRoot, "package.json"))) {
285
- problems.push("package.json (workspace root manifest)");
286
- }
287
-
288
- const templateDir = join(projectRoot, "shared-platform-engineering", "docker-templates");
289
- for (const file of REQUIRED_DOCKER_TEMPLATE_FILES) {
290
- if (!existsSync(join(templateDir, file))) {
291
- problems.push(`shared-platform-engineering/docker-templates/${file}`);
292
- }
293
- }
294
-
295
- if (problems.length === 0) {
296
- return {
297
- name: "Generated Runtime Assets",
298
- didPass: true,
299
- message: "Generated Docker runtime assets are present",
300
- };
301
- }
302
-
303
- return {
304
- name: "Generated Runtime Assets",
305
- didPass: false,
306
- message: `Generated Dockerfiles reference missing project runtime assets:\n ${problems.join("\n ")}`,
307
- fix: "Run `tdk project --yes` (or `tdk config regenerate`) with an updated TDK. `tdk up` also refreshes these assets before starting Tilt.",
308
- };
309
- }
310
-
311
- function findPrivateStarlarkLoadExports(content: string): string[] {
312
- const privateExports = new Set<string>();
313
- const loadCallPattern = /^load\s*\(([\s\S]*?)\)/gm;
314
-
315
- for (const loadMatch of content.matchAll(loadCallPattern)) {
316
- const args = loadMatch[1] ?? "";
317
- const quotedValuePattern = /["']([^"']+)["']/g;
318
- const quotedValues = Array.from(args.matchAll(quotedValuePattern), (match) => match[1]);
319
-
320
- // First quoted arg is the module path. Later quoted args are exported names
321
- // or alias targets, and Starlark refuses to export names beginning with "_".
322
- for (const value of quotedValues.slice(1)) {
323
- if (value.startsWith("_")) {
324
- privateExports.add(value);
325
- }
326
- }
327
- }
328
-
329
- return Array.from(privateExports).sort();
330
- }
331
-
332
- function resolveStarlarkLoadTarget(
333
- file: string,
334
- modulePath: string,
335
- projectRoot: string,
336
- ): string | null {
337
- if (modulePath === "ext://tdk-cli") {
338
- return join(projectRoot, ".tdk", ".tdk-out", "tdk-cli-ext", "Tiltfile");
339
- }
340
-
341
- if (modulePath.startsWith(".") || (!modulePath.includes("://") && !modulePath.startsWith("@"))) {
342
- return normalize(join(dirname(file), modulePath));
343
- }
344
-
345
- return null;
346
- }
347
-
348
- function findMissingRelativeStarlarkLoads(
349
- file: string,
350
- content: string,
351
- projectRoot: string,
352
- ): string[] {
353
- const missing: string[] = [];
354
- const loadCallPattern = /^load\s*\(([\s\S]*?)\)/gm;
355
-
356
- for (const loadMatch of content.matchAll(loadCallPattern)) {
357
- const args = loadMatch[1] ?? "";
358
- const moduleMatch = args.match(/["']([^"']+)["']/);
359
- const modulePath = moduleMatch?.[1];
360
-
361
- if (!modulePath) {
362
- continue;
363
- }
364
-
365
- const resolved = resolveStarlarkLoadTarget(file, modulePath, projectRoot);
366
- if (!resolved) {
367
- continue;
368
- }
369
-
370
- if (!existsSync(resolved)) {
371
- missing.push(`${file}: ${modulePath} -> ${resolved}`);
372
- }
373
- }
374
-
375
- return missing;
376
- }
377
-
378
- function findRelativeStarlarkLoadTargets(
379
- file: string,
380
- content: string,
381
- projectRoot: string,
382
- ): string[] {
383
- const targets: string[] = [];
384
- const loadCallPattern = /^load\s*\(([\s\S]*?)\)/gm;
385
-
386
- for (const loadMatch of content.matchAll(loadCallPattern)) {
387
- const args = loadMatch[1] ?? "";
388
- const moduleMatch = args.match(/["']([^"']+)["']/);
389
- const modulePath = moduleMatch?.[1];
390
-
391
- if (modulePath) {
392
- const target = resolveStarlarkLoadTarget(file, modulePath, projectRoot);
393
- if (target) {
394
- targets.push(target);
395
- }
396
- }
397
- }
398
-
399
- return targets;
400
- }
401
-
402
- function collectReachableStarlarkFiles(entryFile: string, projectRoot: string): string[] {
403
- const visited = new Set<string>();
404
- const pending = [entryFile];
405
-
406
- while (pending.length > 0) {
407
- const file = pending.pop();
408
- if (!file || visited.has(file) || !existsSync(file)) {
409
- continue;
410
- }
411
-
412
- visited.add(file);
413
- const content = readFileSync(file, "utf-8");
414
- for (const target of findRelativeStarlarkLoadTargets(file, content, projectRoot)) {
415
- if (!visited.has(target)) {
416
- pending.push(target);
417
- }
418
- }
419
- }
420
-
421
- return Array.from(visited).sort();
422
- }
423
-
424
- export function checkStarlarkLoadExports(): CheckResult {
425
- const projectRoot = findProjectRoot() ?? process.cwd();
426
- const entryFile = join(projectRoot, ".tdk", ".tdk-out", "Tiltfile");
427
-
428
- if (!existsSync(entryFile)) {
429
- return {
430
- name: "Starlark Load Exports",
431
- didPass: true,
432
- isSkipped: true,
433
- message: "No generated Tiltfile to check",
434
- };
435
- }
436
-
437
- const privateExportProblems: string[] = [];
438
- const missingLoadProblems: string[] = [];
439
- const reachableFiles = collectReachableStarlarkFiles(entryFile, projectRoot);
440
-
441
- for (const file of reachableFiles) {
442
- const content = readFileSync(file, "utf-8");
443
- const privateExports = findPrivateStarlarkLoadExports(content);
444
- if (privateExports.length > 0) {
445
- privateExportProblems.push(`${file}: ${privateExports.join(", ")}`);
446
- }
447
-
448
- for (const missingLoad of findMissingRelativeStarlarkLoads(file, content, projectRoot)) {
449
- missingLoadProblems.push(missingLoad);
450
- }
451
- }
452
-
453
- if (privateExportProblems.length === 0 && missingLoadProblems.length === 0) {
454
- const fileCount = formatCount(reachableFiles.length, "reachable Starlark file");
455
- return {
456
- name: "Starlark Load Exports",
457
- didPass: true,
458
- message: `${fileCount} ${reachableFiles.length === 1 ? "has" : "have"} valid load exports and paths`,
459
- };
460
- }
461
-
462
- const sections: string[] = [];
463
- if (privateExportProblems.length > 0) {
464
- sections.push(`Private exported symbols:\n ${privateExportProblems.join("\n ")}`);
465
- }
466
- if (missingLoadProblems.length > 0) {
467
- sections.push(`Missing relative load targets:\n ${missingLoadProblems.join("\n ")}`);
468
- }
469
-
470
- return {
471
- name: "Starlark Load Exports",
472
- didPass: false,
473
- message: `Starlark load() issues will stop Tilt before services start:\n ${sections.join("\n\n ")}`,
474
- fix: "Regenerate with a current TDK (`tdk config regenerate`). If the issue remains, rename loaded symbols without leading underscores and update stale load paths.",
475
- };
476
- }
477
-
478
- function checkStartupScripts(): CheckResult {
479
- const projectRoot = findProjectRoot() ?? process.cwd();
480
- const resources = discoverResourcesFromRoot(projectRoot);
481
-
482
- const problems: string[] = [];
483
-
484
- for (const resource of resources) {
485
- const packageJsonPath = join(resource.path, "package.json");
486
- if (!existsSync(packageJsonPath)) {
487
- continue;
488
- }
489
-
490
- const appType = resource.config?.appType ?? "backend";
491
- const requiredScripts = REQUIRED_PACKAGE_SCRIPTS[appType] ?? REQUIRED_PACKAGE_SCRIPTS.backend;
492
-
493
- let scripts: Record<string, string>;
494
- try {
495
- scripts = JSON.parse(readFileSync(packageJsonPath, "utf-8")).scripts ?? {};
496
- } catch {
497
- problems.push(`${resource.name} (package.json is invalid JSON)`);
498
- continue;
499
- }
500
-
501
- const missing = requiredScripts.filter((script) => !scripts[script]);
502
- if (missing.length > 0) {
503
- problems.push(`${resource.name}: missing "${missing.join('", "')}"`);
504
- }
505
- }
506
-
507
- if (problems.length === 0) {
508
- return {
509
- name: "Startup Scripts",
510
- didPass: true,
511
- message: "All services have required package.json scripts",
512
- };
513
- }
514
-
515
- return {
516
- name: "Startup Scripts",
517
- didPass: false,
518
- message: `Services missing required package.json scripts:\n ${problems.join("\n ")}`,
519
- fix: 'Add the missing scripts to each service\'s package.json, e.g.:\n "dev": "bun run src/index.ts",\n "build": "tsc",\n "start": "bun run dist/index.js"',
520
- };
521
- }
522
-
523
- /**
524
- * Backend/frontend tsconfig generators set `"types": ["bun"]` on the
525
- * assumption that `@types/bun` is a direct devDependency (`tdk resource`
526
- * adds it for new services). Nothing re-adds it if a service's package.json
527
- * loses that entry -- e.g. a checkout missing it entirely, or a manual edit
528
- * -- and the failure only surfaces later as `tsc: TS2688: Cannot find type
529
- * definition file for 'bun'` inside `bun run build`, mid Docker image build.
530
- */
531
- export function checkTypeScriptTypeDependencies(): CheckResult {
532
- const projectRoot = findProjectRoot() ?? process.cwd();
533
- const resources = discoverResourcesFromRoot(projectRoot);
534
-
535
- const problems: string[] = [];
536
-
537
- for (const resource of resources) {
538
- const packageJsonPath = join(resource.path, "package.json");
539
- const dockerTsconfigPath = join(
540
- resource.path,
541
- ".autogenerated",
542
- "tsconfig.docker.autogenerated.json",
543
- );
544
-
545
- if (!existsSync(packageJsonPath) || !existsSync(dockerTsconfigPath)) {
546
- continue;
547
- }
548
-
549
- const tsconfig = readJsonFile(dockerTsconfigPath);
550
- const compilerOptions = tsconfig?.compilerOptions as Record<string, unknown> | undefined;
551
- const types = compilerOptions?.types;
552
- if (!Array.isArray(types) || !types.includes("bun")) {
553
- continue;
554
- }
555
-
556
- const pkg = readJsonFile(packageJsonPath);
557
- const devDependencies = (pkg?.devDependencies as Record<string, string> | undefined) ?? {};
558
- if (!devDependencies["@types/bun"]) {
559
- problems.push(resource.name);
560
- }
561
- }
562
-
563
- if (problems.length === 0) {
564
- return {
565
- name: "TypeScript Type Dependencies",
566
- didPass: true,
567
- message: "All services with a bun-typed tsconfig have @types/bun installed",
568
- };
569
- }
570
-
571
- return {
572
- name: "TypeScript Type Dependencies",
573
- didPass: false,
574
- message: `Services set "types": ["bun"] in their Docker tsconfig but are missing the "@types/bun" devDependency, so \`bun run build\` fails with TS2688:\n ${problems.join("\n ")}`,
575
- fix: 'Add to each service\'s package.json devDependencies: "@types/bun": "^1.4.2"',
576
- };
577
- }
578
-
579
- function readJsonFile(path: string): Record<string, unknown> | null {
580
- try {
581
- return JSON.parse(readFileSync(path, "utf-8")) as Record<string, unknown>;
582
- } catch {
583
- return null;
584
- }
585
- }
586
-
587
- function hasSyntheticDefaultImports(tsconfigPath: string): boolean {
588
- const config = readJsonFile(tsconfigPath);
589
- const compilerOptions = config?.compilerOptions as Record<string, unknown> | undefined;
590
- return (
591
- compilerOptions?.allowSyntheticDefaultImports === true ||
592
- compilerOptions?.esModuleInterop === true
593
- );
594
- }
595
-
596
- export function checkFrontendDockerPreflight(): CheckResult {
597
- const projectRoot = findProjectRoot() ?? process.cwd();
598
- const resources = discoverResourcesFromRoot(projectRoot).filter(
599
- (resource) => resource.config?.appType === "frontend",
600
- );
601
-
602
- if (resources.length === 0) {
603
- return {
604
- name: "Frontend Docker Preflight",
605
- didPass: true,
606
- isSkipped: true,
607
- message: "No frontend services to check",
608
- };
609
- }
610
-
611
- const problems: string[] = [];
612
-
613
- for (const resource of resources) {
614
- const dockerfilePath = join(resource.path, ".autogenerated", "Dockerfile.app.autogenerated");
615
- const dockerTsconfigPath = join(
616
- resource.path,
617
- ".autogenerated",
618
- "tsconfig.docker.autogenerated.json",
619
- );
620
-
621
- if (existsSync(dockerfilePath)) {
622
- const dockerfile = readFileSync(dockerfilePath, "utf-8");
623
- const exposesNginxPort = /\bEXPOSE\s+80\b/.test(dockerfile);
624
- const stack = resource.config?.stack;
625
- const composePath = stack
626
- ? join(
627
- projectRoot,
628
- "services",
629
- stack,
630
- ".autogenerated",
631
- "docker-compose.app.autogenerated.yml",
632
- )
633
- : "";
634
-
635
- if (exposesNginxPort && composePath && existsSync(composePath)) {
636
- const compose = readFileSync(composePath, "utf-8");
637
- const escapedName = resource.name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
638
- const portPattern = new RegExp(
639
- `traefik\\.http\\.services\\.${escapedName}\\.loadbalancer\\.server\\.port=(\\d+)`,
640
- );
641
- const match = compose.match(portPattern);
642
- const routedPort = match?.[1];
643
-
644
- if (routedPort && routedPort !== "80") {
645
- problems.push(
646
- `${resource.name}: nginx runtime exposes 80, but generated Traefik routes to ${routedPort}`,
647
- );
648
- }
649
- }
650
- }
651
-
652
- if (existsSync(dockerTsconfigPath) && !hasSyntheticDefaultImports(dockerTsconfigPath)) {
653
- const mainPath = join(resource.path, "src", "main.tsx");
654
- if (existsSync(mainPath)) {
655
- const main = readFileSync(mainPath, "utf-8");
656
- const defaultImports = [
657
- /import\s+\w+\s+from\s+["']react["']/,
658
- /import\s+\w+\s+from\s+["']react-dom\/client["']/,
659
- ]
660
- .filter((pattern) => pattern.test(main))
661
- .map((pattern) => (pattern.source.includes("react-dom") ? "react-dom/client" : "react"));
662
-
663
- if (defaultImports.length > 0) {
664
- problems.push(
665
- `${resource.name}: Docker tsconfig does not allow synthetic default imports, but src/main.tsx default-imports ${defaultImports.join(" and ")}`,
666
- );
667
- }
668
- }
669
- }
670
- }
671
-
672
- if (problems.length === 0) {
673
- const frontendCount = formatCount(resources.length, "frontend");
674
- return {
675
- name: "Frontend Docker Preflight",
676
- didPass: true,
677
- message: `${frontendCount} ${resources.length === 1 ? "has" : "have"} compatible Docker build/routing metadata`,
678
- };
679
- }
680
-
681
- return {
682
- name: "Frontend Docker Preflight",
683
- didPass: false,
684
- message: `Frontend Docker metadata has issues that will make \`tdk up\` fail or route 404:\n ${problems.join("\n ")}`,
685
- fix: 'Regenerate with a current TDK (`tdk config regenerate`) and ensure frontend nginx runtimes route to port 80. For React entrypoints, prefer named imports: `import { StrictMode } from "react"` and `import { createRoot } from "react-dom/client"`.',
686
- };
687
- }
688
-
689
- const MEM_NEAR_LIMIT_PCT = 90;
690
- const CPU_HANGING_PCT = 80;
691
-
692
- interface ContainerStat {
693
- name: string;
694
- memPct: number;
695
- cpuPct: number;
696
- }
697
-
698
- function parseDockerStats(raw: string): ContainerStat[] {
699
- return raw
700
- .split("\n")
701
- .map((line) => line.trim())
702
- .filter(Boolean)
703
- .map((line) => {
704
- const [name, memPctRaw, cpuPctRaw] = line.split(",");
705
- return {
706
- name: name ?? "unknown",
707
- memPct: Number.parseFloat((memPctRaw ?? "").replace("%", "")),
708
- cpuPct: Number.parseFloat((cpuPctRaw ?? "").replace("%", "")),
709
- };
710
- })
711
- .filter((stat) => Number.isFinite(stat.memPct) && Number.isFinite(stat.cpuPct));
712
- }
713
-
714
- /**
715
- * Flags containers pinned near their memory limit while also burning CPU --
716
- * the signature of a boot-time process stuck in a retry/fetch loop, not a
717
- * genuine crash (which would just exit, not sit at ~100% resource usage).
718
- *
719
- * Caught in this workspace: a backend runtime image missing the local Prisma
720
- * CLI fell back to `bunx prisma`, which re-fetched prisma@latest from npm on
721
- * every container start. That pinned a 512MB container at ~100% memory and
722
- * 100%+ CPU indefinitely, and it never became healthy. Neither `docker ps`
723
- * (just shows "unhealthy") nor the healthcheck's own retry loop surfaces
724
- * *why* -- only live resource stats catch this pattern before it's mistaken
725
- * for a slow migration or a flaky healthcheck.
726
- */
727
- function checkContainerResourceHealth(): CheckResult {
728
- let raw: string;
729
- try {
730
- raw = execSync('docker stats --no-stream --format "{{.Name}},{{.MemPerc}},{{.CPUPerc}}"', {
731
- stdio: "pipe",
732
- encoding: "utf-8",
733
- timeout: EXEC_TIMEOUT_MS,
734
- });
735
- } catch (err) {
736
- return {
737
- name: "Container Resource Health",
738
- didPass: true,
739
- isSkipped: true,
740
- message: isTimeout(err)
741
- ? "Docker not responding - skipped container resource check"
742
- : "Docker not running - skipped container resource check",
743
- };
744
- }
745
-
746
- const stats = parseDockerStats(raw);
747
- if (stats.length === 0) {
748
- return {
749
- name: "Container Resource Health",
750
- didPass: true,
751
- isSkipped: true,
752
- message: "No running containers to check",
753
- };
754
- }
755
-
756
- const hangers = stats.filter(
757
- (stat) => stat.memPct >= MEM_NEAR_LIMIT_PCT && stat.cpuPct >= CPU_HANGING_PCT,
758
- );
759
-
760
- if (hangers.length === 0) {
761
- return {
762
- name: "Container Resource Health",
763
- didPass: true,
764
- message: `${formatCount(stats.length, "container")} within normal resource usage`,
765
- };
766
- }
767
-
768
- const details = hangers
769
- .map((stat) => `${stat.name} (mem ${stat.memPct.toFixed(0)}%, cpu ${stat.cpuPct.toFixed(0)}%)`)
770
- .join("\n ");
771
-
772
- return {
773
- name: "Container Resource Health",
774
- didPass: false,
775
- message: `${formatCount(hangers.length, "container")} pinned near its memory limit while burning CPU -- likely stuck in a boot-time retry/fetch loop, not a normal crash:\n ${details}`,
776
- fix: "Check the container's boot logs for a network fetch loop (e.g. `bunx <pkg>` re-downloading a CLI on every start instead of using one already installed): docker logs <container>. If a Prisma auto-migration is the cause, set AUTO_MIGRATE=false in the project's .env as a temporary unblock.",
777
- };
778
- }
779
-
780
- const DEFAULT_PING_TIMEOUT_MS = 5000;
781
-
782
- /**
783
- * Pings every routable service on the same /health URLs `tdk up` advertises.
784
- *
785
- * This is a runtime check, not an environment one: before `tdk up` there is
786
- * nothing to ping, so a stopped stack is reported as skipped and doctor still
787
- * passes. Once services are up, an unreachable endpoint is a real failure --
788
- * it catches the case where a container is running but Traefik never routed
789
- * to it, which `docker ps` alone will not show.
790
- */
791
- async function checkServiceHealth(timeoutMs: number): Promise<CheckResult> {
792
- const projectRoot = findProjectRoot() ?? process.cwd();
793
- const targets = buildHealthTargets(discoverResourcesFromRoot(projectRoot));
794
-
795
- if (targets.length === 0) {
796
- return {
797
- name: "Service Health",
798
- didPass: true,
799
- isSkipped: true,
800
- message: "No routable services to ping",
801
- };
802
- }
803
-
804
- const probes = await pingHealthTargets(targets, timeoutMs);
805
- const reachable = probes.filter((probe) => probe.ok);
806
- const failed = probes.filter((probe) => !probe.ok);
807
-
808
- // Nothing answered at all: either the stack was never started, or ingress
809
- // never came up (Traefik port conflict). Prefer failing via
810
- // checkTiltResourceHealth / checkIngressPorts when Tilt is up; here we only
811
- // skip when there is truly nothing to probe yet.
812
- if (reachable.length === 0) {
813
- return {
814
- name: "Service Health",
815
- didPass: true,
816
- isSkipped: true,
817
- message: `No services responded - skipped ping of ${formatCount(targets.length, "service")} (stack may be down, or Traefik never bound :80)`,
818
- fix: "If `tdk up` is already running, check Traefik/port 80 in the Tilt UI. Otherwise start with: tdk up",
819
- };
820
- }
821
-
822
- if (failed.length === 0) {
823
- return {
824
- name: "Service Health",
825
- didPass: true,
826
- message: `All ${formatCount(targets.length, "service")} responding on /health`,
827
- };
828
- }
829
-
830
- const details = failed
831
- .map((probe) => {
832
- const reason = probe.status ? `HTTP ${probe.status}` : (probe.error ?? "no response");
833
- return `${probe.name} (${reason})\n ${probe.url}`;
834
- })
835
- .join("\n ");
836
-
837
- return {
838
- name: "Service Health",
839
- didPass: false,
840
- message: `${formatCount(failed.length, "service")} not responding (${reachable.length}/${probes.length} healthy):\n ${details}`,
841
- fix: "Check container state and routing: docker ps, then tdk networks to compare the advertised URLs against Traefik's routers",
842
- };
843
- }
844
-
845
- export const doctorCommand = new Command("doctor")
846
- .description("Check environment readiness for TDK")
847
- .option("--no-ping", "Skip pinging running services' /health endpoints")
848
- .option(
849
- "--ping-timeout <ms>",
850
- "Per-service ping timeout in milliseconds",
851
- String(DEFAULT_PING_TIMEOUT_MS),
852
- )
853
- .action(async (options) => {
854
- console.log(`\n${chalk.bold("🔍 TDK Doctor")}\n`);
855
- console.log("Checking environment...\n");
856
-
857
- const pingTimeout = Number.parseInt(options.pingTimeout, 10);
858
- if (!Number.isFinite(pingTimeout) || pingTimeout <= 0) {
859
- console.log(`${chalk.red("✗")} --ping-timeout must be a positive number of milliseconds`);
860
- process.exit(1);
861
- }
862
-
863
- const checks: Array<() => CheckResult | Promise<CheckResult>> = [
864
- checkDockerRuntime,
865
- checkTilt,
866
- checkDockerCompose,
867
- checkDockerVersions,
868
- checkMasterConfigs,
869
- checkGeneratedProjectRuntimeAssets,
870
- checkStarlarkLoadExports,
871
- checkStartupScripts,
872
- checkTypeScriptTypeDependencies,
873
- checkFrontendDockerPreflight,
874
- checkEnvironmentVariables,
875
- // Preflight: catch "port 80 already allocated" BEFORE claiming ready.
876
- checkIngressPorts,
877
- // Preflight: Verdaccio down causes ImageBuild bun install ConnectionRefused.
878
- checkPrivateNpmRegistry,
879
- // Runtime checks: skip gracefully if the stack isn't started yet.
880
- checkContainerResourceHealth,
881
- // When Tilt is up, surface red resources (Traefik/apps never started).
882
- checkTiltResourceHealth,
883
- ];
884
-
885
- // Runs last: needs routable services (and working Traefik) to mean anything.
886
- if (options.ping) {
887
- checks.push(() => checkServiceHealth(pingTimeout));
888
- }
889
-
890
- let allPassed = true;
891
-
892
- for (const checkFn of checks) {
893
- const result = await checkFn();
894
-
895
- if (result.isSkipped) {
896
- console.log(`${chalk.gray("○")} ${chalk.gray(result.message)}`);
897
- if (result.fix) {
898
- console.log(`${chalk.blue("ℹ")} ${result.fix}`);
899
- }
900
- } else if (result.didPass) {
901
- console.log(`${chalk.green("✓")} ${result.message}`);
902
- } else {
903
- console.log(`${chalk.red("✗")} ${result.message}`);
904
- if (result.fix) {
905
- console.log(`${chalk.blue("ℹ")} Fix: ${result.fix}`);
906
- }
907
- allPassed = false;
908
- break;
909
- }
910
- }
911
-
912
- console.log("");
913
-
914
- if (allPassed) {
915
- console.log(`${chalk.green(chalk.bold("✓"))} Environment ready for TDK`);
916
- console.log("");
917
- console.log("Next steps:");
918
- console.log(" 1. Run: tdk up");
919
- console.log(" 2. Open: http://localhost:10350");
920
- } else {
921
- console.log(`${chalk.red(chalk.bold("✗"))} Environment not ready`);
922
- console.log("");
923
- console.log("Fix the issues above, then run: tdk doctor");
924
- process.exit(1);
925
- }
926
- });