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

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 (388) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/cli/dist/generator/extension-fetch.js +16 -9
  3. package/cli/package.json +1 -1
  4. package/package.json +16 -1
  5. package/.claude/skills/layer-autoresearch/SKILL.md +0 -48
  6. package/.claude/skills/tdk-troubleshoot/SKILL.md +0 -222
  7. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -40
  8. package/.github/ISSUE_TEMPLATE/config.yml +0 -11
  9. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -18
  10. package/.github/ISSUE_TEMPLATE/premium_license.yml +0 -43
  11. package/.github/dependabot.yml +0 -33
  12. package/.github/pull_request_template.md +0 -5
  13. package/.github/workflows/ci.yml +0 -200
  14. package/.github/workflows/release-binaries.yml +0 -139
  15. package/.github/zizmor.yml +0 -9
  16. package/.pre-commit-config.yaml +0 -57
  17. package/CODE_OF_CONDUCT.md +0 -9
  18. package/CONTRIBUTING.md +0 -42
  19. package/Makefile +0 -92
  20. package/SECURITY.md +0 -17
  21. package/benchmarks/results/container-scale-2026-09-25T20-54-49-736Z.json +0 -45
  22. package/benchmarks/results/container-scale-2026-09-25T21-01-20-540Z.json +0 -150
  23. package/benchmarks/results/container-scale-2026-09-25T21-15-01-441Z.json +0 -73
  24. package/benchmarks/results/container-scale-2026-09-25T22-09-01-630Z.json +0 -77
  25. package/benchmarks/results/container-scale-2026-09-25T22-18-28-371Z.json +0 -202
  26. package/cli/AGENTS.md +0 -390
  27. package/cli/DESIGN.md +0 -735
  28. package/cli/README.md +0 -292
  29. package/cli/biome.json +0 -40
  30. package/cli/dependency-graph.svg +0 -1135
  31. package/cli/dist/cli.d.ts +0 -3
  32. package/cli/dist/cli.d.ts.map +0 -1
  33. package/cli/dist/cli.js.map +0 -1
  34. package/cli/dist/commands/completion.d.ts +0 -3
  35. package/cli/dist/commands/completion.d.ts.map +0 -1
  36. package/cli/dist/commands/completion.js.map +0 -1
  37. package/cli/dist/commands/config.d.ts +0 -3
  38. package/cli/dist/commands/config.d.ts.map +0 -1
  39. package/cli/dist/commands/config.js.map +0 -1
  40. package/cli/dist/commands/doctor.d.ts +0 -19
  41. package/cli/dist/commands/doctor.d.ts.map +0 -1
  42. package/cli/dist/commands/doctor.js.map +0 -1
  43. package/cli/dist/commands/down.d.ts +0 -3
  44. package/cli/dist/commands/down.d.ts.map +0 -1
  45. package/cli/dist/commands/down.js.map +0 -1
  46. package/cli/dist/commands/help.d.ts +0 -2
  47. package/cli/dist/commands/help.d.ts.map +0 -1
  48. package/cli/dist/commands/help.js.map +0 -1
  49. package/cli/dist/commands/networks.d.ts +0 -3
  50. package/cli/dist/commands/networks.d.ts.map +0 -1
  51. package/cli/dist/commands/networks.js.map +0 -1
  52. package/cli/dist/commands/project.d.ts +0 -9
  53. package/cli/dist/commands/project.d.ts.map +0 -1
  54. package/cli/dist/commands/project.js.map +0 -1
  55. package/cli/dist/commands/projects.d.ts +0 -3
  56. package/cli/dist/commands/projects.d.ts.map +0 -1
  57. package/cli/dist/commands/projects.js.map +0 -1
  58. package/cli/dist/commands/resource.d.ts +0 -69
  59. package/cli/dist/commands/resource.d.ts.map +0 -1
  60. package/cli/dist/commands/resource.js.map +0 -1
  61. package/cli/dist/commands/resources.d.ts +0 -3
  62. package/cli/dist/commands/resources.d.ts.map +0 -1
  63. package/cli/dist/commands/resources.js.map +0 -1
  64. package/cli/dist/commands/stack.d.ts +0 -3
  65. package/cli/dist/commands/stack.d.ts.map +0 -1
  66. package/cli/dist/commands/stack.js.map +0 -1
  67. package/cli/dist/commands/stacks.d.ts +0 -3
  68. package/cli/dist/commands/stacks.d.ts.map +0 -1
  69. package/cli/dist/commands/stacks.js.map +0 -1
  70. package/cli/dist/commands/status.d.ts +0 -3
  71. package/cli/dist/commands/status.d.ts.map +0 -1
  72. package/cli/dist/commands/status.js.map +0 -1
  73. package/cli/dist/commands/ui.d.ts +0 -3
  74. package/cli/dist/commands/ui.d.ts.map +0 -1
  75. package/cli/dist/commands/ui.js.map +0 -1
  76. package/cli/dist/commands/up.d.ts +0 -3
  77. package/cli/dist/commands/up.d.ts.map +0 -1
  78. package/cli/dist/commands/up.js.map +0 -1
  79. package/cli/dist/commands/upgrade.d.ts +0 -14
  80. package/cli/dist/commands/upgrade.d.ts.map +0 -1
  81. package/cli/dist/commands/upgrade.js.map +0 -1
  82. package/cli/dist/commands/version.d.ts +0 -3
  83. package/cli/dist/commands/version.d.ts.map +0 -1
  84. package/cli/dist/commands/version.js.map +0 -1
  85. package/cli/dist/components/Accessible.d.ts +0 -8
  86. package/cli/dist/components/Accessible.d.ts.map +0 -1
  87. package/cli/dist/components/Accessible.js.map +0 -1
  88. package/cli/dist/components/BaseTooltip.d.ts +0 -4
  89. package/cli/dist/components/BaseTooltip.d.ts.map +0 -1
  90. package/cli/dist/components/BaseTooltip.js.map +0 -1
  91. package/cli/dist/components/DetailPanel.d.ts +0 -4
  92. package/cli/dist/components/DetailPanel.d.ts.map +0 -1
  93. package/cli/dist/components/DetailPanel.js.map +0 -1
  94. package/cli/dist/components/FileTree.d.ts +0 -4
  95. package/cli/dist/components/FileTree.d.ts.map +0 -1
  96. package/cli/dist/components/FileTree.js.map +0 -1
  97. package/cli/dist/components/ResourceSelectInput.d.ts +0 -4
  98. package/cli/dist/components/ResourceSelectInput.d.ts.map +0 -1
  99. package/cli/dist/components/ResourceSelectInput.js.map +0 -1
  100. package/cli/dist/components/ResourceTable.d.ts +0 -4
  101. package/cli/dist/components/ResourceTable.d.ts.map +0 -1
  102. package/cli/dist/components/ResourceTable.js.map +0 -1
  103. package/cli/dist/components/TabBar.d.ts +0 -4
  104. package/cli/dist/components/TabBar.d.ts.map +0 -1
  105. package/cli/dist/components/TabBar.js.map +0 -1
  106. package/cli/dist/components/Tooltip.d.ts +0 -12
  107. package/cli/dist/components/Tooltip.d.ts.map +0 -1
  108. package/cli/dist/components/Tooltip.js.map +0 -1
  109. package/cli/dist/components/index.d.ts +0 -8
  110. package/cli/dist/components/index.d.ts.map +0 -1
  111. package/cli/dist/components/index.js.map +0 -1
  112. package/cli/dist/config/platform-standards.d.ts +0 -159
  113. package/cli/dist/config/platform-standards.d.ts.map +0 -1
  114. package/cli/dist/config/platform-standards.js.map +0 -1
  115. package/cli/dist/generator/extension-fetch.d.ts +0 -25
  116. package/cli/dist/generator/extension-fetch.d.ts.map +0 -1
  117. package/cli/dist/generator/extension-fetch.js.map +0 -1
  118. package/cli/dist/generator/template-engine.d.ts +0 -62
  119. package/cli/dist/generator/template-engine.d.ts.map +0 -1
  120. package/cli/dist/generator/template-engine.js.map +0 -1
  121. package/cli/dist/index.d.ts +0 -11
  122. package/cli/dist/index.d.ts.map +0 -1
  123. package/cli/dist/index.js.map +0 -1
  124. package/cli/dist/types/index.d.ts +0 -257
  125. package/cli/dist/types/index.d.ts.map +0 -1
  126. package/cli/dist/types/index.js.map +0 -1
  127. package/cli/dist/utils/cache.d.ts +0 -19
  128. package/cli/dist/utils/cache.d.ts.map +0 -1
  129. package/cli/dist/utils/cache.js.map +0 -1
  130. package/cli/dist/utils/command-helpers.d.ts +0 -17
  131. package/cli/dist/utils/command-helpers.d.ts.map +0 -1
  132. package/cli/dist/utils/command-helpers.js.map +0 -1
  133. package/cli/dist/utils/constants.d.ts +0 -53
  134. package/cli/dist/utils/constants.d.ts.map +0 -1
  135. package/cli/dist/utils/constants.js.map +0 -1
  136. package/cli/dist/utils/discovery-context.d.ts +0 -4
  137. package/cli/dist/utils/discovery-context.d.ts.map +0 -1
  138. package/cli/dist/utils/discovery-context.js.map +0 -1
  139. package/cli/dist/utils/docker.d.ts +0 -4
  140. package/cli/dist/utils/docker.d.ts.map +0 -1
  141. package/cli/dist/utils/docker.js.map +0 -1
  142. package/cli/dist/utils/doctor-runtime.d.ts +0 -81
  143. package/cli/dist/utils/doctor-runtime.d.ts.map +0 -1
  144. package/cli/dist/utils/doctor-runtime.js.map +0 -1
  145. package/cli/dist/utils/env-validator.d.ts +0 -15
  146. package/cli/dist/utils/env-validator.d.ts.map +0 -1
  147. package/cli/dist/utils/env-validator.js.map +0 -1
  148. package/cli/dist/utils/errors.d.ts +0 -31
  149. package/cli/dist/utils/errors.d.ts.map +0 -1
  150. package/cli/dist/utils/errors.js.map +0 -1
  151. package/cli/dist/utils/file-helpers.d.ts +0 -14
  152. package/cli/dist/utils/file-helpers.d.ts.map +0 -1
  153. package/cli/dist/utils/file-helpers.js.map +0 -1
  154. package/cli/dist/utils/formatting.d.ts +0 -30
  155. package/cli/dist/utils/formatting.d.ts.map +0 -1
  156. package/cli/dist/utils/formatting.js.map +0 -1
  157. package/cli/dist/utils/paths.d.ts +0 -3
  158. package/cli/dist/utils/paths.d.ts.map +0 -1
  159. package/cli/dist/utils/paths.js.map +0 -1
  160. package/cli/dist/utils/port-assignment.d.ts +0 -6
  161. package/cli/dist/utils/port-assignment.d.ts.map +0 -1
  162. package/cli/dist/utils/port-assignment.js.map +0 -1
  163. package/cli/dist/utils/project-features.d.ts +0 -23
  164. package/cli/dist/utils/project-features.d.ts.map +0 -1
  165. package/cli/dist/utils/project-features.js.map +0 -1
  166. package/cli/dist/utils/project-templates.d.ts +0 -7
  167. package/cli/dist/utils/project-templates.d.ts.map +0 -1
  168. package/cli/dist/utils/project-templates.js.map +0 -1
  169. package/cli/dist/utils/prompt.d.ts +0 -28
  170. package/cli/dist/utils/prompt.d.ts.map +0 -1
  171. package/cli/dist/utils/prompt.js.map +0 -1
  172. package/cli/dist/utils/resource-features.d.ts +0 -29
  173. package/cli/dist/utils/resource-features.d.ts.map +0 -1
  174. package/cli/dist/utils/resource-features.js.map +0 -1
  175. package/cli/dist/utils/service-urls.d.ts +0 -30
  176. package/cli/dist/utils/service-urls.d.ts.map +0 -1
  177. package/cli/dist/utils/service-urls.js.map +0 -1
  178. package/cli/dist/utils/services.d.ts +0 -18
  179. package/cli/dist/utils/services.d.ts.map +0 -1
  180. package/cli/dist/utils/services.js.map +0 -1
  181. package/cli/dist/utils/stack-features.d.ts +0 -22
  182. package/cli/dist/utils/stack-features.d.ts.map +0 -1
  183. package/cli/dist/utils/stack-features.js.map +0 -1
  184. package/cli/dist/utils/tar.d.ts +0 -7
  185. package/cli/dist/utils/tar.d.ts.map +0 -1
  186. package/cli/dist/utils/tar.js.map +0 -1
  187. package/cli/dist/utils/tilt.d.ts +0 -20
  188. package/cli/dist/utils/tilt.d.ts.map +0 -1
  189. package/cli/dist/utils/tilt.js.map +0 -1
  190. package/cli/dist/utils/validation.d.ts +0 -16
  191. package/cli/dist/utils/validation.d.ts.map +0 -1
  192. package/cli/dist/utils/validation.js.map +0 -1
  193. package/cli/knip.json +0 -6
  194. package/cli/pnpm-lock.yaml +0 -2305
  195. package/cli/pnpm-workspace.yaml +0 -2
  196. package/cli/src/cli.ts +0 -72
  197. package/cli/src/commands/__tests__/always-enabled-infra.test.ts +0 -109
  198. package/cli/src/commands/__tests__/config.test.ts +0 -146
  199. package/cli/src/commands/__tests__/doctor.test.ts +0 -730
  200. package/cli/src/commands/__tests__/error-handling.test.ts +0 -78
  201. package/cli/src/commands/__tests__/phases-model.test.ts +0 -161
  202. package/cli/src/commands/__tests__/project-resource-features-e2e.test.ts +0 -187
  203. package/cli/src/commands/__tests__/project.test.ts +0 -68
  204. package/cli/src/commands/__tests__/resource.test.ts +0 -226
  205. package/cli/src/commands/__tests__/saas-starter-integration.test.ts +0 -194
  206. package/cli/src/commands/__tests__/stack-features-e2e.test.ts +0 -135
  207. package/cli/src/commands/__tests__/upgrade.test.ts +0 -198
  208. package/cli/src/commands/completion.ts +0 -300
  209. package/cli/src/commands/config.ts +0 -299
  210. package/cli/src/commands/doctor.ts +0 -926
  211. package/cli/src/commands/down.ts +0 -37
  212. package/cli/src/commands/help.ts +0 -143
  213. package/cli/src/commands/networks-design.md +0 -80
  214. package/cli/src/commands/networks.ts +0 -332
  215. package/cli/src/commands/project.ts +0 -456
  216. package/cli/src/commands/projects.ts +0 -82
  217. package/cli/src/commands/resource.ts +0 -652
  218. package/cli/src/commands/resources.ts +0 -95
  219. package/cli/src/commands/stack.ts +0 -128
  220. package/cli/src/commands/stacks.ts +0 -52
  221. package/cli/src/commands/status.ts +0 -88
  222. package/cli/src/commands/ui.tsx +0 -843
  223. package/cli/src/commands/up.ts +0 -169
  224. package/cli/src/commands/upgrade.ts +0 -628
  225. package/cli/src/commands/version.ts +0 -9
  226. package/cli/src/components/Accessible.tsx +0 -21
  227. package/cli/src/components/BaseTooltip.tsx +0 -66
  228. package/cli/src/components/DetailPanel.tsx +0 -146
  229. package/cli/src/components/FileTree.tsx +0 -89
  230. package/cli/src/components/ResourceSelectInput.tsx +0 -30
  231. package/cli/src/components/ResourceTable.tsx +0 -78
  232. package/cli/src/components/TabBar.tsx +0 -53
  233. package/cli/src/components/Tooltip.tsx +0 -11
  234. package/cli/src/components/index.ts +0 -7
  235. package/cli/src/config/platform-standards.test.ts +0 -11
  236. package/cli/src/config/platform-standards.ts +0 -196
  237. package/cli/src/generator/__tests__/extension-fetch.test.ts +0 -242
  238. package/cli/src/generator/__tests__/template-engine.test.ts +0 -70
  239. package/cli/src/generator/extension-fetch.ts +0 -286
  240. package/cli/src/generator/template-engine.ts +0 -752
  241. package/cli/src/index.ts +0 -86
  242. package/cli/src/templates.d.ts +0 -4
  243. package/cli/src/types/index.ts +0 -353
  244. package/cli/src/utils/__tests__/cache.test.ts +0 -98
  245. package/cli/src/utils/__tests__/formatting.test.ts +0 -170
  246. package/cli/src/utils/__tests__/paths.test.ts +0 -180
  247. package/cli/src/utils/__tests__/port-assignment.test.ts +0 -121
  248. package/cli/src/utils/__tests__/service-urls.test.ts +0 -174
  249. package/cli/src/utils/__tests__/services.test.ts +0 -531
  250. package/cli/src/utils/__tests__/tilt.test.ts +0 -172
  251. package/cli/src/utils/__tests__/validation.test.ts +0 -148
  252. package/cli/src/utils/cache.ts +0 -76
  253. package/cli/src/utils/command-helpers.ts +0 -54
  254. package/cli/src/utils/constants.ts +0 -130
  255. package/cli/src/utils/discovery-context.ts +0 -49
  256. package/cli/src/utils/docker.ts +0 -20
  257. package/cli/src/utils/doctor-runtime.ts +0 -644
  258. package/cli/src/utils/env-validator.ts +0 -139
  259. package/cli/src/utils/errors.ts +0 -168
  260. package/cli/src/utils/file-helpers.ts +0 -62
  261. package/cli/src/utils/formatting.ts +0 -215
  262. package/cli/src/utils/paths.ts +0 -53
  263. package/cli/src/utils/port-assignment.ts +0 -106
  264. package/cli/src/utils/project-features.ts +0 -118
  265. package/cli/src/utils/project-templates.ts +0 -29
  266. package/cli/src/utils/prompt.ts +0 -128
  267. package/cli/src/utils/resource-features.ts +0 -215
  268. package/cli/src/utils/service-urls.ts +0 -124
  269. package/cli/src/utils/services.ts +0 -364
  270. package/cli/src/utils/stack-features.ts +0 -30
  271. package/cli/src/utils/tar.ts +0 -24
  272. package/cli/src/utils/tilt.ts +0 -133
  273. package/cli/src/utils/validation.ts +0 -67
  274. package/cli/tsconfig.json +0 -25
  275. package/cli/tsconfig.typecheck.json +0 -8
  276. package/docs/FEATURES.md +0 -281
  277. package/docs/demo.svg +0 -217
  278. package/engine/docs/AUTODISCOVERY_TEST.md +0 -182
  279. package/engine/docs/C4-ARCHITECTURE-operations.md +0 -396
  280. package/engine/docs/C4-ARCHITECTURE-overview.md +0 -284
  281. package/engine/docs/C4-ARCHITECTURE.md +0 -17
  282. package/engine/docs/GOLDEN_IMAGE_INTEGRATION.md +0 -349
  283. package/engine/docs/MANIFEST_DRIVEN_ARCHITECTURE.md +0 -357
  284. package/engine/docs/README.md +0 -284
  285. package/install.sh +0 -19
  286. package/knip.json +0 -10
  287. package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/.openspec.yaml +0 -2
  288. package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/design.md +0 -102
  289. package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/proposal.md +0 -31
  290. package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/specs/vscode-tdk-notifications/spec.md +0 -48
  291. package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/specs/vscode-tdk-orchestration/spec.md +0 -63
  292. package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/specs/vscode-tdk-troubleshooting/spec.md +0 -56
  293. package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/tasks.md +0 -61
  294. package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/.openspec.yaml +0 -2
  295. package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/design.md +0 -114
  296. package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/proposal.md +0 -32
  297. package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/specs/manifest-field-migration/spec.md +0 -20
  298. package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/specs/resource-terminology-standard/spec.md +0 -20
  299. package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/specs/stack-terminology-standard/spec.md +0 -20
  300. package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/tasks.md +0 -194
  301. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/.openspec.yaml +0 -2
  302. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/design.md +0 -111
  303. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/proposal.md +0 -33
  304. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/function-naming-alignment/spec.md +0 -12
  305. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/optional-parameter-patterns/spec.md +0 -18
  306. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/parameter-documentation/spec.md +0 -16
  307. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/parameter-naming-consistency/spec.md +0 -12
  308. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/parameter-ordering-standard/spec.md +0 -12
  309. package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/tasks.md +0 -194
  310. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/.openspec.yaml +0 -2
  311. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/design.md +0 -84
  312. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/proposal.md +0 -31
  313. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/codebase-audit/spec.md +0 -27
  314. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/dead-code-cleanup/spec.md +0 -27
  315. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/test-gap-fill/spec.md +0 -23
  316. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/todo-resolution/spec.md +0 -27
  317. package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/tasks.md +0 -39
  318. package/openspec/changes/archive/2026-06-25-landscape-consolidation/.openspec.yaml +0 -2
  319. package/openspec/changes/archive/2026-06-25-landscape-consolidation/design.md +0 -80
  320. package/openspec/changes/archive/2026-06-25-landscape-consolidation/proposal.md +0 -40
  321. package/openspec/changes/archive/2026-06-25-landscape-consolidation/spec.md +0 -52
  322. package/openspec/changes/archive/2026-06-25-landscape-consolidation/tasks.md +0 -51
  323. package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/.openspec.yaml +0 -2
  324. package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/design.md +0 -43
  325. package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/proposal.md +0 -29
  326. package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/specs/self-contained-generated-projects/spec.md +0 -67
  327. package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/tasks.md +0 -27
  328. package/openspec/changes/optimize-runtime-docker-layers/.openspec.yaml +0 -3
  329. package/openspec/changes/optimize-runtime-docker-layers/design.md +0 -81
  330. package/openspec/changes/optimize-runtime-docker-layers/proposal.md +0 -44
  331. package/openspec/changes/optimize-runtime-docker-layers/specs/runtime-container-footprint/spec.md +0 -79
  332. package/openspec/changes/optimize-runtime-docker-layers/tasks.md +0 -36
  333. package/openspec/changes/prioritized-cold-start/.openspec.yaml +0 -4
  334. package/openspec/changes/prioritized-cold-start/design.md +0 -137
  335. package/openspec/changes/prioritized-cold-start/proposal.md +0 -41
  336. package/openspec/changes/prioritized-cold-start/specs/on-demand-resource-startup/spec.md +0 -98
  337. package/openspec/changes/prioritized-cold-start/tasks.md +0 -69
  338. package/openspec/config.yaml +0 -1
  339. package/openspec/specs/manifest-field-migration/spec.md +0 -24
  340. package/openspec/specs/resource-terminology-standard/spec.md +0 -24
  341. package/openspec/specs/self-contained-generated-projects/spec.md +0 -67
  342. package/openspec/specs/stack-terminology-standard/spec.md +0 -24
  343. package/platform/services/platform/proxy/service.yaml +0 -14
  344. package/scripts/audit-codebase.sh +0 -213
  345. package/scripts/autoresearch/layer-eval.sh +0 -65
  346. package/scripts/benchmark/README.md +0 -25
  347. package/scripts/benchmark/container-scale.ts +0 -503
  348. package/scripts/benchmark/pre-release-gate.sh +0 -9
  349. package/scripts/install-git-hooks.sh +0 -14
  350. package/scripts/measure-idle-footprint.sh +0 -58
  351. package/scripts/record-demo.sh +0 -43
  352. package/scripts/release-binaries.sh +0 -97
  353. package/scripts/setup-pre-commit.sh +0 -33
  354. package/scripts/stage-npm-engine.sh +0 -36
  355. package/tests/tilt-engine/__init__.py +0 -5
  356. package/tests/tilt-engine/conftest.py +0 -182
  357. package/tests/tilt-engine/fixtures/appointment-frontend-service.json +0 -11
  358. package/tests/tilt-engine/fixtures/identity-backend-service.json +0 -12
  359. package/tests/tilt-engine/fixtures/invalid-service.json +0 -4
  360. package/tests/tilt-engine/test_agents_md_generator.py +0 -341
  361. package/tests/tilt-engine/test_agents_md_integration.py +0 -378
  362. package/tests/tilt-engine/test_cache_operations.py +0 -181
  363. package/tests/tilt-engine/test_cache_persistence.py +0 -142
  364. package/tests/tilt-engine/test_code_executor.py +0 -152
  365. package/tests/tilt-engine/test_code_viewer.py +0 -127
  366. package/tests/tilt-engine/test_compose_port_anchors.py +0 -310
  367. package/tests/tilt-engine/test_config_inspector.py +0 -162
  368. package/tests/tilt-engine/test_daemon_focus_mode.py +0 -89
  369. package/tests/tilt-engine/test_daemon_polling.py +0 -122
  370. package/tests/tilt-engine/test_daemon_registration.py +0 -115
  371. package/tests/tilt-engine/test_daemon_validation.py +0 -107
  372. package/tests/tilt-engine/test_docker_generator_bugs.py +0 -493
  373. package/tests/tilt-engine/test_docker_prune.py +0 -119
  374. package/tests/tilt-engine/test_dockerignore_path_bug.py +0 -82
  375. package/tests/tilt-engine/test_file_browser.py +0 -193
  376. package/tests/tilt-engine/test_frontend_basepath_manifest.py +0 -27
  377. package/tests/tilt-engine/test_health_dependencies.py +0 -130
  378. package/tests/tilt-engine/test_health_endpoints.py +0 -118
  379. package/tests/tilt-engine/test_health_tilt_ui.py +0 -85
  380. package/tests/tilt-engine/test_runtime_container_footprint.py +0 -162
  381. package/tests/tilt-engine/test_sablier_defer_start.py +0 -237
  382. package/tests/tilt-engine/test_safety_aliases.py +0 -84
  383. package/tests/tilt-engine/test_snapshot_diff.py +0 -136
  384. package/tests/tilt-engine/test_snapshot_persistence.py +0 -163
  385. package/tests/tilt-engine/test_snapshot_scanning.py +0 -123
  386. package/tests/tilt-engine/test_standalone_project_boot.py +0 -61
  387. package/tests/tilt-engine/test_standalone_traefik.py +0 -160
  388. package/tests/tilt-engine/test_traefik_static_wake_route.py +0 -187
