@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.
- package/CHANGELOG.md +9 -0
- package/README.md +1 -1
- package/cli/dist/commands/doctor.js +21 -3
- package/cli/dist/commands/upgrade.js +7 -7
- package/cli/dist/generator/extension-fetch.js +16 -9
- package/cli/dist/utils/spinner.js +39 -0
- package/cli/package.json +1 -2
- package/package.json +16 -2
- package/.claude/skills/layer-autoresearch/SKILL.md +0 -48
- package/.claude/skills/tdk-troubleshoot/SKILL.md +0 -222
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -40
- package/.github/ISSUE_TEMPLATE/config.yml +0 -11
- package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -18
- package/.github/ISSUE_TEMPLATE/premium_license.yml +0 -43
- package/.github/dependabot.yml +0 -33
- package/.github/pull_request_template.md +0 -5
- package/.github/workflows/ci.yml +0 -200
- package/.github/workflows/release-binaries.yml +0 -139
- package/.github/zizmor.yml +0 -9
- package/.pre-commit-config.yaml +0 -57
- package/CODE_OF_CONDUCT.md +0 -9
- package/CONTRIBUTING.md +0 -42
- package/Makefile +0 -92
- package/SECURITY.md +0 -17
- package/benchmarks/results/container-scale-2026-09-25T20-54-49-736Z.json +0 -45
- package/benchmarks/results/container-scale-2026-09-25T21-01-20-540Z.json +0 -150
- package/benchmarks/results/container-scale-2026-09-25T21-15-01-441Z.json +0 -73
- package/benchmarks/results/container-scale-2026-09-25T22-09-01-630Z.json +0 -77
- package/benchmarks/results/container-scale-2026-09-25T22-18-28-371Z.json +0 -202
- package/cli/AGENTS.md +0 -390
- package/cli/DESIGN.md +0 -735
- package/cli/README.md +0 -292
- package/cli/biome.json +0 -40
- package/cli/dependency-graph.svg +0 -1135
- package/cli/dist/cli.d.ts +0 -3
- package/cli/dist/cli.d.ts.map +0 -1
- package/cli/dist/cli.js.map +0 -1
- package/cli/dist/commands/completion.d.ts +0 -3
- package/cli/dist/commands/completion.d.ts.map +0 -1
- package/cli/dist/commands/completion.js.map +0 -1
- package/cli/dist/commands/config.d.ts +0 -3
- package/cli/dist/commands/config.d.ts.map +0 -1
- package/cli/dist/commands/config.js.map +0 -1
- package/cli/dist/commands/doctor.d.ts +0 -19
- package/cli/dist/commands/doctor.d.ts.map +0 -1
- package/cli/dist/commands/doctor.js.map +0 -1
- package/cli/dist/commands/down.d.ts +0 -3
- package/cli/dist/commands/down.d.ts.map +0 -1
- package/cli/dist/commands/down.js.map +0 -1
- package/cli/dist/commands/help.d.ts +0 -2
- package/cli/dist/commands/help.d.ts.map +0 -1
- package/cli/dist/commands/help.js.map +0 -1
- package/cli/dist/commands/networks.d.ts +0 -3
- package/cli/dist/commands/networks.d.ts.map +0 -1
- package/cli/dist/commands/networks.js.map +0 -1
- package/cli/dist/commands/project.d.ts +0 -9
- package/cli/dist/commands/project.d.ts.map +0 -1
- package/cli/dist/commands/project.js.map +0 -1
- package/cli/dist/commands/projects.d.ts +0 -3
- package/cli/dist/commands/projects.d.ts.map +0 -1
- package/cli/dist/commands/projects.js.map +0 -1
- package/cli/dist/commands/resource.d.ts +0 -69
- package/cli/dist/commands/resource.d.ts.map +0 -1
- package/cli/dist/commands/resource.js.map +0 -1
- package/cli/dist/commands/resources.d.ts +0 -3
- package/cli/dist/commands/resources.d.ts.map +0 -1
- package/cli/dist/commands/resources.js.map +0 -1
- package/cli/dist/commands/stack.d.ts +0 -3
- package/cli/dist/commands/stack.d.ts.map +0 -1
- package/cli/dist/commands/stack.js.map +0 -1
- package/cli/dist/commands/stacks.d.ts +0 -3
- package/cli/dist/commands/stacks.d.ts.map +0 -1
- package/cli/dist/commands/stacks.js.map +0 -1
- package/cli/dist/commands/status.d.ts +0 -3
- package/cli/dist/commands/status.d.ts.map +0 -1
- package/cli/dist/commands/status.js.map +0 -1
- package/cli/dist/commands/ui.d.ts +0 -3
- package/cli/dist/commands/ui.d.ts.map +0 -1
- package/cli/dist/commands/ui.js.map +0 -1
- package/cli/dist/commands/up.d.ts +0 -3
- package/cli/dist/commands/up.d.ts.map +0 -1
- package/cli/dist/commands/up.js.map +0 -1
- package/cli/dist/commands/upgrade.d.ts +0 -14
- package/cli/dist/commands/upgrade.d.ts.map +0 -1
- package/cli/dist/commands/upgrade.js.map +0 -1
- package/cli/dist/commands/version.d.ts +0 -3
- package/cli/dist/commands/version.d.ts.map +0 -1
- package/cli/dist/commands/version.js.map +0 -1
- package/cli/dist/components/Accessible.d.ts +0 -8
- package/cli/dist/components/Accessible.d.ts.map +0 -1
- package/cli/dist/components/Accessible.js.map +0 -1
- package/cli/dist/components/BaseTooltip.d.ts +0 -4
- package/cli/dist/components/BaseTooltip.d.ts.map +0 -1
- package/cli/dist/components/BaseTooltip.js.map +0 -1
- package/cli/dist/components/DetailPanel.d.ts +0 -4
- package/cli/dist/components/DetailPanel.d.ts.map +0 -1
- package/cli/dist/components/DetailPanel.js.map +0 -1
- package/cli/dist/components/FileTree.d.ts +0 -4
- package/cli/dist/components/FileTree.d.ts.map +0 -1
- package/cli/dist/components/FileTree.js.map +0 -1
- package/cli/dist/components/ResourceSelectInput.d.ts +0 -4
- package/cli/dist/components/ResourceSelectInput.d.ts.map +0 -1
- package/cli/dist/components/ResourceSelectInput.js.map +0 -1
- package/cli/dist/components/ResourceTable.d.ts +0 -4
- package/cli/dist/components/ResourceTable.d.ts.map +0 -1
- package/cli/dist/components/ResourceTable.js.map +0 -1
- package/cli/dist/components/TabBar.d.ts +0 -4
- package/cli/dist/components/TabBar.d.ts.map +0 -1
- package/cli/dist/components/TabBar.js.map +0 -1
- package/cli/dist/components/Tooltip.d.ts +0 -12
- package/cli/dist/components/Tooltip.d.ts.map +0 -1
- package/cli/dist/components/Tooltip.js.map +0 -1
- package/cli/dist/components/index.d.ts +0 -8
- package/cli/dist/components/index.d.ts.map +0 -1
- package/cli/dist/components/index.js.map +0 -1
- package/cli/dist/config/platform-standards.d.ts +0 -159
- package/cli/dist/config/platform-standards.d.ts.map +0 -1
- package/cli/dist/config/platform-standards.js.map +0 -1
- package/cli/dist/generator/extension-fetch.d.ts +0 -25
- package/cli/dist/generator/extension-fetch.d.ts.map +0 -1
- package/cli/dist/generator/extension-fetch.js.map +0 -1
- package/cli/dist/generator/template-engine.d.ts +0 -62
- package/cli/dist/generator/template-engine.d.ts.map +0 -1
- package/cli/dist/generator/template-engine.js.map +0 -1
- package/cli/dist/index.d.ts +0 -11
- package/cli/dist/index.d.ts.map +0 -1
- package/cli/dist/index.js.map +0 -1
- package/cli/dist/types/index.d.ts +0 -257
- package/cli/dist/types/index.d.ts.map +0 -1
- package/cli/dist/types/index.js.map +0 -1
- package/cli/dist/utils/cache.d.ts +0 -19
- package/cli/dist/utils/cache.d.ts.map +0 -1
- package/cli/dist/utils/cache.js.map +0 -1
- package/cli/dist/utils/command-helpers.d.ts +0 -17
- package/cli/dist/utils/command-helpers.d.ts.map +0 -1
- package/cli/dist/utils/command-helpers.js.map +0 -1
- package/cli/dist/utils/constants.d.ts +0 -53
- package/cli/dist/utils/constants.d.ts.map +0 -1
- package/cli/dist/utils/constants.js.map +0 -1
- package/cli/dist/utils/discovery-context.d.ts +0 -4
- package/cli/dist/utils/discovery-context.d.ts.map +0 -1
- package/cli/dist/utils/discovery-context.js.map +0 -1
- package/cli/dist/utils/docker.d.ts +0 -4
- package/cli/dist/utils/docker.d.ts.map +0 -1
- package/cli/dist/utils/docker.js.map +0 -1
- package/cli/dist/utils/doctor-runtime.d.ts +0 -81
- package/cli/dist/utils/doctor-runtime.d.ts.map +0 -1
- package/cli/dist/utils/doctor-runtime.js.map +0 -1
- package/cli/dist/utils/env-validator.d.ts +0 -15
- package/cli/dist/utils/env-validator.d.ts.map +0 -1
- package/cli/dist/utils/env-validator.js.map +0 -1
- package/cli/dist/utils/errors.d.ts +0 -31
- package/cli/dist/utils/errors.d.ts.map +0 -1
- package/cli/dist/utils/errors.js.map +0 -1
- package/cli/dist/utils/file-helpers.d.ts +0 -14
- package/cli/dist/utils/file-helpers.d.ts.map +0 -1
- package/cli/dist/utils/file-helpers.js.map +0 -1
- package/cli/dist/utils/formatting.d.ts +0 -30
- package/cli/dist/utils/formatting.d.ts.map +0 -1
- package/cli/dist/utils/formatting.js.map +0 -1
- package/cli/dist/utils/paths.d.ts +0 -3
- package/cli/dist/utils/paths.d.ts.map +0 -1
- package/cli/dist/utils/paths.js.map +0 -1
- package/cli/dist/utils/port-assignment.d.ts +0 -6
- package/cli/dist/utils/port-assignment.d.ts.map +0 -1
- package/cli/dist/utils/port-assignment.js.map +0 -1
- package/cli/dist/utils/project-features.d.ts +0 -23
- package/cli/dist/utils/project-features.d.ts.map +0 -1
- package/cli/dist/utils/project-features.js.map +0 -1
- package/cli/dist/utils/project-templates.d.ts +0 -7
- package/cli/dist/utils/project-templates.d.ts.map +0 -1
- package/cli/dist/utils/project-templates.js.map +0 -1
- package/cli/dist/utils/prompt.d.ts +0 -28
- package/cli/dist/utils/prompt.d.ts.map +0 -1
- package/cli/dist/utils/prompt.js.map +0 -1
- package/cli/dist/utils/resource-features.d.ts +0 -29
- package/cli/dist/utils/resource-features.d.ts.map +0 -1
- package/cli/dist/utils/resource-features.js.map +0 -1
- package/cli/dist/utils/service-urls.d.ts +0 -30
- package/cli/dist/utils/service-urls.d.ts.map +0 -1
- package/cli/dist/utils/service-urls.js.map +0 -1
- package/cli/dist/utils/services.d.ts +0 -18
- package/cli/dist/utils/services.d.ts.map +0 -1
- package/cli/dist/utils/services.js.map +0 -1
- package/cli/dist/utils/stack-features.d.ts +0 -22
- package/cli/dist/utils/stack-features.d.ts.map +0 -1
- package/cli/dist/utils/stack-features.js.map +0 -1
- package/cli/dist/utils/tar.d.ts +0 -7
- package/cli/dist/utils/tar.d.ts.map +0 -1
- package/cli/dist/utils/tar.js.map +0 -1
- package/cli/dist/utils/tilt.d.ts +0 -20
- package/cli/dist/utils/tilt.d.ts.map +0 -1
- package/cli/dist/utils/tilt.js.map +0 -1
- package/cli/dist/utils/validation.d.ts +0 -16
- package/cli/dist/utils/validation.d.ts.map +0 -1
- package/cli/dist/utils/validation.js.map +0 -1
- package/cli/knip.json +0 -6
- package/cli/pnpm-lock.yaml +0 -2305
- package/cli/pnpm-workspace.yaml +0 -2
- package/cli/src/cli.ts +0 -72
- package/cli/src/commands/__tests__/always-enabled-infra.test.ts +0 -109
- package/cli/src/commands/__tests__/config.test.ts +0 -146
- package/cli/src/commands/__tests__/doctor.test.ts +0 -730
- package/cli/src/commands/__tests__/error-handling.test.ts +0 -78
- package/cli/src/commands/__tests__/phases-model.test.ts +0 -161
- package/cli/src/commands/__tests__/project-resource-features-e2e.test.ts +0 -187
- package/cli/src/commands/__tests__/project.test.ts +0 -68
- package/cli/src/commands/__tests__/resource.test.ts +0 -226
- package/cli/src/commands/__tests__/saas-starter-integration.test.ts +0 -194
- package/cli/src/commands/__tests__/stack-features-e2e.test.ts +0 -135
- package/cli/src/commands/__tests__/upgrade.test.ts +0 -198
- package/cli/src/commands/completion.ts +0 -300
- package/cli/src/commands/config.ts +0 -299
- package/cli/src/commands/doctor.ts +0 -926
- package/cli/src/commands/down.ts +0 -37
- package/cli/src/commands/help.ts +0 -143
- package/cli/src/commands/networks-design.md +0 -80
- package/cli/src/commands/networks.ts +0 -332
- package/cli/src/commands/project.ts +0 -456
- package/cli/src/commands/projects.ts +0 -82
- package/cli/src/commands/resource.ts +0 -652
- package/cli/src/commands/resources.ts +0 -95
- package/cli/src/commands/stack.ts +0 -128
- package/cli/src/commands/stacks.ts +0 -52
- package/cli/src/commands/status.ts +0 -88
- package/cli/src/commands/ui.tsx +0 -843
- package/cli/src/commands/up.ts +0 -169
- package/cli/src/commands/upgrade.ts +0 -628
- package/cli/src/commands/version.ts +0 -9
- package/cli/src/components/Accessible.tsx +0 -21
- package/cli/src/components/BaseTooltip.tsx +0 -66
- package/cli/src/components/DetailPanel.tsx +0 -146
- package/cli/src/components/FileTree.tsx +0 -89
- package/cli/src/components/ResourceSelectInput.tsx +0 -30
- package/cli/src/components/ResourceTable.tsx +0 -78
- package/cli/src/components/TabBar.tsx +0 -53
- package/cli/src/components/Tooltip.tsx +0 -11
- package/cli/src/components/index.ts +0 -7
- package/cli/src/config/platform-standards.test.ts +0 -11
- package/cli/src/config/platform-standards.ts +0 -196
- package/cli/src/generator/__tests__/extension-fetch.test.ts +0 -242
- package/cli/src/generator/__tests__/template-engine.test.ts +0 -70
- package/cli/src/generator/extension-fetch.ts +0 -286
- package/cli/src/generator/template-engine.ts +0 -752
- package/cli/src/index.ts +0 -86
- package/cli/src/templates.d.ts +0 -4
- package/cli/src/types/index.ts +0 -353
- package/cli/src/utils/__tests__/cache.test.ts +0 -98
- package/cli/src/utils/__tests__/formatting.test.ts +0 -170
- package/cli/src/utils/__tests__/paths.test.ts +0 -180
- package/cli/src/utils/__tests__/port-assignment.test.ts +0 -121
- package/cli/src/utils/__tests__/service-urls.test.ts +0 -174
- package/cli/src/utils/__tests__/services.test.ts +0 -531
- package/cli/src/utils/__tests__/tilt.test.ts +0 -172
- package/cli/src/utils/__tests__/validation.test.ts +0 -148
- package/cli/src/utils/cache.ts +0 -76
- package/cli/src/utils/command-helpers.ts +0 -54
- package/cli/src/utils/constants.ts +0 -130
- package/cli/src/utils/discovery-context.ts +0 -49
- package/cli/src/utils/docker.ts +0 -20
- package/cli/src/utils/doctor-runtime.ts +0 -644
- package/cli/src/utils/env-validator.ts +0 -139
- package/cli/src/utils/errors.ts +0 -168
- package/cli/src/utils/file-helpers.ts +0 -62
- package/cli/src/utils/formatting.ts +0 -215
- package/cli/src/utils/paths.ts +0 -53
- package/cli/src/utils/port-assignment.ts +0 -106
- package/cli/src/utils/project-features.ts +0 -118
- package/cli/src/utils/project-templates.ts +0 -29
- package/cli/src/utils/prompt.ts +0 -128
- package/cli/src/utils/resource-features.ts +0 -215
- package/cli/src/utils/service-urls.ts +0 -124
- package/cli/src/utils/services.ts +0 -364
- package/cli/src/utils/stack-features.ts +0 -30
- package/cli/src/utils/tar.ts +0 -24
- package/cli/src/utils/tilt.ts +0 -133
- package/cli/src/utils/validation.ts +0 -67
- package/cli/tsconfig.json +0 -25
- package/cli/tsconfig.typecheck.json +0 -8
- package/docs/FEATURES.md +0 -281
- package/docs/demo.svg +0 -217
- package/engine/docs/AUTODISCOVERY_TEST.md +0 -182
- package/engine/docs/C4-ARCHITECTURE-operations.md +0 -396
- package/engine/docs/C4-ARCHITECTURE-overview.md +0 -284
- package/engine/docs/C4-ARCHITECTURE.md +0 -17
- package/engine/docs/GOLDEN_IMAGE_INTEGRATION.md +0 -349
- package/engine/docs/MANIFEST_DRIVEN_ARCHITECTURE.md +0 -357
- package/engine/docs/README.md +0 -284
- package/install.sh +0 -19
- package/knip.json +0 -10
- package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/.openspec.yaml +0 -2
- package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/design.md +0 -102
- package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/proposal.md +0 -31
- package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/specs/vscode-tdk-notifications/spec.md +0 -48
- package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/specs/vscode-tdk-orchestration/spec.md +0 -63
- package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/specs/vscode-tdk-troubleshooting/spec.md +0 -56
- package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/tasks.md +0 -61
- package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/.openspec.yaml +0 -2
- package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/design.md +0 -114
- package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/proposal.md +0 -32
- package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/specs/manifest-field-migration/spec.md +0 -20
- package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/specs/resource-terminology-standard/spec.md +0 -20
- package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/specs/stack-terminology-standard/spec.md +0 -20
- package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/tasks.md +0 -194
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/.openspec.yaml +0 -2
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/design.md +0 -111
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/proposal.md +0 -33
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/function-naming-alignment/spec.md +0 -12
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/optional-parameter-patterns/spec.md +0 -18
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/parameter-documentation/spec.md +0 -16
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/parameter-naming-consistency/spec.md +0 -12
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/parameter-ordering-standard/spec.md +0 -12
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/tasks.md +0 -194
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/.openspec.yaml +0 -2
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/design.md +0 -84
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/proposal.md +0 -31
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/codebase-audit/spec.md +0 -27
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/dead-code-cleanup/spec.md +0 -27
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/test-gap-fill/spec.md +0 -23
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/todo-resolution/spec.md +0 -27
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/tasks.md +0 -39
- package/openspec/changes/archive/2026-06-25-landscape-consolidation/.openspec.yaml +0 -2
- package/openspec/changes/archive/2026-06-25-landscape-consolidation/design.md +0 -80
- package/openspec/changes/archive/2026-06-25-landscape-consolidation/proposal.md +0 -40
- package/openspec/changes/archive/2026-06-25-landscape-consolidation/spec.md +0 -52
- package/openspec/changes/archive/2026-06-25-landscape-consolidation/tasks.md +0 -51
- package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/.openspec.yaml +0 -2
- package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/design.md +0 -43
- package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/proposal.md +0 -29
- package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/specs/self-contained-generated-projects/spec.md +0 -67
- package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/tasks.md +0 -27
- package/openspec/changes/optimize-runtime-docker-layers/.openspec.yaml +0 -3
- package/openspec/changes/optimize-runtime-docker-layers/design.md +0 -81
- package/openspec/changes/optimize-runtime-docker-layers/proposal.md +0 -44
- package/openspec/changes/optimize-runtime-docker-layers/specs/runtime-container-footprint/spec.md +0 -79
- package/openspec/changes/optimize-runtime-docker-layers/tasks.md +0 -36
- package/openspec/changes/prioritized-cold-start/.openspec.yaml +0 -4
- package/openspec/changes/prioritized-cold-start/design.md +0 -137
- package/openspec/changes/prioritized-cold-start/proposal.md +0 -41
- package/openspec/changes/prioritized-cold-start/specs/on-demand-resource-startup/spec.md +0 -98
- package/openspec/changes/prioritized-cold-start/tasks.md +0 -69
- package/openspec/config.yaml +0 -1
- package/openspec/specs/manifest-field-migration/spec.md +0 -24
- package/openspec/specs/resource-terminology-standard/spec.md +0 -24
- package/openspec/specs/self-contained-generated-projects/spec.md +0 -67
- package/openspec/specs/stack-terminology-standard/spec.md +0 -24
- package/platform/services/platform/proxy/service.yaml +0 -14
- package/scripts/audit-codebase.sh +0 -213
- package/scripts/autoresearch/layer-eval.sh +0 -65
- package/scripts/benchmark/README.md +0 -25
- package/scripts/benchmark/container-scale.ts +0 -503
- package/scripts/benchmark/pre-release-gate.sh +0 -9
- package/scripts/install-git-hooks.sh +0 -14
- package/scripts/measure-idle-footprint.sh +0 -58
- package/scripts/record-demo.sh +0 -43
- package/scripts/release-binaries.sh +0 -97
- package/scripts/setup-pre-commit.sh +0 -33
- package/scripts/stage-npm-engine.sh +0 -36
- package/tests/tilt-engine/__init__.py +0 -5
- package/tests/tilt-engine/conftest.py +0 -182
- package/tests/tilt-engine/fixtures/appointment-frontend-service.json +0 -11
- package/tests/tilt-engine/fixtures/identity-backend-service.json +0 -12
- package/tests/tilt-engine/fixtures/invalid-service.json +0 -4
- package/tests/tilt-engine/test_agents_md_generator.py +0 -341
- package/tests/tilt-engine/test_agents_md_integration.py +0 -378
- package/tests/tilt-engine/test_cache_operations.py +0 -181
- package/tests/tilt-engine/test_cache_persistence.py +0 -142
- package/tests/tilt-engine/test_code_executor.py +0 -152
- package/tests/tilt-engine/test_code_viewer.py +0 -127
- package/tests/tilt-engine/test_compose_port_anchors.py +0 -310
- package/tests/tilt-engine/test_config_inspector.py +0 -162
- package/tests/tilt-engine/test_daemon_focus_mode.py +0 -89
- package/tests/tilt-engine/test_daemon_polling.py +0 -122
- package/tests/tilt-engine/test_daemon_registration.py +0 -115
- package/tests/tilt-engine/test_daemon_validation.py +0 -107
- package/tests/tilt-engine/test_docker_generator_bugs.py +0 -493
- package/tests/tilt-engine/test_docker_prune.py +0 -119
- package/tests/tilt-engine/test_dockerignore_path_bug.py +0 -82
- package/tests/tilt-engine/test_file_browser.py +0 -193
- package/tests/tilt-engine/test_frontend_basepath_manifest.py +0 -27
- package/tests/tilt-engine/test_health_dependencies.py +0 -130
- package/tests/tilt-engine/test_health_endpoints.py +0 -118
- package/tests/tilt-engine/test_health_tilt_ui.py +0 -85
- package/tests/tilt-engine/test_runtime_container_footprint.py +0 -162
- package/tests/tilt-engine/test_sablier_defer_start.py +0 -237
- package/tests/tilt-engine/test_safety_aliases.py +0 -84
- package/tests/tilt-engine/test_snapshot_diff.py +0 -136
- package/tests/tilt-engine/test_snapshot_persistence.py +0 -163
- package/tests/tilt-engine/test_snapshot_scanning.py +0 -123
- package/tests/tilt-engine/test_standalone_project_boot.py +0 -61
- package/tests/tilt-engine/test_standalone_traefik.py +0 -160
- package/tests/tilt-engine/test_traefik_static_wake_route.py +0 -187
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Integration test for AGENTS.md generator.
|
|
4
|
-
|
|
5
|
-
This test verifies the generator works by:
|
|
6
|
-
1. Mocking the Starlark environment (Utils, write_fn)
|
|
7
|
-
2. Calling the generator logic with test manifests
|
|
8
|
-
3. Verifying the generated AGENTS.md content
|
|
9
|
-
|
|
10
|
-
Usage:
|
|
11
|
-
python3 tests/tilt-engine/test_agents_md_integration.py
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
import re
|
|
15
|
-
import sys
|
|
16
|
-
from pathlib import Path
|
|
17
|
-
from typing import Dict, Any, List
|
|
18
|
-
|
|
19
|
-
# Add project root to path
|
|
20
|
-
PROJECT_ROOT = Path(__file__).parent.parent.parent
|
|
21
|
-
sys.path.insert(0, str(PROJECT_ROOT))
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class MockUtils:
|
|
25
|
-
"""Mock Utils struct for testing."""
|
|
26
|
-
|
|
27
|
-
@staticmethod
|
|
28
|
-
def get_template_header(template_type: str, generator_name: str, resource_name: str, output_hint: str) -> str:
|
|
29
|
-
return f"# GENERATED BY TDK - {template_type} for {resource_name}\n# Generator: {generator_name}\n# {output_hint}"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class MockFileWriter:
|
|
33
|
-
"""Mock write_fn that captures written files."""
|
|
34
|
-
|
|
35
|
-
def __init__(self):
|
|
36
|
-
self.files: Dict[str, str] = {}
|
|
37
|
-
|
|
38
|
-
def write(self, path: str, content: str) -> None:
|
|
39
|
-
"""Mock write_file function."""
|
|
40
|
-
self.files[path] = content
|
|
41
|
-
print(f" 📝 Mock write: {path}")
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def extract_template_from_generator() -> str:
|
|
45
|
-
"""Extract TEMPLATE_AGENTS_MD from the generator source."""
|
|
46
|
-
generator_path = PROJECT_ROOT / "engine" / "topologies" / "tilt" / "generators" / "agents_md.star"
|
|
47
|
-
content = generator_path.read_text()
|
|
48
|
-
|
|
49
|
-
match = re.search(r'TEMPLATE_AGENTS_MD = """(.*?)"""', content, re.DOTALL)
|
|
50
|
-
if not match:
|
|
51
|
-
raise ValueError("Could not find TEMPLATE_AGENTS_MD in generator")
|
|
52
|
-
|
|
53
|
-
return match.group(1)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def simulate_generate_agents_md(manifest: Dict[str, Any], write_fn=None) -> str:
|
|
57
|
-
"""
|
|
58
|
-
Simulate the generate_agents_md function in Python.
|
|
59
|
-
|
|
60
|
-
This mirrors the logic in agents_md.star but in Python for testing.
|
|
61
|
-
"""
|
|
62
|
-
resource_path = manifest.get('_servicePath', '')
|
|
63
|
-
app_name = manifest.get('appName', 'unknown-service')
|
|
64
|
-
app_type = manifest.get('appType', 'backend')
|
|
65
|
-
|
|
66
|
-
# Get template
|
|
67
|
-
template = extract_template_from_generator()
|
|
68
|
-
|
|
69
|
-
# Generate header
|
|
70
|
-
header = MockUtils.get_template_header(
|
|
71
|
-
'agents_md',
|
|
72
|
-
'AgentsMd.generate()',
|
|
73
|
-
app_name,
|
|
74
|
-
'Output: .autogenerated/AGENTS.md'
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
# Format template
|
|
78
|
-
timestamp = "2026-04-28 12:00:00" # Fixed for testing
|
|
79
|
-
content = template.format(
|
|
80
|
-
header=header,
|
|
81
|
-
resource_name=app_name,
|
|
82
|
-
app_type=app_type,
|
|
83
|
-
timestamp=timestamp,
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
if write_fn:
|
|
87
|
-
output_path = f"{resource_path}/.autogenerated/AGENTS.md"
|
|
88
|
-
write_fn(output_path, content)
|
|
89
|
-
|
|
90
|
-
return content
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def test_backend_service():
|
|
94
|
-
"""Test AGENTS.md generation for a backend service."""
|
|
95
|
-
print("\n" + "=" * 70)
|
|
96
|
-
print("🧪 TEST 1: Backend Service (test-api-backend)")
|
|
97
|
-
print("=" * 70)
|
|
98
|
-
|
|
99
|
-
manifest = {
|
|
100
|
-
"appName": "test-api-backend",
|
|
101
|
-
"appType": "backend",
|
|
102
|
-
"stack": "test",
|
|
103
|
-
"port": 4001,
|
|
104
|
-
"_servicePath": "services/product/test/test-api-backend",
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
writer = MockFileWriter()
|
|
108
|
-
content = simulate_generate_agents_md(manifest, writer.write)
|
|
109
|
-
|
|
110
|
-
# Assertions
|
|
111
|
-
assert "test-api-backend" in content, "Service name should appear"
|
|
112
|
-
assert "backend" in content, "App type should appear"
|
|
113
|
-
assert ".autogenerated/" in content, "Should reference .autogenerated folder"
|
|
114
|
-
|
|
115
|
-
output_path = "services/product/test/test-api-backend/.autogenerated/AGENTS.md"
|
|
116
|
-
assert output_path in writer.files, f"Should write to correct path: {output_path}"
|
|
117
|
-
assert output_path.endswith("AGENTS.md"), "File should be named AGENTS.md"
|
|
118
|
-
|
|
119
|
-
print(f"\n✅ Backend test passed!")
|
|
120
|
-
print(f" Output path: {output_path}")
|
|
121
|
-
print(f" Content length: {len(content)} chars")
|
|
122
|
-
|
|
123
|
-
return True
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
def test_frontend_service():
|
|
127
|
-
"""Test AGENTS.md generation for a frontend service."""
|
|
128
|
-
print("\n" + "=" * 70)
|
|
129
|
-
print("🧪 TEST 2: Frontend Service (test-app-frontend)")
|
|
130
|
-
print("=" * 70)
|
|
131
|
-
|
|
132
|
-
manifest = {
|
|
133
|
-
"appName": "test-app-frontend",
|
|
134
|
-
"appType": "frontend",
|
|
135
|
-
"stack": "test",
|
|
136
|
-
"port": 3001,
|
|
137
|
-
"backendName": "test-api-backend",
|
|
138
|
-
"_servicePath": "services/product/test/test-app-frontend",
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
writer = MockFileWriter()
|
|
142
|
-
content = simulate_generate_agents_md(manifest, writer.write)
|
|
143
|
-
|
|
144
|
-
# Assertions
|
|
145
|
-
assert "test-app-frontend" in content, "Service name should appear"
|
|
146
|
-
assert "frontend" in content, "App type should appear"
|
|
147
|
-
assert "vite.config" in content, "Should mention vite config (relevant for frontend)"
|
|
148
|
-
assert "nginx" in content, "Should mention nginx (relevant for frontend)"
|
|
149
|
-
|
|
150
|
-
output_path = "services/product/test/test-app-frontend/.autogenerated/AGENTS.md"
|
|
151
|
-
assert output_path in writer.files, f"Should write to correct path: {output_path}"
|
|
152
|
-
|
|
153
|
-
print(f"\n✅ Frontend test passed!")
|
|
154
|
-
print(f" Content includes frontend-specific references")
|
|
155
|
-
|
|
156
|
-
return True
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
def test_migrator_service():
|
|
160
|
-
"""Test AGENTS.md generation for a migrator service."""
|
|
161
|
-
print("\n" + "=" * 70)
|
|
162
|
-
print("🧪 TEST 3: Migrator Service (test-db-migrator)")
|
|
163
|
-
print("=" * 70)
|
|
164
|
-
|
|
165
|
-
manifest = {
|
|
166
|
-
"appName": "test-db-migrator",
|
|
167
|
-
"appType": "migrator",
|
|
168
|
-
"stack": "test",
|
|
169
|
-
"port": 7001,
|
|
170
|
-
"_servicePath": "services/product/test/test-db-migrator",
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
writer = MockFileWriter()
|
|
174
|
-
content = simulate_generate_agents_md(manifest, writer.write)
|
|
175
|
-
|
|
176
|
-
assert "test-db-migrator" in content, "Service name should appear"
|
|
177
|
-
assert "migrator" in content or "backend" in content, "App type should appear"
|
|
178
|
-
|
|
179
|
-
output_path = "services/product/test/test-db-migrator/.autogenerated/AGENTS.md"
|
|
180
|
-
assert output_path in writer.files, f"Should write to correct path: {output_path}"
|
|
181
|
-
|
|
182
|
-
print(f"\n✅ Migrator test passed!")
|
|
183
|
-
|
|
184
|
-
return True
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
def test_content_structure():
|
|
188
|
-
"""Test that generated content has all required sections."""
|
|
189
|
-
print("\n" + "=" * 70)
|
|
190
|
-
print("🧪 TEST 4: Content Structure Validation")
|
|
191
|
-
print("=" * 70)
|
|
192
|
-
|
|
193
|
-
manifest = {
|
|
194
|
-
"appName": "structure-test-service",
|
|
195
|
-
"appType": "backend",
|
|
196
|
-
"_servicePath": "services/test",
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
content = simulate_generate_agents_md(manifest)
|
|
200
|
-
|
|
201
|
-
required_sections = [
|
|
202
|
-
("---", "YAML frontmatter start"),
|
|
203
|
-
("title:", "Title field"),
|
|
204
|
-
("status: autogenerated", "Autogenerated status"),
|
|
205
|
-
("# ⚠️ AUTOGENERATED FILES", "Warning header"),
|
|
206
|
-
("## Why This Folder Exists", "Why section"),
|
|
207
|
-
("## What Happens If You Modify Files Here", "Consequences section"),
|
|
208
|
-
("## Where to Make Changes Instead", "Alternatives section"),
|
|
209
|
-
("## How Regeneration Works", "Architecture section"),
|
|
210
|
-
("## For AI Agents", "AI agent section"),
|
|
211
|
-
("## Emergency Override", "Emergency section"),
|
|
212
|
-
("service.json", "References service.json"),
|
|
213
|
-
("package.json", "References package.json"),
|
|
214
|
-
("NEVER", "Critical NEVER instruction"),
|
|
215
|
-
("ALWAYS", "Best practice ALWAYS instruction"),
|
|
216
|
-
("Generator Metadata", "Metadata section"),
|
|
217
|
-
]
|
|
218
|
-
|
|
219
|
-
all_passed = True
|
|
220
|
-
for pattern, description in required_sections:
|
|
221
|
-
if pattern in content:
|
|
222
|
-
print(f" ✅ {description}")
|
|
223
|
-
else:
|
|
224
|
-
print(f" ❌ {description} - missing: '{pattern}'")
|
|
225
|
-
all_passed = False
|
|
226
|
-
|
|
227
|
-
# Verify list of generated files
|
|
228
|
-
generated_files = [
|
|
229
|
-
"vite.config", "tsconfig", "Dockerfile", "nginx",
|
|
230
|
-
".env", "bunfig", ".npmrc", "docker-compose",
|
|
231
|
-
"playwright", "prisma"
|
|
232
|
-
]
|
|
233
|
-
|
|
234
|
-
for file_type in generated_files:
|
|
235
|
-
if file_type in content:
|
|
236
|
-
print(f" ✅ Mentions {file_type}")
|
|
237
|
-
else:
|
|
238
|
-
print(f" ⚠️ Missing mention of {file_type}")
|
|
239
|
-
|
|
240
|
-
return all_passed
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
def test_ai_agent_instructions():
|
|
244
|
-
"""Test that AI agent instructions are clear and present."""
|
|
245
|
-
print("\n" + "=" * 70)
|
|
246
|
-
print("🧪 TEST 5: AI Agent Instructions")
|
|
247
|
-
print("=" * 70)
|
|
248
|
-
|
|
249
|
-
manifest = {
|
|
250
|
-
"appName": "ai-test-service",
|
|
251
|
-
"appType": "backend",
|
|
252
|
-
"_servicePath": "services/ai/test",
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
content = simulate_generate_agents_md(manifest)
|
|
256
|
-
|
|
257
|
-
# Check for AI-specific instructions
|
|
258
|
-
ai_checks = [
|
|
259
|
-
("write()", "References write() function"),
|
|
260
|
-
("edit()", "References edit() function"),
|
|
261
|
-
("skill(", "References skill() function"),
|
|
262
|
-
("CRITICAL INSTRUCTIONS", "Has critical instructions section"),
|
|
263
|
-
("❌", "Has X emoji for wrong way"),
|
|
264
|
-
("✅", "Has checkmark emoji for right way"),
|
|
265
|
-
]
|
|
266
|
-
|
|
267
|
-
all_passed = True
|
|
268
|
-
for pattern, description in ai_checks:
|
|
269
|
-
if pattern in content:
|
|
270
|
-
print(f" ✅ {description}")
|
|
271
|
-
else:
|
|
272
|
-
print(f" ❌ {description} - missing: '{pattern}'")
|
|
273
|
-
all_passed = False
|
|
274
|
-
|
|
275
|
-
return all_passed
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
def test_no_write_fn():
|
|
279
|
-
"""Test that generator works without write_fn (returns content only)."""
|
|
280
|
-
print("\n" + "=" * 70)
|
|
281
|
-
print("🧪 TEST 6: Generator Without write_fn")
|
|
282
|
-
print("=" * 70)
|
|
283
|
-
|
|
284
|
-
manifest = {
|
|
285
|
-
"appName": "no-write-service",
|
|
286
|
-
"appType": "backend",
|
|
287
|
-
"_servicePath": "services/test",
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
# Call without write_fn
|
|
291
|
-
content = simulate_generate_agents_md(manifest, write_fn=None)
|
|
292
|
-
|
|
293
|
-
assert content is not None, "Should return content"
|
|
294
|
-
assert len(content) > 1000, "Content should be substantial"
|
|
295
|
-
assert "no-write-service" in content, "Should include service name"
|
|
296
|
-
|
|
297
|
-
print(" ✅ Returns content without writing when write_fn=None")
|
|
298
|
-
|
|
299
|
-
return True
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
def test_all_services():
|
|
303
|
-
"""Test generation for all service types."""
|
|
304
|
-
print("\n" + "=" * 70)
|
|
305
|
-
print("🧪 TEST 7: All Service Types")
|
|
306
|
-
print("=" * 70)
|
|
307
|
-
|
|
308
|
-
resource_types = ["backend", "frontend", "migrator", "library", "sdk"]
|
|
309
|
-
|
|
310
|
-
for svc_type in resource_types:
|
|
311
|
-
manifest = {
|
|
312
|
-
"appName": f"test-{svc_type}",
|
|
313
|
-
"appType": svc_type,
|
|
314
|
-
"_servicePath": f"services/test/{svc_type}",
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
writer = MockFileWriter()
|
|
318
|
-
content = simulate_generate_agents_md(manifest, writer.write)
|
|
319
|
-
|
|
320
|
-
assert svc_type in content, f"Should include appType: {svc_type}"
|
|
321
|
-
assert f"test-{svc_type}" in content, f"Should include service name"
|
|
322
|
-
print(f" ✅ {svc_type} service works")
|
|
323
|
-
|
|
324
|
-
return True
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
def run_all_tests():
|
|
328
|
-
"""Run all integration tests."""
|
|
329
|
-
print("\n" + "=" * 70)
|
|
330
|
-
print("🚀 AGENTS.MD GENERATOR INTEGRATION TESTS")
|
|
331
|
-
print("=" * 70)
|
|
332
|
-
|
|
333
|
-
tests = [
|
|
334
|
-
("Backend Service", test_backend_service),
|
|
335
|
-
("Frontend Service", test_frontend_service),
|
|
336
|
-
("Migrator Service", test_migrator_service),
|
|
337
|
-
("Content Structure", test_content_structure),
|
|
338
|
-
("AI Agent Instructions", test_ai_agent_instructions),
|
|
339
|
-
("No Write Function", test_no_write_fn),
|
|
340
|
-
("All Service Types", test_all_services),
|
|
341
|
-
]
|
|
342
|
-
|
|
343
|
-
results = []
|
|
344
|
-
for name, test_func in tests:
|
|
345
|
-
try:
|
|
346
|
-
passed = test_func()
|
|
347
|
-
results.append((name, passed))
|
|
348
|
-
except Exception as e:
|
|
349
|
-
print(f"\n💥 ERROR in {name}: {e}")
|
|
350
|
-
import traceback
|
|
351
|
-
traceback.print_exc()
|
|
352
|
-
results.append((name, False))
|
|
353
|
-
|
|
354
|
-
# Summary
|
|
355
|
-
print("\n" + "=" * 70)
|
|
356
|
-
print("📊 TEST SUMMARY")
|
|
357
|
-
print("=" * 70)
|
|
358
|
-
|
|
359
|
-
passed_count = sum(1 for _, p in results if p)
|
|
360
|
-
total_count = len(results)
|
|
361
|
-
|
|
362
|
-
for name, passed in results:
|
|
363
|
-
status = "✅ PASS" if passed else "❌ FAIL"
|
|
364
|
-
print(f" {status}: {name}")
|
|
365
|
-
|
|
366
|
-
print(f"\n Total: {passed_count}/{total_count} tests passed")
|
|
367
|
-
|
|
368
|
-
if passed_count == total_count:
|
|
369
|
-
print("\n🎉 All tests passed!")
|
|
370
|
-
return 0
|
|
371
|
-
else:
|
|
372
|
-
print(f"\n⚠️ {total_count - passed_count} test(s) failed")
|
|
373
|
-
return 1
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
if __name__ == "__main__":
|
|
377
|
-
exit_code = run_all_tests()
|
|
378
|
-
sys.exit(exit_code)
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Tests for registry cache operations.
|
|
3
|
-
Tests the CRUD operations for the service registry cache.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@pytest.mark.cache
|
|
10
|
-
class TestCacheOperations:
|
|
11
|
-
"""Tests for registry cache CRUD operations."""
|
|
12
|
-
|
|
13
|
-
def test_add_new_resource_to_cache(self, resource_registry_cache):
|
|
14
|
-
"""
|
|
15
|
-
Scenario: Add new service to cache
|
|
16
|
-
WHEN `CacheOps.add_resource_to_cache()` is called with a valid service object
|
|
17
|
-
THEN the service SHALL be stored in `_DISCOVERY_CACHE`
|
|
18
|
-
AND it SHALL be retrievable by path via `CacheOps.get_resource_by_path_from_cache()`
|
|
19
|
-
"""
|
|
20
|
-
cache = resource_registry_cache
|
|
21
|
-
service = {
|
|
22
|
-
"name": "test-service",
|
|
23
|
-
"path": "services/product/test/test-service"
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
# Add to cache
|
|
27
|
-
self._add_to_cache(cache, service["path"], service)
|
|
28
|
-
|
|
29
|
-
# Verify retrievable
|
|
30
|
-
retrieved = self._get_from_cache(cache, service["path"])
|
|
31
|
-
assert retrieved is not None
|
|
32
|
-
assert retrieved["name"] == "test-service"
|
|
33
|
-
|
|
34
|
-
def test_add_resource_with_metadata(self, resource_registry_cache):
|
|
35
|
-
"""
|
|
36
|
-
Scenario: Add service with metadata
|
|
37
|
-
WHEN adding a service with fields `name`, `type`, `path`, `domain`, `port`
|
|
38
|
-
THEN all fields SHALL be preserved in the cache
|
|
39
|
-
AND retrieval SHALL return the exact same data
|
|
40
|
-
"""
|
|
41
|
-
cache = resource_registry_cache
|
|
42
|
-
service = {
|
|
43
|
-
"name": "identity-backend",
|
|
44
|
-
"type": "backend",
|
|
45
|
-
"path": "services/product/identity/identity-backend",
|
|
46
|
-
"stack": "identity",
|
|
47
|
-
"port": 4001
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
self._add_to_cache(cache, service["path"], service)
|
|
51
|
-
retrieved = self._get_from_cache(cache, service["path"])
|
|
52
|
-
|
|
53
|
-
assert retrieved["name"] == "identity-backend"
|
|
54
|
-
assert retrieved["type"] == "backend"
|
|
55
|
-
assert retrieved["stack"] == "identity"
|
|
56
|
-
assert retrieved["port"] == 4001
|
|
57
|
-
|
|
58
|
-
def test_prevent_duplicate_adds(self, resource_registry_cache):
|
|
59
|
-
"""
|
|
60
|
-
Scenario: Prevent duplicate adds
|
|
61
|
-
WHEN attempting to add a service with a path already in cache
|
|
62
|
-
THEN the new service data SHALL overwrite the old data (update semantics)
|
|
63
|
-
AND the cache SHALL contain only one entry for that path
|
|
64
|
-
"""
|
|
65
|
-
cache = resource_registry_cache
|
|
66
|
-
path = "services/product/test/service"
|
|
67
|
-
|
|
68
|
-
# Add initial version
|
|
69
|
-
self._add_to_cache(cache, path, {"name": "v1", "port": 4000})
|
|
70
|
-
|
|
71
|
-
# Add updated version (should overwrite)
|
|
72
|
-
self._add_to_cache(cache, path, {"name": "v2", "port": 4001})
|
|
73
|
-
|
|
74
|
-
# Retrieve and verify
|
|
75
|
-
retrieved = self._get_from_cache(cache, path)
|
|
76
|
-
assert retrieved["name"] == "v2"
|
|
77
|
-
assert retrieved["port"] == 4001
|
|
78
|
-
|
|
79
|
-
def test_remove_existing_service(self, resource_registry_cache):
|
|
80
|
-
"""
|
|
81
|
-
Scenario: Remove existing service
|
|
82
|
-
WHEN `CacheOps.remove_resource_from_cache()` is called with a path in cache
|
|
83
|
-
THEN the service SHALL be removed from `_DISCOVERY_CACHE`
|
|
84
|
-
AND subsequent `CacheOps.has_resource_in_cache()` SHALL return `False`
|
|
85
|
-
"""
|
|
86
|
-
cache = resource_registry_cache
|
|
87
|
-
path = "services/product/test/service"
|
|
88
|
-
|
|
89
|
-
# Add and verify
|
|
90
|
-
self._add_to_cache(cache, path, {"name": "test"})
|
|
91
|
-
assert self._has_in_cache(cache, path)
|
|
92
|
-
|
|
93
|
-
# Remove
|
|
94
|
-
self._remove_from_cache(cache, path)
|
|
95
|
-
|
|
96
|
-
# Verify removed
|
|
97
|
-
assert not self._has_in_cache(cache, path)
|
|
98
|
-
|
|
99
|
-
def test_remove_non_existent_service(self, resource_registry_cache):
|
|
100
|
-
"""
|
|
101
|
-
Scenario: Remove non-existent service
|
|
102
|
-
WHEN attempting to remove a path not in cache
|
|
103
|
-
THEN it SHALL complete without error (idempotent)
|
|
104
|
-
AND other cache entries SHALL remain unaffected
|
|
105
|
-
"""
|
|
106
|
-
cache = resource_registry_cache
|
|
107
|
-
|
|
108
|
-
# Add a service
|
|
109
|
-
self._add_to_cache(cache, "path1", {"name": "service1"})
|
|
110
|
-
|
|
111
|
-
# Try to remove non-existent path
|
|
112
|
-
self._remove_from_cache(cache, "nonexistent") # Should not raise
|
|
113
|
-
|
|
114
|
-
# Verify other entries unaffected
|
|
115
|
-
assert self._has_in_cache(cache, "path1")
|
|
116
|
-
|
|
117
|
-
def test_check_resource_existence(self, resource_registry_cache):
|
|
118
|
-
"""
|
|
119
|
-
Scenario: Check service existence
|
|
120
|
-
WHEN `CacheOps.has_resource_in_cache()` is called with a cached path
|
|
121
|
-
THEN it SHALL return `True`
|
|
122
|
-
"""
|
|
123
|
-
cache = resource_registry_cache
|
|
124
|
-
path = "services/product/test/service"
|
|
125
|
-
|
|
126
|
-
self._add_to_cache(cache, path, {"name": "test"})
|
|
127
|
-
|
|
128
|
-
assert self._has_in_cache(cache, path)
|
|
129
|
-
|
|
130
|
-
def test_check_non_existent_service(self, resource_registry_cache):
|
|
131
|
-
"""
|
|
132
|
-
Scenario: Check non-existent service
|
|
133
|
-
WHEN `CacheOps.has_resource_in_cache()` is called with an unknown path
|
|
134
|
-
THEN it SHALL return `False`
|
|
135
|
-
"""
|
|
136
|
-
cache = resource_registry_cache
|
|
137
|
-
|
|
138
|
-
assert not self._has_in_cache(cache, "nonexistent")
|
|
139
|
-
|
|
140
|
-
def test_get_resource_by_path(self, resource_registry_cache):
|
|
141
|
-
"""
|
|
142
|
-
Scenario: Get service by path
|
|
143
|
-
WHEN `CacheOps.get_resource_by_path_from_cache()` is called with a cached path
|
|
144
|
-
THEN it SHALL return the full service object
|
|
145
|
-
"""
|
|
146
|
-
cache = resource_registry_cache
|
|
147
|
-
service = {"name": "test", "type": "backend"}
|
|
148
|
-
path = "services/product/test/service"
|
|
149
|
-
|
|
150
|
-
self._add_to_cache(cache, path, service)
|
|
151
|
-
retrieved = self._get_from_cache(cache, path)
|
|
152
|
-
|
|
153
|
-
assert retrieved == service
|
|
154
|
-
|
|
155
|
-
def test_get_non_existent_resource_returns_none(self, resource_registry_cache):
|
|
156
|
-
"""
|
|
157
|
-
Scenario: Get non-existent service
|
|
158
|
-
WHEN `CacheOps.get_resource_by_path_from_cache()` is called with an unknown path
|
|
159
|
-
THEN it SHALL return `None` (not raise an exception)
|
|
160
|
-
"""
|
|
161
|
-
cache = resource_registry_cache
|
|
162
|
-
|
|
163
|
-
result = self._get_from_cache(cache, "nonexistent")
|
|
164
|
-
|
|
165
|
-
assert result is None
|
|
166
|
-
|
|
167
|
-
# Helper methods to simulate cache operations
|
|
168
|
-
def _add_to_cache(self, cache, path, service):
|
|
169
|
-
if "resource_path_map" not in cache:
|
|
170
|
-
cache["resource_path_map"] = {}
|
|
171
|
-
cache["resource_path_map"][path] = service
|
|
172
|
-
|
|
173
|
-
def _get_from_cache(self, cache, path):
|
|
174
|
-
return cache.get("resource_path_map", {}).get(path)
|
|
175
|
-
|
|
176
|
-
def _remove_from_cache(self, cache, path):
|
|
177
|
-
if path in cache.get("resource_path_map", {}):
|
|
178
|
-
del cache["resource_path_map"][path]
|
|
179
|
-
|
|
180
|
-
def _has_in_cache(self, cache, path):
|
|
181
|
-
return path in cache.get("resource_path_map", {})
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Tests for registry cache persistence.
|
|
3
|
-
Tests saving and loading the cache from the filesystem.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import json
|
|
7
|
-
import pytest
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@pytest.mark.cache
|
|
12
|
-
class TestCachePersistence:
|
|
13
|
-
"""Tests for cache persistence operations."""
|
|
14
|
-
|
|
15
|
-
def test_save_cache_to_file(self, temp_dir, resource_registry_cache):
|
|
16
|
-
"""
|
|
17
|
-
Scenario: Save cache to file
|
|
18
|
-
WHEN the cache is saved to a JSON file
|
|
19
|
-
THEN the file SHALL exist with valid JSON
|
|
20
|
-
AND it SHALL contain all cached services
|
|
21
|
-
"""
|
|
22
|
-
cache_file = temp_dir / "discovery-cache.json"
|
|
23
|
-
|
|
24
|
-
# Add services to cache
|
|
25
|
-
cache = resource_registry_cache
|
|
26
|
-
cache["resource_path_map"] = {
|
|
27
|
-
"path1": {"name": "service1"},
|
|
28
|
-
"path2": {"name": "service2"}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
# Save to file
|
|
32
|
-
self._save_cache(cache, cache_file)
|
|
33
|
-
|
|
34
|
-
# Verify file exists
|
|
35
|
-
assert cache_file.exists()
|
|
36
|
-
|
|
37
|
-
# Verify content
|
|
38
|
-
with open(cache_file) as f:
|
|
39
|
-
data = json.load(f)
|
|
40
|
-
|
|
41
|
-
assert "resource_path_map" in data
|
|
42
|
-
assert len(data["resource_path_map"]) == 2
|
|
43
|
-
|
|
44
|
-
def test_load_cache_from_file(self, temp_dir, resource_registry_cache):
|
|
45
|
-
"""
|
|
46
|
-
Scenario: Load cache from file
|
|
47
|
-
WHEN loading cache from a previously saved JSON file
|
|
48
|
-
THEN `_DISCOVERY_CACHE` SHALL be populated with the saved services
|
|
49
|
-
AND all query operations SHALL work on the loaded data
|
|
50
|
-
"""
|
|
51
|
-
cache_file = temp_dir / "discovery-cache.json"
|
|
52
|
-
|
|
53
|
-
# Create saved cache file
|
|
54
|
-
saved_data = {
|
|
55
|
-
"resource_path_map": {
|
|
56
|
-
"path1": {"name": "service1", "type": "backend"},
|
|
57
|
-
"path2": {"name": "service2", "type": "frontend"}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
with open(cache_file, "w") as f:
|
|
61
|
-
json.dump(saved_data, f)
|
|
62
|
-
|
|
63
|
-
# Load cache
|
|
64
|
-
cache = resource_registry_cache
|
|
65
|
-
self._load_cache(cache, cache_file)
|
|
66
|
-
|
|
67
|
-
# Verify loaded
|
|
68
|
-
assert "path1" in cache["resource_path_map"]
|
|
69
|
-
assert cache["resource_path_map"]["path1"]["name"] == "service1"
|
|
70
|
-
assert cache["resource_path_map"]["path2"]["type"] == "frontend"
|
|
71
|
-
|
|
72
|
-
def test_cache_survives_process_restart(self, temp_dir, resource_registry_cache):
|
|
73
|
-
"""
|
|
74
|
-
Scenario: Cache survives process restart
|
|
75
|
-
WHEN the Tilt process restarts
|
|
76
|
-
AND the cache file exists
|
|
77
|
-
THEN the cache SHALL be reloaded automatically
|
|
78
|
-
AND no services SHALL need re-discovery
|
|
79
|
-
"""
|
|
80
|
-
cache_file = temp_dir / "discovery-cache.json"
|
|
81
|
-
|
|
82
|
-
# Simulate first run - save cache
|
|
83
|
-
cache1 = resource_registry_cache
|
|
84
|
-
cache1["resource_path_map"] = {
|
|
85
|
-
"services/test/service1": {"name": "service1"},
|
|
86
|
-
"services/test/service2": {"name": "service2"}
|
|
87
|
-
}
|
|
88
|
-
self._save_cache(cache1, cache_file)
|
|
89
|
-
|
|
90
|
-
# Simulate restart - new cache object, load from file
|
|
91
|
-
cache2 = {"initialized": False, "resource_path_map": {}}
|
|
92
|
-
self._load_cache(cache2, cache_file)
|
|
93
|
-
|
|
94
|
-
# Verify cache survived
|
|
95
|
-
assert "services/test/service1" in cache2["resource_path_map"]
|
|
96
|
-
assert "services/test/service2" in cache2["resource_path_map"]
|
|
97
|
-
assert cache2["resource_path_map"]["services/test/service1"]["name"] == "service1"
|
|
98
|
-
|
|
99
|
-
def test_save_and_load_empty_cache(self, temp_dir):
|
|
100
|
-
"""Test saving and loading an empty cache."""
|
|
101
|
-
cache_file = temp_dir / "empty-cache.json"
|
|
102
|
-
|
|
103
|
-
empty_cache = {"resource_path_map": {}}
|
|
104
|
-
self._save_cache(empty_cache, cache_file)
|
|
105
|
-
|
|
106
|
-
loaded_cache = {"resource_path_map": {}}
|
|
107
|
-
self._load_cache(loaded_cache, cache_file)
|
|
108
|
-
|
|
109
|
-
assert len(loaded_cache["resource_path_map"]) == 0
|
|
110
|
-
|
|
111
|
-
def test_cache_file_format(self, temp_dir):
|
|
112
|
-
"""Test that cache file has expected format."""
|
|
113
|
-
cache_file = temp_dir / "cache.json"
|
|
114
|
-
|
|
115
|
-
cache = {
|
|
116
|
-
"initialized": True,
|
|
117
|
-
"resource_path_map": {
|
|
118
|
-
"path": {"name": "test"}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
self._save_cache(cache, cache_file)
|
|
122
|
-
|
|
123
|
-
with open(cache_file) as f:
|
|
124
|
-
content = f.read()
|
|
125
|
-
|
|
126
|
-
# Should be valid JSON
|
|
127
|
-
data = json.loads(content)
|
|
128
|
-
assert "resource_path_map" in data
|
|
129
|
-
|
|
130
|
-
# Helper methods
|
|
131
|
-
def _save_cache(self, cache, path):
|
|
132
|
-
with open(path, "w") as f:
|
|
133
|
-
json.dump(cache, f, indent=2)
|
|
134
|
-
|
|
135
|
-
def _load_cache(self, cache, path):
|
|
136
|
-
if not path.exists():
|
|
137
|
-
return
|
|
138
|
-
|
|
139
|
-
with open(path) as f:
|
|
140
|
-
data = json.load(f)
|
|
141
|
-
|
|
142
|
-
cache.update(data)
|