@@ -1,162 +0,0 @@
1
- """
2
- Tests for config inspector component.
3
- Tests the multi-pane comparison and editing features.
4
- """
5
-
6
- import os
7
- import pytest
8
- import hashlib
9
- from pathlib import Path
10
-
11
-
12
- @pytest.mark.ide
13
- class TestConfigInspector:
14
- """Tests for config inspector functionality."""
15
-
16
- def test_single_pane_default_view(self):
17
- """
18
- Scenario: Single-pane default view
19
- WHEN a user requests `GET /`
20
- THEN it SHALL display a single pane with the first master config
21
- """
22
- # Simulate default view
23
- panes = [{"name": "TILT_RESOURCE_DEFAULTS.star", "content": "# Content"}]
24
-
25
- assert len(panes) == 1, "Default view should have 1 pane"
26
- assert "TILT_RESOURCE_DEFAULTS.star" in panes[0]["name"]
27
-
28
- def test_dual_pane_comparison(self):
29
- """
30
- Scenario: Dual-pane comparison
31
- WHEN a user requests `GET /?master1=TILT_RESOURCE_DEFAULTS.star&master2=spec.master`
32
- THEN it SHALL display two panes side-by-side
33
- AND both configs SHALL be viewable simultaneously
34
- """
35
- # Simulate dual-pane request
36
- requested_masters = ["TILT_RESOURCE_DEFAULTS.star", "spec.master"]
37
-
38
- panes = [
39
- {"name": name, "content": f"# {name} content"}
40
- for name in requested_masters
41
- ]
42
-
43
- assert len(panes) == 2, "Dual-pane should have 2 panes"
44
- assert all(p["name"] in requested_masters for p in panes)
45
-
46
- def test_triple_pane_with_sync_scroll(self):
47
- """
48
- Scenario: Triple-pane with sync scroll
49
- WHEN a user requests `GET /?master1=A.star&master2=B.star&master3=C.star&sync=true`
50
- THEN it SHALL display three panes
51
- AND scrolling one pane SHALL sync scroll the others
52
- """
53
- requested_masters = ["A.star", "B.star", "C.star"]
54
- sync_enabled = True
55
-
56
- panes = [
57
- {"name": name, "content": f"# {name} content", "sync_scroll": sync_enabled}
58
- for name in requested_masters
59
- ]
60
-
61
- assert len(panes) == 3, "Triple-pane should have 3 panes"
62
- assert all(p.get("sync_scroll") for p in panes), "All panes should have sync scroll enabled"
63
-
64
- def test_edit_mode_toggle(self, temp_dir):
65
- """
66
- Scenario: Edit mode toggle
67
- WHEN a user clicks the "✏️ Edit Mode" button
68
- THEN textareas SHALL become editable
69
- AND save buttons SHALL appear for each pane
70
- """
71
- # Simulate edit mode toggle
72
- edit_mode = True
73
-
74
- pane = {
75
- "name": "test.star",
76
- "content": "# Original",
77
- "editable": edit_mode,
78
- "dirty": False
79
- }
80
-
81
- assert pane["editable"], "Pane should be editable in edit mode"
82
-
83
- # Simulate edit
84
- pane["content"] = "# Modified"
85
- pane["dirty"] = True
86
-
87
- assert pane["dirty"], "Pane should be marked as dirty after edit"
88
-
89
- def test_safe_file_saving_with_backups(self, temp_dir):
90
- """
91
- Scenario: Safe file saving
92
- WHEN a user saves changes in edit mode
93
- THEN it SHALL create a backup in `.backups/` before writing
94
- AND it SHALL use atomic write (temp file + rename)
95
- """
96
- test_file = temp_dir / "test.star"
97
- original_content = "# Original content"
98
- test_file.write_text(original_content)
99
-
100
- # Create backup directory
101
- backup_dir = temp_dir / ".backups"
102
- backup_dir.mkdir(exist_ok=True)
103
-
104
- # Simulate safe save
105
- new_content = "# Modified content"
106
- self._safe_save_file(test_file, new_content, backup_dir)
107
-
108
- # Verify backup created (backup files are named like "test.star.0")
109
- backup_files = list(backup_dir.glob(f"{test_file.name}.*"))
110
- assert len(backup_files) > 0, f"Backup should be created in {backup_dir}"
111
-
112
- # Verify new content written
113
- assert test_file.read_text() == new_content, "File should have new content"
114
-
115
- # Verify backup has original content
116
- backup_content = backup_files[0].read_text()
117
- assert backup_content == original_content, "Backup should have original content"
118
-
119
- def test_conflict_detection(self, temp_dir):
120
- """
121
- Scenario: Conflict detection
122
- WHEN a user attempts to save but the file was modified on disk since loading
123
- THEN it SHALL return `409 Conflict` with current file hash
124
- AND it SHALL ask user to refresh and retry
125
- """
126
- test_file = temp_dir / "test.star"
127
- original_content = "# Version 1"
128
- test_file.write_text(original_content)
129
-
130
- # Load file and compute hash
131
- loaded_content = test_file.read_text()
132
- loaded_hash = hashlib.sha256(loaded_content.encode()).hexdigest()
133
-
134
- # Simulate external modification
135
- test_file.write_text("# Version 2 (external change)")
136
-
137
- # Try to save with old hash
138
- current_content = test_file.read_text()
139
- current_hash = hashlib.sha256(current_content.encode()).hexdigest()
140
-
141
- # Hash mismatch = conflict
142
- assert loaded_hash != current_hash, "Should detect conflict (hash mismatch)"
143
-
144
- def _safe_save_file(self, path: Path, content: str, backup_dir: Path):
145
- """Simulate safe file save with backup."""
146
- import tempfile
147
- import shutil
148
-
149
- # Create backup
150
- if path.exists():
151
- backup_path = backup_dir / f"{path.name}.{len(list(backup_dir.glob('*')))}"
152
- shutil.copy2(path, backup_path)
153
-
154
- # Atomic write using temp file
155
- temp_fd, temp_path = tempfile.mkstemp(dir=path.parent)
156
- try:
157
- with os.fdopen(temp_fd, 'w') as f:
158
- f.write(content)
159
- os.replace(temp_path, path)
160
- except Exception:
161
- os.unlink(temp_path)
162
- raise
@@ -1,89 +0,0 @@
1
- """
2
- Tests for daemon focus mode compliance.
3
- Tests that discovery respects focus mode stack restrictions.
4
- """
5
-
6
- import pytest
7
- from pathlib import Path
8
- import json
9
-
10
-
11
- @pytest.mark.daemon
12
- class TestDaemonFocusMode:
13
- """Tests for focus mode compliance."""
14
-
15
- def test_focus_mode_restricts_discovery(self, temp_dir):
16
- """
17
- Scenario: Focus mode restricts discovery
18
- WHEN `--focus identity` is enabled and a new resource appears in `services/product/billing/`
19
- THEN the daemon SHALL NOT trigger registration (queue it for later)
20
- AND it SHALL log "⏳ Resource queued (focus mode)"
21
- """
22
- # Simulate focus mode config
23
- focus_config = {
24
- "enabled": True,
25
- "stacks": ["identity", "order"],
26
- "excluded_paths": []
27
- }
28
-
29
- # Resource outside focus
30
- resource_stack = "billing"
31
- is_in_focus = resource_stack in focus_config["stacks"]
32
-
33
- assert not is_in_focus, "billing should not be in focus mode"
34
-
35
- # In real daemon, this would queue instead of registering
36
- # For test, verify the filtering logic works
37
- should_register = not focus_config["enabled"] or is_in_focus
38
- assert not should_register, "Resource outside focus should not be registered immediately"
39
-
40
- def test_focus_mode_allows_matching_resources(self, temp_dir):
41
- """
42
- Scenario: Focus mode allows matching resources
43
- WHEN `--focus identity` is enabled and a new resource appears in `services/product/identity/`
44
- THEN the daemon SHALL trigger registration normally
45
- """
46
- # Create resource in focus stack
47
- focus_config = {
48
- "enabled": True,
49
- "stacks": ["identity", "order"],
50
- "excluded_paths": []
51
- }
52
-
53
- resource_stack = "identity"
54
- is_in_focus = resource_stack in focus_config["stacks"]
55
-
56
- assert is_in_focus, "identity should be in focus mode"
57
-
58
- # In focus - should register
59
- should_register = not focus_config["enabled"] or is_in_focus
60
- assert should_register, "Resource in focus should be registered"
61
-
62
- def test_focus_mode_disabled_allows_all(self):
63
- """Test that when focus mode is disabled, all resources are registered."""
64
- focus_config = {
65
- "enabled": False,
66
- "stacks": ["identity"],
67
- "excluded_paths": []
68
- }
69
-
70
- resource_stack = "billing"
71
- is_in_focus = resource_stack in focus_config["stacks"]
72
-
73
- # Focus disabled - should register regardless
74
- should_register = not focus_config["enabled"] or is_in_focus
75
- assert should_register, "When focus mode disabled, all resources should register"
76
-
77
- def test_focus_mode_stack_matching(self):
78
- """Test stack matching logic for focus mode."""
79
- test_cases = [
80
- ({"enabled": True, "stacks": ["identity"]}, "identity", True),
81
- ({"enabled": True, "stacks": ["identity"]}, "billing", False),
82
- ({"enabled": True, "stacks": ["identity", "order"]}, "order", True),
83
- ({"enabled": False, "stacks": ["identity"]}, "billing", True),
84
- ]
85
-
86
- for config, stack, expected in test_cases:
87
- is_in_focus = stack in config["stacks"]
88
- should_register = not config["enabled"] or is_in_focus
89
- assert should_register == expected, f"Failed for {stack} with config {config}"
@@ -1,122 +0,0 @@
1
- """
2
- Tests for discovery daemon polling behavior.
3
- Tests the continuous monitoring and polling intervals.
4
- """
5
-
6
- import asyncio
7
- import pytest
8
- from pathlib import Path
9
- from unittest.mock import Mock, patch, MagicMock
10
-
11
-
12
- @pytest.mark.daemon
13
- class TestDaemonPolling:
14
- """Tests for daemon polling functionality."""
15
-
16
- @pytest.mark.asyncio
17
- async def test_daemon_polls_at_configured_interval(self):
18
- """
19
- Scenario: Daemon polls at configured interval
20
- WHEN the daemon starts with `DISCOVERY_SCAN_INTERVAL=2`
21
- THEN it SHALL call the scanner function every 2 seconds
22
- """
23
- mock_scanner = Mock(return_value=[])
24
-
25
- # Mock the daemon loop to run only 3 iterations
26
- call_count = 0
27
- async def mock_daemon_loop():
28
- nonlocal call_count
29
- for _ in range(3):
30
- mock_scanner()
31
- call_count += 1
32
- await asyncio.sleep(0.1) # Fast sleep for testing
33
-
34
- # Run the mock daemon
35
- await mock_daemon_loop()
36
-
37
- assert call_count == 3, f"Expected 3 polling calls, got {call_count}"
38
- assert mock_scanner.call_count == 3
39
-
40
- @pytest.mark.asyncio
41
- async def test_daemon_stops_cleanly_on_signal(self):
42
- """
43
- Scenario: Daemon can be stopped
44
- WHEN the daemon receives a stop signal
45
- THEN it SHALL cease polling and exit cleanly within 1 second
46
- """
47
- stop_event = asyncio.Event()
48
- poll_count = [0] # Use list to allow mutation in nested function
49
-
50
- async def polling_loop():
51
- while not stop_event.is_set():
52
- poll_count[0] += 1
53
- try:
54
- await asyncio.wait_for(stop_event.wait(), timeout=0.1)
55
- except asyncio.TimeoutError:
56
- pass
57
-
58
- # Start polling
59
- task = asyncio.create_task(polling_loop())
60
-
61
- # Let it poll a few times
62
- await asyncio.sleep(0.25)
63
-
64
- # Signal stop
65
- stop_event.set()
66
-
67
- # Wait for clean exit with timeout
68
- try:
69
- await asyncio.wait_for(task, timeout=1.0)
70
- except asyncio.TimeoutError:
71
- task.cancel()
72
-
73
- assert poll_count[0] >= 2, "Should have polled at least twice"
74
- assert task.done(), "Task should be completed"
75
-
76
- def test_polling_respects_interval_setting(self):
77
- """Test that the daemon respects DISCOVERY_SCAN_INTERVAL."""
78
- import os
79
-
80
- # Default should be 5 seconds
81
- interval = int(os.environ.get("DISCOVERY_SCAN_INTERVAL", "5"))
82
-
83
- assert interval > 0, "Interval should be positive"
84
- assert interval <= 60, "Interval should be reasonable (<= 60s)"
85
-
86
- @pytest.mark.asyncio
87
- async def test_polling_detects_changes_over_time(self, temp_dir):
88
- """Test that daemon detects changes across multiple polling cycles."""
89
- from pathlib import Path
90
- import json
91
-
92
- # Create initial service
93
- services_dir = temp_dir / "services" / "product"
94
- services_dir.mkdir(parents=True)
95
-
96
- resource_dir = services_dir / "initial" / "service"
97
- resource_dir.mkdir(parents=True)
98
- (resource_dir / "service.json").write_text(json.dumps({"name": "initial"}))
99
-
100
- poll_results = []
101
-
102
- async def mock_scan_cycle():
103
- # Simulate scanning
104
- import sys
105
- sys.path.insert(0, str(Path("discovery").resolve()))
106
- from resource_snapshot import get_current_services
107
-
108
- services = get_current_services(str(services_dir))
109
- poll_results.append(len(services))
110
-
111
- # First poll - should find 1 service
112
- await mock_scan_cycle()
113
- assert poll_results[-1] == 1
114
-
115
- # Add new service
116
- new_dir = services_dir / "new" / "service"
117
- new_dir.mkdir(parents=True)
118
- (new_dir / "service.json").write_text(json.dumps({"name": "new"}))
119
-
120
- # Second poll - should find 2 services
121
- await mock_scan_cycle()
122
- assert poll_results[-1] == 2
@@ -1,115 +0,0 @@
1
- """
2
- Tests for daemon auto-registration functionality.
3
- Tests the triggering of Tilt resource creation for new services.
4
- """
5
-
6
- import pytest
7
- from pathlib import Path
8
- from unittest.mock import Mock, patch, call
9
- import json
10
-
11
-
12
- @pytest.mark.daemon
13
- class TestDaemonRegistration:
14
- """Tests for daemon auto-registration."""
15
-
16
- def test_new_resource_triggers_registration(self, temp_dir):
17
- """
18
- Scenario: New service triggers registration
19
- WHEN the daemon detects a new service.json file not in the cache
20
- THEN it SHALL emit a registration event with the service path and metadata
21
- AND the Tilt resource for that service SHALL be created
22
- """
23
- from pathlib import Path
24
- import sys
25
- sys.path.insert(0, str(Path("discovery").resolve()))
26
- from resource_snapshot import diff_snapshots, save_snapshot, load_snapshot
27
-
28
- original_dir = Path.cwd()
29
-
30
- try:
31
- # Set up initial snapshot
32
- services_dir = temp_dir / "services" / "product"
33
- initial_service = services_dir / "existing" / "service"
34
- initial_service.mkdir(parents=True)
35
- (initial_service / "service.json").write_text(json.dumps({"name": "existing"}))
36
-
37
- import os
38
- os.chdir(temp_dir)
39
-
40
- # Save initial snapshot
41
- from resource_snapshot import get_current_services
42
- initial_services = get_current_services("services/product")
43
- save_snapshot(initial_services)
44
-
45
- # Simulate adding new service
46
- new_service = services_dir / "new" / "service"
47
- new_service.mkdir(parents=True)
48
- (new_service / "service.json").write_text(json.dumps({"name": "new"}))
49
-
50
- # Get current services and diff
51
- current_services = get_current_services("services/product")
52
- old_snapshot = load_snapshot()
53
-
54
- added, removed, modified = diff_snapshots(old_snapshot, current_services)
55
-
56
- # Verify new service was detected
57
- assert len(added) == 1, f"Expected 1 new service, got {len(added)}"
58
- assert any("new" in s for s in added), "Should detect the new service"
59
- finally:
60
- os.chdir(original_dir)
61
-
62
- def test_unchanged_services_do_not_trigger(self, temp_dir):
63
- """
64
- Scenario: No registration for unchanged services
65
- WHEN the daemon scans and finds no changes from previous snapshot
66
- THEN it SHALL NOT emit any registration events
67
- """
68
- from pathlib import Path
69
- import sys
70
- import os
71
- sys.path.insert(0, str(Path("discovery").resolve()))
72
- from resource_snapshot import save_snapshot, load_snapshot, diff_snapshots, get_current_services
73
-
74
- original_dir = Path.cwd()
75
-
76
- try:
77
- # Set up services
78
- services_dir = temp_dir / "services" / "product"
79
- resource_dir = services_dir / "stable" / "service"
80
- resource_dir.mkdir(parents=True)
81
- (resource_dir / "service.json").write_text(json.dumps({"name": "stable"}))
82
-
83
- os.chdir(temp_dir)
84
-
85
- # Save snapshot
86
- services = get_current_services("services/product")
87
- save_snapshot(services)
88
-
89
- # Scan again (no changes)
90
- current_services = get_current_services("services/product")
91
- old_snapshot = load_snapshot()
92
-
93
- added, removed, modified = diff_snapshots(old_snapshot, current_services)
94
-
95
- # Verify no changes detected
96
- assert len(added) == 0, "Should have no added services"
97
- assert len(removed) == 0, "Should have no removed services"
98
- assert len(modified) == 0, "Should have no modified services"
99
- finally:
100
- os.chdir(original_dir)
101
-
102
- def test_registration_includes_resource_metadata(self):
103
- """Test that registration events include full service metadata."""
104
- mock_registration_event = {
105
- "path": "services/product/test/service.json",
106
- "name": "test-service",
107
- "type": "backend",
108
- "stack": "test",
109
- "port": 4000
110
- }
111
-
112
- assert "path" in mock_registration_event
113
- assert "name" in mock_registration_event
114
- assert "type" in mock_registration_event
115
- assert "port" in mock_registration_event
@@ -1,107 +0,0 @@
1
- """
2
- Tests for daemon service validation.
3
- Tests that invalid service.json files are rejected before registration.
4
- """
5
-
6
- import pytest
7
- import json
8
- from pathlib import Path
9
-
10
-
11
- @pytest.mark.daemon
12
- class TestDaemonValidation:
13
- """Tests for service validation."""
14
-
15
- def test_invalid_resource_json_rejected(self):
16
- """
17
- Scenario: Invalid service.json rejected
18
- WHEN a new service.json file has missing required fields (e.g., no `name`)
19
- THEN the daemon SHALL log "❌ Invalid service.json at {path}"
20
- AND it SHALL NOT attempt registration
21
- """
22
- # Invalid service - missing required fields
23
- invalid_service = {
24
- "type": "backend",
25
- "port": 4000
26
- # Missing: name, domain, path
27
- }
28
-
29
- # Validate required fields
30
- required_fields = ["name", "type", "domain", "path"]
31
- missing_fields = [f for f in required_fields if f not in invalid_service]
32
-
33
- assert len(missing_fields) > 0, "Should detect missing fields"
34
- assert "name" in missing_fields, "Should detect missing 'name' field"
35
-
36
- # In real daemon, this would be rejected
37
- is_valid = len(missing_fields) == 0
38
- assert not is_valid, "Invalid service should be rejected"
39
-
40
- def test_valid_resource_json_accepted(self):
41
- """
42
- Scenario: Valid service.json accepted
43
- WHEN a new service.json file has all required fields (`name`, `type`, `domain`, `port`)
44
- THEN the daemon SHALL proceed with registration
45
- """
46
- # Valid service with all required fields
47
- valid_service = {
48
- "name": "test-service",
49
- "type": "backend",
50
- "stack": "test",
51
- "port": 4000,
52
- "path": "services/product/test/test-service"
53
- }
54
-
55
- required_fields = ["appName", "appType", "stack", "path"]
56
- missing_fields = [f for f in required_fields if f not in valid_service]
57
-
58
- is_valid = len(missing_fields) == 0
59
- assert is_valid, "Valid service should be accepted"
60
-
61
- def test_validation_detects_port_range(self):
62
- """Test that port is validated to be in reasonable range."""
63
- test_cases = [
64
- ({"appName": "test", "appType": "backend", "stack": "test", "path": "p", "port": 3000}, True),
65
- ({"appName": "test", "appType": "backend", "stack": "test", "path": "p", "port": 9999}, True),
66
- ({"appName": "test", "appType": "backend", "stack": "test", "path": "p", "port": 80}, False), # Too low
67
- ({"appName": "test", "appType": "backend", "stack": "test", "path": "p", "port": 100000}, False), # Too high
68
- ]
69
-
70
- for service, expected_valid in test_cases:
71
- port = service.get("port", 0)
72
- is_valid = 3000 <= port <= 9999
73
- assert is_valid == expected_valid, f"Port {port} validation failed"
74
-
75
- def test_validation_detects_invalid_type(self):
76
- """Test that appType is validated against allowed values."""
77
- valid_types = ["backend", "frontend", "library", "migrator", "sdk", "worker"]
78
-
79
- test_cases = [
80
- ("backend", True),
81
- ("frontend", True),
82
- ("microservice", False), # Invalid type
83
- ("api", False), # Invalid type
84
- ]
85
-
86
- for app_type, expected_valid in test_cases:
87
- is_valid = app_type in valid_types
88
- assert is_valid == expected_valid, f"Type '{app_type}' validation failed"
89
-
90
- def test_validation_allows_optional_fields(self):
91
- """Test that optional fields don't cause validation failure."""
92
- resource_with_optional = {
93
- "name": "test-service",
94
- "type": "backend",
95
- "stack": "test",
96
- "port": 4000,
97
- "path": "services/product/test/test-service",
98
- # Optional fields
99
- "features": ["prisma", "nats"],
100
- "replicas": 2,
101
- "healthCheck": True
102
- }
103
-
104
- required_fields = ["name", "type", "domain", "path"]
105
- has_all_required = all(f in resource_with_optional for f in required_fields)
106
-
107
- assert has_all_required, "Service with optional fields should still be valid"