thothctl 0.25.7__tar.gz → 0.26.0__tar.gz
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.
- {thothctl-0.25.7 → thothctl-0.26.0}/PKG-INFO +2 -2
- thothctl-0.26.0/docs/framework/specs/phase1.9_composition_generation.md +302 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/generate/commands/iac.py +12 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/providers/bedrock_provider.py +10 -1
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/rules_compiler.py +26 -24
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/intent/code_generator.py +11 -1
- thothctl-0.26.0/src/thothctl/services/generate/intent/composition_models.py +182 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/intent/context_builder.py +99 -17
- thothctl-0.26.0/src/thothctl/services/generate/intent/intent_decomposer.py +365 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/intent/intent_service.py +156 -0
- thothctl-0.26.0/src/thothctl/services/generate/intent/project_assembler.py +396 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/version.py +1 -1
- {thothctl-0.25.7 → thothctl-0.26.0}/.devcontainer/Dockerfile +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/.devcontainer/README.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/.devcontainer/devcontainer.json +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/.github/workflows/docs.yml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/.github/workflows/python-publish.yml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/.github/workflows/release.yml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/.gitignore +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/.pre-commit-config.yaml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/.pydocstyle +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/.readthedocs.yaml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/Dockerfile +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/LICENSE +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/README.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/catalog/catalog-info.yaml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/dashboard/README.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/ai-review/README.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/ai-review/agent_specifications.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/ai-review/agentcore.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/check/blast-radius.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/check/check_environment.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/check/check_iac.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/check/check_overview.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/check/check_project_iac.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/check/check_space.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/check/cost-analysis-quick-reference.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/check/cost-analysis.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/check/customizing_rules.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/check/deps-advanced.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/check/deps.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/check/drift-detection.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/check/plan.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/dashboard/dashboard_overview.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/document/customizing_docs.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/document/document_iac.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/document/document_overview.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/document/iac.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/document/mermaid_examples.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/document/mermaid_quickref.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/document/use_cases.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/generate/generate_components.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/generate/generate_iac.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/generate/generate_stacks.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/init/init.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/init/init_space.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/inventory/CHANGELOG.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/inventory/frameworks/terraform.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/inventory/frameworks/terragrunt.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/inventory/iac.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/inventory/inventory_iac.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/inventory/inventory_overview.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/list/list_overview.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/list/list_projects.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/list/list_spaces.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/mcp/mcp.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/project/iac.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/project/project_cleanup.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/project/project_convert.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/project/project_overview.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/project/project_upgrade.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/project/use_cases.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/remove/remove_overview.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/remove/remove_project.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/remove/remove_space.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/scan/iac.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/scan/scan_iac.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/scan/scan_overview.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/scan/use_cases.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/space/space_overview.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/upgrade/upgrade_overview.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/workflow/workflow_devsecops.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/commands/workflow/workflow_overview.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/concepts.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/cross_platform_support.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/framework_architecture.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/infrastructure_composition.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/policy_as_code.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/roadmap_fdi.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/software_architecture.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/space_configuration.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/specs/phase1_intent_to_iac.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/use_cases/README.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/use_cases/ai_dlc.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/use_cases/check_command.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/use_cases/devsecops_quickstart.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/use_cases/devsecops_sdlc.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/use_cases/inventory_command.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/use_cases/platform_engineering_templates.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/use_cases/space_management.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/use_cases/tasks/create_template.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/framework/use_cases/tasks/workflow_implementation_plan.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/img/commnad_init.png +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/img/framework/thothforge-framework.svg +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/img/framework/thothfr.png +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/img/icon-light.png +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/img/icon.png +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/img/init_project.gif +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/img/stable/scan_report_example.png +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/includes/abbreviations.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/index.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/installation/devcontainer_setup.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/installation/linux_installation.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/installation/windows_installation.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/javascripts/tablesort.js +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/mcp.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/navigation.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/quick_start.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/requirements.txt +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/stylesheets/extra-enhanced.css +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/stylesheets/extra.css +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/telemetry.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/template_engine/cli_commands_audit.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/template_engine/for_developers.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/template_engine/for_platform_engineers.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/template_engine/github_templates.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/template_engine/template_engine.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/toolkit_overview.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/troubleshooting/linux_troubleshooting.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/troubleshooting/macos_troubleshooting.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/troubleshooting/troubleshooting.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/docs/troubleshooting/windows_troubleshooting.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/mkdocs.yaml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/pyproject.toml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/scripts/check_output_consistency.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/scripts/run_mcp_server.sh +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/application/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/autocomplete.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/ai_review/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/ai_review/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/ai_review/commands/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/ai_review/commands/analyze.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/ai_review/commands/apply_fix.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/ai_review/commands/configure.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/ai_review/commands/configure_decisions.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/ai_review/commands/decide.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/ai_review/commands/history.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/ai_review/commands/improve.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/ai_review/commands/orchestrate.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/ai_review/commands/override.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/ai_review/commands/report.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/ai_review/commands/serve.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/check/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/check/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/check/commands/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/check/commands/config.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/check/commands/environment.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/check/commands/iac.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/check/commands/project/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/check/commands/project/iac.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/check/commands/project.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/check/commands/space.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/dashboard/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/dashboard/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/dashboard/commands/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/dashboard/commands/launch.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/document/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/document/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/document/commands/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/document/commands/iac.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/generate/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/generate/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/generate/commands/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/generate/commands/component.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/generate/commands/stacks.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/init/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/init/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/init/commands/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/init/commands/env.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/init/commands/project.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/init/commands/space.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/init/commands/template.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/inventory/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/inventory/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/inventory/commands/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/inventory/commands/check.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/inventory/commands/iac.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/list/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/list/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/list/commands/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/list/commands/projects.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/list/commands/spaces.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/list/commands/templates.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/mcp/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/mcp/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/mcp/commands/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/mcp/commands/register.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/mcp/commands/server.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/mcp/commands/status.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/mcp/commands/stop.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/project/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/project/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/project/commands/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/project/commands/bootstrap.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/project/commands/cleanup.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/project/commands/convert.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/project/commands/upgrade.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/quickstart/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/quickstart/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/remove/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/remove/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/remove/project.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/remove/space.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/scan/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/scan/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/scan/commands/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/scan/commands/iac.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/space/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/space/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/space/commands/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/space/commands/activate.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/space/commands/deactivate.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/space/commands/export_space.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/space/commands/import_space.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/space/commands/show.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/space/commands/update.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/upgrade/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/workflow/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/workflow/cli.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/workflow/commands/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/workflow/commands/devsecops.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/commands/workflow/commands/run.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/common/.thothcf.setup.toml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/common/.thothcf_home.toml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/common/.thothcf_module.toml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/common/.thothcf_project.toml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/common/.thothcf_template_parameters.toml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/common/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/common/common.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/common/terragrunt/.thothcf_project.toml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/config/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/config/constants.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/config/default_values.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/config/defaults.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/config/models.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/config/settings.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/config/template_config.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/config/template_configs.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/config/templates.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/config/validation.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/cli_ui.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/commands.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/config.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/integrations/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/integrations/azure_devops/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/integrations/azure_devops/get_azure_devops.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/integrations/azure_devops/pull_request_comments.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/integrations/github/get_github.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/integrations/github/pull_request_comments.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/integrations/integrate_messages_services/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/integrations/integrate_messages_services/microsoft_teams.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/integrations/integrate_messages_services/sent_message_teams.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/integrations/pattern_names.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/integrations/pr_comments/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/integrations/pr_comments/pr_comment_publisher.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/logger.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/telemetry.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/core/version_tools.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/domain/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/domain/interfaces/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/domain/models/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/mcp/README.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/mcp/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/mcp/server.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/agentcore/agentcore.json +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/ai_agent.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/analyzers/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/analyzers/code_reviewer.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/analyzers/context_builder.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/analyzers/report_analyzer.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/analyzers/risk_assessor.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/bedrock_agent_api.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/config/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/config/ai_settings.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/config/decision_rules.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/decision_engine.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/main.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/memory.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/orchestrator.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/pr_decision_publisher.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/providers/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/providers/azure_provider.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/providers/bedrock_agent_provider.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/providers/ollama_provider.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/providers/openai_provider.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/safety/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/safety/safety_guard.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/strands_agent.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/tracing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/utils/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/utils/cost_tracker.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/utils/fix_patterns.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/utils/fix_prompts.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/utils/formatters.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/utils/prompts.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/environment/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/environment/check_environment.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/org_policy_loader.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/blast_radius_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cfn_blast_radius_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/check_origin_version.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/check_project_structure.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/cost_analyzer.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/models/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/models/cloudformation_mapper.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/models/cost_models.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/aws_pricing_client.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/base_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/apigateway_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/bedrock_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/cloudwatch_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/dynamodb_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/ebs_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/ec2_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/ecs_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/eip_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/eks_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/elb_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/free_resources_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/kms_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/lambda_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/msk_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/rds_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/s3_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/secrets_manager_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/pricing/providers/vpc_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/cost/unified_cost_report.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/drift/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/drift/cfn_drift_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/drift/drift_ai.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/drift/drift_history.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/drift/drift_policy.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/drift/drift_report.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/drift/drift_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/drift/models.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/risk_assessment.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/project/validate_project_structure.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/rule_merger.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/check/stack_optimizer/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/dashboard/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/dashboard/dashboard_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/dashboard/data_loader.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/document/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/document/architecture_renderer.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/document/create_documentation.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/document/files_content.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/document/files_scan.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/document/iac_documentation.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/document/iac_grunt_graph.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/document/iac_grunt_info.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/document/topology_generator.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_stacks/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_stacks/config_generator.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_stacks/remote_config_generation.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_stacks/stack_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_stacks/templates/terragrunt.hcl.j2 +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_stacks/terragrunt.hcl +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_template/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_template/config.yaml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_template/create_code.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_template/create_component.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_template/create_component_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_template/create_stacks.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_template/create_template.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_template/files_content.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_template/github_template_loader.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/create_template/project_templates.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/intent/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/intent/models.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/intent/prompts.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/generate/intent/validator.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/init/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/init/environment/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/init/environment/install_tools.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/init/environment/prerequisite_checker.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/init/environment/tool_packs.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/init/project/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/init/project/project.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/init/space/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/init/space/example_space.toml +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/init/space/export_import.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/init/space/inheritance.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/init/space/space.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/init/space/terraform_module_cache.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/inventory/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/inventory/cdk_parsers.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/inventory/cdk_sbom_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/inventory/changelog_parser.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/inventory/inventory_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/inventory/models.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/inventory/module_compatibility_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/inventory/report_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/inventory/schema_compatibility_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/inventory/terragrunt_parser.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/inventory/update_versions.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/inventory/version_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/mcp/README.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/mcp/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/mcp/simple_http_server.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/mcp/stdio_server.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/bootstrap/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/bootstrap/bootstrap_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/cleanup/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/cleanup/clean_project.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/cleanup/clean_space.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/convert/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/convert/conversion_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/convert/get_project_data.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/convert/post_init.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/convert/project_converter.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/convert/project_defaults.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/convert/set_project_parameters.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/create_terramate/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/create_terramate/create_terramate_stacks.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/create_terramate/detect_changes_stacks.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/create_terramate/manage_terramate_stacks.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/upgrade/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/project/upgrade/upgrade_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/compliance_review.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/import_reports.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/models.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/report_parser.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/sarif_output.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/scan_history.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/scan_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/scanners/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/scanners/checkov.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/scanners/kics.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/scanners/opa.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/scanners/scan_reports.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/scanners/scanners.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/scanners/terraform_compliance.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/scanners/tfsec.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/scan/scanners/trivy.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/workflow/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/workflow/custom_workflow_engine.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/workflow/models.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/workflow/phases/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/workflow/phases/base.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/workflow/phases/build.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/workflow/phases/deploy.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/workflow/phases/develop.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/workflow/phases/monitor.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/workflow/phases/plan.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/workflow/phases/secure.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/workflow/phases/test.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/workflow/workflow_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/templates/ai_reports/pr_comment.md +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/templates/reports/inventory_report.html +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/templates/reports/inventory_report.js +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/templates/unified_report_styles.css +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/banner.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/create_compliance_html_reports.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/create_html_reports.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/delete_directory.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/fix_report_styling.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/render_scan_report.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/report_html_utils.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/templates/dashboard.html +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/templates/index_report.html +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/templates/individual_report.html +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/templates/simple_report.html +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/templates/unified_report_styles.css +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/templates/unified_scan_report.html +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/templates/unified_simple_report.html +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/common/templates/xunit_report.html +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/crypto.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/git_changes.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/manage_backend_resources/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/manage_backend_resources/manage_backend_resources.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/modules_ops/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/modules_ops/terraform_module_details.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/modules_ops/terraform_modules_fetcher.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/platform_utils.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/process_hcl/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/process_hcl/analyze_terraform_plan.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/process_hcl/graph_manager.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/process_hcl/graph_terragrunt_dependencies.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/process_hcl/process_terraform_file.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/process_hcl/risk_analyzing_terraform_plan.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/sync_workspaces/__init__.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/sync_workspaces/sync_terraform_workspaces.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/sync_workspaces/sync_terragrunt_workspaces.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/template_loader.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/utils/thoth_colors.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/wellcome_banner.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/conftest.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_agentcore_entrypoint.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_ai_apply_fix.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_ai_decision_engine.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_ai_fix_patterns.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_ai_memory.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_ai_orchestrator.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_ai_pr_decision.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_ai_safety_guard.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_aws_pricing_client.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_azure_devops_pr_comments.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_bedrock_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_cdk_inventory.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_cdk_language_selection.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_cfn_blast_radius.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_cfn_drift_detection.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_context_steering.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_cost_analyzer.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_cost_models.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_cost_policy_enforcement.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_cost_pr_comments.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_dashboard_loading_fix.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_dashboard_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_drift.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_drift_detection.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_ec2_pricing.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_generate_iac_codegen.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_generate_iac_context.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_generate_iac_prompts.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_generate_iac_service.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_generate_iac_validator.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_github_pr_comments.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_iac_cost_integration.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_init_ai_tools.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_init_template_params.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_intent_quick_wins.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_intent_rules_integration.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_inventory_pr_comments.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_kics_scanner.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_mermaid_edge_labels.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_new_cost_providers.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_opa_data_files.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_parallel_scan.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_platform_utils.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_pr_comment_publisher.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_provider_source_url_fix.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_provider_versions.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_rules_compiler.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_scan_cfn_support.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_scan_command.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_scan_pr_comments.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_space_command.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_space_management.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_stack_optimizer.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_template_url_fix.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_terragrunt_parser.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_topology_generator.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tests/test_workflow_integration.py +0 -0
- {thothctl-0.25.7 → thothctl-0.26.0}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: thothctl
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.26.0
|
|
4
4
|
Summary: A CLI for Developer Control Plane. Accelerate your cloud IaC deployments.
|
|
5
5
|
Project-URL: SourceCode, https://github.com/thothforge/thothctl
|
|
6
6
|
Project-URL: HomePage, https://github.com/thothforge/thothctl
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
# Phase 1.9: Composition-Aware Intent-to-IaC Generation — Spec
|
|
2
|
+
|
|
3
|
+
> **Version**: 1.0 | **Target**: v0.26.0 | **Effort**: ~8 days
|
|
4
|
+
> **Author**: ThothForge | **Status**: Ready for implementation
|
|
5
|
+
> **Depends on**: Phase 1 (Intent-to-IaC) ✅, Phase 2.4 (Rules integration) ✅
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
Extend `thothctl generate iac` to produce **full multi-stack projects** following the ThothForge scaffold composition rules — not just single flat modules. The AI decomposes a high-level intent into multiple stacks organized by layers, wires dependencies between them, and produces a complete project ready for `terragrunt run-all plan`.
|
|
10
|
+
|
|
11
|
+
## Design Principles
|
|
12
|
+
|
|
13
|
+
1. **Scaffold-driven** — output structure comes from `.thothcf_project.toml`, not AI invention
|
|
14
|
+
2. **Layer-aware** — foundation → platform → application → observability (ordered dependencies)
|
|
15
|
+
3. **Org policy compliant** — naming, tagging, security rules enforced at generation time
|
|
16
|
+
4. **Incremental** — can generate into an existing project (adds stacks, doesn't overwrite)
|
|
17
|
+
5. **Framework-agnostic** — supports terraform-terragrunt, terraform, cdkv2, cloudformation
|
|
18
|
+
|
|
19
|
+
## Architecture
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
User Intent (complex, multi-service)
|
|
23
|
+
↓
|
|
24
|
+
┌──────────────────────────────────────────────────────────────────┐
|
|
25
|
+
│ 1. Intent Decomposer │
|
|
26
|
+
│ - Breaks intent into discrete infrastructure components │
|
|
27
|
+
│ - Assigns each component to a layer (foundation/platform/app) │
|
|
28
|
+
│ - Identifies dependencies between components │
|
|
29
|
+
│ Output: CompositionPlan (list of stacks + dependency graph) │
|
|
30
|
+
└──────────────┬───────────────────────────────────────────────────┘
|
|
31
|
+
↓
|
|
32
|
+
┌──────────────────────────────────────────────────────────────────┐
|
|
33
|
+
│ 2. Stack Generator (per stack) │
|
|
34
|
+
│ - Uses existing CodeGenerator for each stack's code │
|
|
35
|
+
│ - Adds terragrunt.hcl with includes + dependencies │
|
|
36
|
+
│ - Places in correct path: stacks/<layer>/<domain>/<service>/ │
|
|
37
|
+
│ Output: List[GeneratedFile] per stack │
|
|
38
|
+
└──────────────┬───────────────────────────────────────────────────┘
|
|
39
|
+
↓
|
|
40
|
+
┌──────────────────────────────────────────────────────────────────┐
|
|
41
|
+
│ 3. Project Assembler │
|
|
42
|
+
│ - Creates root.hcl + common/ if needed │
|
|
43
|
+
│ - Merges all stack files into project structure │
|
|
44
|
+
│ - Runs validation on the full project │
|
|
45
|
+
│ Output: Complete project directory │
|
|
46
|
+
└──────────────────────────────────────────────────────────────────┘
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Layer Model
|
|
50
|
+
|
|
51
|
+
| Layer | Purpose | Examples | Dependencies |
|
|
52
|
+
|-------|---------|----------|--------------|
|
|
53
|
+
| `foundation` | Core networking & security | VPC, subnets, NAT, KMS keys, IAM baselines | None (root layer) |
|
|
54
|
+
| `platform` | Shared services | ECS/EKS cluster, RDS, ElastiCache, S3 buckets | → foundation |
|
|
55
|
+
| `application` | Workload-specific | Lambda functions, API Gateway, DynamoDB tables | → platform |
|
|
56
|
+
| `observability` | Monitoring & alerting | CloudWatch dashboards, alarms, log groups | → platform |
|
|
57
|
+
|
|
58
|
+
## CLI Interface
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Full project generation (new project)
|
|
62
|
+
thothctl generate iac \
|
|
63
|
+
-i "Microservices platform: VPC with 3 AZs, ECS Fargate cluster, RDS PostgreSQL, S3 data lake, API Gateway" \
|
|
64
|
+
--project-type terraform-terragrunt \
|
|
65
|
+
--composition full \
|
|
66
|
+
-o ./my-platform \
|
|
67
|
+
--apply
|
|
68
|
+
|
|
69
|
+
# Add stacks to existing project (incremental)
|
|
70
|
+
thothctl generate iac \
|
|
71
|
+
-i "Add Redis cache for session management" \
|
|
72
|
+
--project-type terraform-terragrunt \
|
|
73
|
+
--composition incremental \
|
|
74
|
+
--apply
|
|
75
|
+
|
|
76
|
+
# Single stack (current behavior, default)
|
|
77
|
+
thothctl generate iac \
|
|
78
|
+
-i "S3 bucket with encryption" \
|
|
79
|
+
--apply
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## CompositionPlan Model
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
@dataclass
|
|
86
|
+
class StackPlan:
|
|
87
|
+
"""A single stack to generate."""
|
|
88
|
+
name: str # e.g., "vpc"
|
|
89
|
+
layer: str # foundation | platform | application | observability
|
|
90
|
+
domain: str # e.g., "networking", "data", "compute"
|
|
91
|
+
intent: str # Specific intent for this stack
|
|
92
|
+
depends_on: List[str] # Stack names this depends on
|
|
93
|
+
module_source: Optional[str] # Official module if applicable
|
|
94
|
+
|
|
95
|
+
@dataclass
|
|
96
|
+
class CompositionPlan:
|
|
97
|
+
"""Full project composition plan."""
|
|
98
|
+
stacks: List[StackPlan]
|
|
99
|
+
project_type: str
|
|
100
|
+
needs_root_config: bool # True if root.hcl doesn't exist
|
|
101
|
+
needs_common: bool # True if common/ doesn't exist
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Intent Decomposition Prompt
|
|
105
|
+
|
|
106
|
+
The AI receives the high-level intent + layer model and returns a structured decomposition:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
SYSTEM: You are an infrastructure architect. Decompose the user's intent into
|
|
110
|
+
discrete infrastructure stacks following the layer model:
|
|
111
|
+
- foundation: networking, security baselines, encryption keys
|
|
112
|
+
- platform: shared compute, databases, storage
|
|
113
|
+
- application: workload-specific resources
|
|
114
|
+
- observability: monitoring, alerting
|
|
115
|
+
|
|
116
|
+
Return JSON:
|
|
117
|
+
{
|
|
118
|
+
"stacks": [
|
|
119
|
+
{
|
|
120
|
+
"name": "vpc",
|
|
121
|
+
"layer": "foundation",
|
|
122
|
+
"domain": "networking",
|
|
123
|
+
"intent": "VPC with 3 private subnets, 3 public subnets, NAT gateway per AZ",
|
|
124
|
+
"depends_on": [],
|
|
125
|
+
"module_source": "terraform-aws-modules/vpc/aws"
|
|
126
|
+
},
|
|
127
|
+
...
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Terragrunt.hcl Generation
|
|
133
|
+
|
|
134
|
+
For each stack, generate the orchestration file:
|
|
135
|
+
|
|
136
|
+
```hcl
|
|
137
|
+
# Auto-generated by ThothCTL — stacks/platform/data/s3/terragrunt.hcl
|
|
138
|
+
include "root" {
|
|
139
|
+
path = find_in_parent_folders("root.hcl")
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
dependency "vpc" {
|
|
143
|
+
config_path = "../../../foundation/networking/vpc"
|
|
144
|
+
|
|
145
|
+
mock_outputs = {
|
|
146
|
+
vpc_id = "vpc-mock-12345"
|
|
147
|
+
subnet_ids = ["subnet-mock-1", "subnet-mock-2"]
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
mock_outputs_merge_strategy_with_state = "shallow"
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
inputs = {
|
|
154
|
+
vpc_id = dependency.vpc.outputs.vpc_id
|
|
155
|
+
subnet_ids = dependency.vpc.outputs.subnet_ids
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Root Config Generation (if needed)
|
|
160
|
+
|
|
161
|
+
```hcl
|
|
162
|
+
# root.hcl — Generated by ThothCTL
|
|
163
|
+
locals {
|
|
164
|
+
# Environment from directory structure or tfvars
|
|
165
|
+
environment = get_env("TF_VAR_environment", "dev")
|
|
166
|
+
project = "my-platform"
|
|
167
|
+
region = "us-east-1"
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
remote_state {
|
|
171
|
+
backend = "s3"
|
|
172
|
+
generate = {
|
|
173
|
+
path = "backend.tf"
|
|
174
|
+
if_exists = "overwrite_terragrunt"
|
|
175
|
+
}
|
|
176
|
+
config = {
|
|
177
|
+
bucket = "${local.project}-terraform-state"
|
|
178
|
+
key = "${path_relative_to_include()}/terraform.tfstate"
|
|
179
|
+
region = local.region
|
|
180
|
+
encrypt = true
|
|
181
|
+
dynamodb_table = "${local.project}-state-lock"
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
generate "provider" {
|
|
186
|
+
path = "provider.tf"
|
|
187
|
+
if_exists = "overwrite_terragrunt"
|
|
188
|
+
contents = <<EOF
|
|
189
|
+
provider "aws" {
|
|
190
|
+
region = "${local.region}"
|
|
191
|
+
|
|
192
|
+
default_tags {
|
|
193
|
+
tags = {
|
|
194
|
+
Project = "${local.project}"
|
|
195
|
+
Environment = "${local.environment}"
|
|
196
|
+
ManagedBy = "terragrunt"
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
EOF
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Implementation Tasks
|
|
205
|
+
|
|
206
|
+
| # | Task | Effort | Dependencies |
|
|
207
|
+
|---|------|--------|-------------|
|
|
208
|
+
| 1.9.1 | Add `--composition` flag to CLI (full/incremental/single) | 1d | — |
|
|
209
|
+
| 1.9.2 | Create `IntentDecomposer` class (AI call to break intent into stacks) | 2d | — |
|
|
210
|
+
| 1.9.3 | Create `CompositionPlan` + `StackPlan` models | 0.5d | — |
|
|
211
|
+
| 1.9.4 | Create `ProjectAssembler` (root.hcl, common/, merge stacks) | 1.5d | 1.9.3 |
|
|
212
|
+
| 1.9.5 | Generate `terragrunt.hcl` per stack (Jinja2 template + dependency wiring) | 1d | 1.9.4 |
|
|
213
|
+
| 1.9.6 | Loop: generate code per stack using existing `CodeGenerator` | 1d | 1.9.2, 1.9.5 |
|
|
214
|
+
| 1.9.7 | Validate full project (terraform validate per stack + org rules) | 0.5d | 1.9.6 |
|
|
215
|
+
| 1.9.8 | Write tests + docs | 0.5d | 1.9.7 |
|
|
216
|
+
|
|
217
|
+
## Example Output
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
$ thothctl generate iac \
|
|
221
|
+
-i "Fintech platform: VPC, ECS cluster, PostgreSQL RDS, S3 data lake" \
|
|
222
|
+
--project-type terraform-terragrunt \
|
|
223
|
+
--composition full \
|
|
224
|
+
-o ./fintech-infra \
|
|
225
|
+
--apply
|
|
226
|
+
|
|
227
|
+
🎯 Intent: Fintech platform: VPC, ECS cluster, PostgreSQL RDS, S3 data lake
|
|
228
|
+
🤖 Provider: bedrock (model: us.anthropic.claude-sonnet-4-6)
|
|
229
|
+
📐 Composition: full project (terraform-terragrunt)
|
|
230
|
+
|
|
231
|
+
🧩 Decomposed into 4 stacks:
|
|
232
|
+
foundation/networking/vpc — VPC with 3 AZs, NAT, flow logs
|
|
233
|
+
platform/compute/ecs — ECS Fargate cluster (depends: vpc)
|
|
234
|
+
platform/data/rds — PostgreSQL RDS Multi-AZ (depends: vpc)
|
|
235
|
+
platform/data/s3 — S3 data lake with KMS (depends: vpc)
|
|
236
|
+
|
|
237
|
+
📁 Generating project structure...
|
|
238
|
+
✅ root.hcl
|
|
239
|
+
✅ common/common.hcl
|
|
240
|
+
✅ stacks/foundation/networking/vpc/ (4 files)
|
|
241
|
+
✅ stacks/platform/compute/ecs/ (4 files)
|
|
242
|
+
✅ stacks/platform/data/rds/ (4 files)
|
|
243
|
+
✅ stacks/platform/data/s3/ (4 files)
|
|
244
|
+
|
|
245
|
+
🔒 Validating (Checkov + org rules)...
|
|
246
|
+
✅ All stacks pass validation
|
|
247
|
+
|
|
248
|
+
✨ Project generated: ./fintech-infra (18 files, 4 stacks)
|
|
249
|
+
Next: cd fintech-infra && terragrunt run-all plan
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## CDK Composition (cdkv2 project type)
|
|
253
|
+
|
|
254
|
+
For CDK projects, the composition generates the app entry point + stack classes:
|
|
255
|
+
|
|
256
|
+
```
|
|
257
|
+
my-cdk-app/
|
|
258
|
+
├── bin/app.ts ← CDK app entry (instantiates all stacks)
|
|
259
|
+
├── lib/
|
|
260
|
+
│ ├── stacks/
|
|
261
|
+
│ │ ├── foundation/
|
|
262
|
+
│ │ │ └── networking-stack.ts
|
|
263
|
+
│ │ ├── platform/
|
|
264
|
+
│ │ │ ├── compute-stack.ts
|
|
265
|
+
│ │ │ └── data-stack.ts
|
|
266
|
+
│ │ └── application/
|
|
267
|
+
│ │ └── api-stack.ts
|
|
268
|
+
│ └── constructs/ ← Shared L2/L3 constructs
|
|
269
|
+
├── cdk.json
|
|
270
|
+
├── package.json
|
|
271
|
+
└── tsconfig.json
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## CloudFormation Composition
|
|
275
|
+
|
|
276
|
+
For CloudFormation, generates nested stacks with cross-stack references:
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
my-cfn-project/
|
|
280
|
+
├── templates/
|
|
281
|
+
│ ├── foundation/
|
|
282
|
+
│ │ └── networking.yaml ← Exports VpcId, SubnetIds
|
|
283
|
+
│ ├── platform/
|
|
284
|
+
│ │ ├── compute.yaml ← Imports !ImportValue VpcId
|
|
285
|
+
│ │ └── data.yaml
|
|
286
|
+
│ └── application/
|
|
287
|
+
│ └── api.yaml
|
|
288
|
+
├── parameters/
|
|
289
|
+
│ ├── dev.json
|
|
290
|
+
│ └── prd.json
|
|
291
|
+
└── deploy.sh ← Ordered deployment script
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Success Criteria
|
|
295
|
+
|
|
296
|
+
- [ ] `--composition full` generates complete project with root config + multiple stacks
|
|
297
|
+
- [ ] Stacks placed in correct layer paths
|
|
298
|
+
- [ ] Dependencies wired correctly (terragrunt.hcl has dependency blocks)
|
|
299
|
+
- [ ] Org rules enforced across all generated stacks
|
|
300
|
+
- [ ] Works for terraform-terragrunt, cdkv2, cloudformation
|
|
301
|
+
- [ ] Incremental mode adds stacks without overwriting existing
|
|
302
|
+
- [ ] `terragrunt run-all plan` succeeds on generated project (no syntax errors)
|
|
@@ -36,6 +36,7 @@ class GenerateIaCCommand(ClickCommand):
|
|
|
36
36
|
max_iterations: int = 3,
|
|
37
37
|
skip_validation: bool = False,
|
|
38
38
|
include_diagram: bool = True,
|
|
39
|
+
composition: str = "single",
|
|
39
40
|
**kwargs,
|
|
40
41
|
) -> None:
|
|
41
42
|
"""Execute IaC generation from intent."""
|
|
@@ -120,6 +121,7 @@ class GenerateIaCCommand(ClickCommand):
|
|
|
120
121
|
max_iterations=max_iterations,
|
|
121
122
|
skip_validation=skip_validation,
|
|
122
123
|
include_diagram=include_diagram,
|
|
124
|
+
composition=composition,
|
|
123
125
|
)
|
|
124
126
|
|
|
125
127
|
# Display results
|
|
@@ -287,4 +289,14 @@ cli = GenerateIaCCommand.as_click_command(
|
|
|
287
289
|
default=True,
|
|
288
290
|
help="Generate architecture diagram alongside code",
|
|
289
291
|
),
|
|
292
|
+
click.option(
|
|
293
|
+
"--composition",
|
|
294
|
+
type=click.Choice(["single", "full", "incremental"], case_sensitive=False),
|
|
295
|
+
default="single",
|
|
296
|
+
help=(
|
|
297
|
+
"Composition mode: 'single' generates one stack (default), "
|
|
298
|
+
"'full' generates a complete project with root config, "
|
|
299
|
+
"'incremental' adds stacks to an existing project"
|
|
300
|
+
),
|
|
301
|
+
),
|
|
290
302
|
)
|
{thothctl-0.25.7 → thothctl-0.26.0}/src/thothctl/services/ai_review/providers/bedrock_provider.py
RENAMED
|
@@ -25,8 +25,17 @@ class BedrockProvider:
|
|
|
25
25
|
if self._client is None:
|
|
26
26
|
try:
|
|
27
27
|
import boto3
|
|
28
|
+
from botocore.config import Config
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
# IaC generation responses can be large; increase read timeout
|
|
31
|
+
config = Config(
|
|
32
|
+
read_timeout=300,
|
|
33
|
+
connect_timeout=10,
|
|
34
|
+
retries={"max_attempts": 2},
|
|
35
|
+
)
|
|
36
|
+
self._client = boto3.client(
|
|
37
|
+
"bedrock-runtime", region_name=self.region, config=config
|
|
38
|
+
)
|
|
30
39
|
except ImportError:
|
|
31
40
|
raise ImportError(
|
|
32
41
|
"boto3 package required. Install with: pip install boto3"
|
|
@@ -131,15 +131,20 @@ class RulesCompiler:
|
|
|
131
131
|
|
|
132
132
|
deny_or_warn = "deny" if severity == "error" else "warn"
|
|
133
133
|
|
|
134
|
+
type_filter = ""
|
|
135
|
+
if resource_types:
|
|
136
|
+
types_list = ", ".join(f'"{t}"' for t in resource_types)
|
|
137
|
+
type_filter = (
|
|
138
|
+
f"\n allowed_types := [{types_list}]"
|
|
139
|
+
f"\n resource_type == allowed_types[_]"
|
|
140
|
+
)
|
|
141
|
+
|
|
134
142
|
rego_rule = textwrap.dedent(
|
|
135
143
|
f"""\
|
|
136
144
|
# Rule: {name}
|
|
137
|
-
{deny_or_warn}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
resource_type := resource_types[_]
|
|
141
|
-
{"type_check := " + repr(resource_types) + chr(10) + " resource_type == type_check[_]" if resource_types else ""}
|
|
142
|
-
instances := resource_block[resource_type]
|
|
145
|
+
{deny_or_warn} contains msg if {{
|
|
146
|
+
resource_type := object.keys(input.resource)[_]{type_filter}
|
|
147
|
+
instances := input.resource[resource_type]
|
|
143
148
|
instance_name := object.keys(instances)[_]
|
|
144
149
|
not regex.match(`{pattern}`, instance_name)
|
|
145
150
|
msg := sprintf("{name}: resource '%s.%s' does not match naming pattern '{pattern}'", [resource_type, instance_name])
|
|
@@ -194,12 +199,11 @@ class RulesCompiler:
|
|
|
194
199
|
rego_rule = textwrap.dedent(
|
|
195
200
|
f"""\
|
|
196
201
|
# Rule: {name}
|
|
197
|
-
{deny_or_warn}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
{type_filter_line} instances := resource_block[resource_type]
|
|
202
|
+
{deny_or_warn} contains msg if {{
|
|
203
|
+
resource_type := object.keys(input.resource)[_]
|
|
204
|
+
{type_filter_line} instances := input.resource[resource_type]
|
|
201
205
|
instance_name := object.keys(instances)[_]
|
|
202
|
-
instance := instances[instance_name]
|
|
206
|
+
instance := instances[instance_name][_]
|
|
203
207
|
required_tags := [{tags_str}]
|
|
204
208
|
required_tag := required_tags[_]
|
|
205
209
|
not instance.tags[required_tag]
|
|
@@ -248,12 +252,11 @@ class RulesCompiler:
|
|
|
248
252
|
rego_rule = textwrap.dedent(
|
|
249
253
|
f"""\
|
|
250
254
|
# Rule: {rule_id} — banned pattern: {pattern}
|
|
251
|
-
{deny_or_warn}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
instances := resource_block[resource_type]
|
|
255
|
+
{deny_or_warn} contains msg if {{
|
|
256
|
+
resource_type := object.keys(input.resource)[_]
|
|
257
|
+
instances := input.resource[resource_type]
|
|
255
258
|
instance_name := object.keys(instances)[_]
|
|
256
|
-
instance := instances[instance_name]
|
|
259
|
+
instance := instances[instance_name][_]
|
|
257
260
|
walk(instance, [path, value])
|
|
258
261
|
key_str := concat(".", path)
|
|
259
262
|
val_str := sprintf("%v", [value])
|
|
@@ -306,14 +309,13 @@ class RulesCompiler:
|
|
|
306
309
|
rego_rule = textwrap.dedent(
|
|
307
310
|
f"""\
|
|
308
311
|
# Rule: {name} — require multi-AZ for databases
|
|
309
|
-
{deny_or_warn}
|
|
310
|
-
resource_block := input.resource[_]
|
|
311
|
-
resource_type := object.keys(resource_block)[_]
|
|
312
|
+
{deny_or_warn} contains msg if {{
|
|
312
313
|
db_types := [{types_str}]
|
|
313
|
-
resource_type
|
|
314
|
-
|
|
314
|
+
resource_type := db_types[_]
|
|
315
|
+
input.resource[resource_type]
|
|
316
|
+
instances := input.resource[resource_type]
|
|
315
317
|
instance_name := object.keys(instances)[_]
|
|
316
|
-
instance := instances[instance_name]
|
|
318
|
+
instance := instances[instance_name][_]
|
|
317
319
|
not instance.multi_az == true
|
|
318
320
|
msg := sprintf("{name}: resource '%s.%s' should have multi_az = true", [resource_type, instance_name])
|
|
319
321
|
}}
|
|
@@ -328,7 +330,7 @@ class RulesCompiler:
|
|
|
328
330
|
rego_rule = textwrap.dedent(
|
|
329
331
|
f"""\
|
|
330
332
|
# Rule: {name} — require module: {mod}
|
|
331
|
-
{deny_or_warn}
|
|
333
|
+
{deny_or_warn} contains msg if {{
|
|
332
334
|
modules := object.get(input, "module", [])
|
|
333
335
|
module_sources := [src |
|
|
334
336
|
mod_block := modules[_]
|
|
@@ -348,7 +350,7 @@ class RulesCompiler:
|
|
|
348
350
|
rego_rule = textwrap.dedent(
|
|
349
351
|
f"""\
|
|
350
352
|
# Rule: {name} — max {max_resources} resources per file
|
|
351
|
-
{deny_or_warn}
|
|
353
|
+
{deny_or_warn} contains msg if {{
|
|
352
354
|
resources := input.resource
|
|
353
355
|
count(resources) > {max_resources}
|
|
354
356
|
msg := sprintf("{name}: file has %d resources (max {max_resources})", [count(resources)])
|
|
@@ -58,6 +58,8 @@ class CodeGenerator:
|
|
|
58
58
|
config = settings.get_provider_config(provider_name)
|
|
59
59
|
if model:
|
|
60
60
|
config.model = model
|
|
61
|
+
# IaC generation needs higher token limit than review (full modules)
|
|
62
|
+
config.max_tokens = max(config.max_tokens, 16000)
|
|
61
63
|
self._provider = cls(config)
|
|
62
64
|
logger.info(
|
|
63
65
|
f"AI provider initialized: {provider_name} (model: {config.model})"
|
|
@@ -91,7 +93,15 @@ class CodeGenerator:
|
|
|
91
93
|
|
|
92
94
|
try:
|
|
93
95
|
raw_result = self._provider.analyze(system_prompt, intent)
|
|
94
|
-
|
|
96
|
+
output = self._parse_response(raw_result)
|
|
97
|
+
|
|
98
|
+
# Retry once if parsing failed (model sometimes returns malformed JSON)
|
|
99
|
+
if not output.files and output.raw_response:
|
|
100
|
+
logger.warning("First attempt returned no files — retrying generation")
|
|
101
|
+
raw_result = self._provider.analyze(system_prompt, intent)
|
|
102
|
+
output = self._parse_response(raw_result)
|
|
103
|
+
|
|
104
|
+
return output
|
|
95
105
|
except Exception as e:
|
|
96
106
|
logger.error(f"AI generation failed: {e}")
|
|
97
107
|
return GenerationOutput(
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"""Composition models for multi-stack Intent-to-IaC decomposition.
|
|
2
|
+
|
|
3
|
+
Defines the data structures used to represent a decomposed infrastructure
|
|
4
|
+
intent as a collection of ordered stacks organized by architectural layers.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from collections import deque
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
from typing import Dict, List, Optional
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Canonical layer ordering (lower index = deployed first)
|
|
13
|
+
LAYER_ORDER: Dict[str, int] = {
|
|
14
|
+
"foundation": 0,
|
|
15
|
+
"platform": 1,
|
|
16
|
+
"application": 2,
|
|
17
|
+
"observability": 3,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class StackPlan:
|
|
23
|
+
"""A single infrastructure stack within a composition plan.
|
|
24
|
+
|
|
25
|
+
Represents one logical unit of IaC (e.g., VPC, EKS cluster, RDS)
|
|
26
|
+
that maps to a directory of Terraform/Terragrunt files.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
name: str # e.g., 'vpc'
|
|
30
|
+
layer: str # foundation | platform | application | observability
|
|
31
|
+
domain: str # e.g., 'networking', 'data', 'compute'
|
|
32
|
+
intent: str # Specific intent for this stack
|
|
33
|
+
depends_on: List[str] = field(default_factory=list) # Stack names
|
|
34
|
+
module_source: Optional[str] = None # Official module if applicable
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def path(self) -> str:
|
|
38
|
+
"""Return the relative directory path for this stack."""
|
|
39
|
+
return f"stacks/{self.layer}/{self.domain}/{self.name}"
|
|
40
|
+
|
|
41
|
+
def __repr__(self) -> str:
|
|
42
|
+
"""Return a concise string representation."""
|
|
43
|
+
deps = ", ".join(self.depends_on) if self.depends_on else "none"
|
|
44
|
+
return (
|
|
45
|
+
f"StackPlan(name={self.name!r}, layer={self.layer!r}, "
|
|
46
|
+
f"domain={self.domain!r}, depends_on=[{deps}])"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass
|
|
51
|
+
class CompositionPlan:
|
|
52
|
+
"""A full decomposition of an intent into ordered stacks.
|
|
53
|
+
|
|
54
|
+
Contains all stacks needed to fulfil the user's infrastructure intent,
|
|
55
|
+
organized by layer with dependency information for correct ordering.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
stacks: List[StackPlan] = field(default_factory=list)
|
|
59
|
+
project_type: str = "terraform"
|
|
60
|
+
needs_root_config: bool = True
|
|
61
|
+
needs_common: bool = True
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def stack_count(self) -> int:
|
|
65
|
+
"""Return the total number of stacks in the plan."""
|
|
66
|
+
return len(self.stacks)
|
|
67
|
+
|
|
68
|
+
def get_stacks_by_layer(self, layer: str) -> List[StackPlan]:
|
|
69
|
+
"""Return all stacks belonging to the specified layer.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
layer: One of foundation, platform, application, observability.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
List of StackPlan objects in the given layer.
|
|
76
|
+
"""
|
|
77
|
+
return [s for s in self.stacks if s.layer == layer]
|
|
78
|
+
|
|
79
|
+
def topological_order(self) -> List[StackPlan]:
|
|
80
|
+
"""Return stacks in dependency-resolved order (Kahn's algorithm).
|
|
81
|
+
|
|
82
|
+
Stacks with no dependencies come first (foundation layer),
|
|
83
|
+
followed by stacks whose dependencies have already been resolved.
|
|
84
|
+
Ties within the same depth are broken by layer order, then name.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
List of StackPlan in topological (deployment) order.
|
|
88
|
+
|
|
89
|
+
Raises:
|
|
90
|
+
ValueError: If a circular dependency is detected.
|
|
91
|
+
"""
|
|
92
|
+
if not self.stacks:
|
|
93
|
+
return []
|
|
94
|
+
|
|
95
|
+
# Build adjacency and in-degree maps by stack name
|
|
96
|
+
name_to_stack: Dict[str, StackPlan] = {s.name: s for s in self.stacks}
|
|
97
|
+
in_degree: Dict[str, int] = {s.name: 0 for s in self.stacks}
|
|
98
|
+
dependents: Dict[str, List[str]] = {s.name: [] for s in self.stacks}
|
|
99
|
+
|
|
100
|
+
for stack in self.stacks:
|
|
101
|
+
for dep in stack.depends_on:
|
|
102
|
+
if dep in name_to_stack:
|
|
103
|
+
in_degree[stack.name] += 1
|
|
104
|
+
dependents[dep].append(stack.name)
|
|
105
|
+
|
|
106
|
+
# Initialize queue with zero in-degree nodes
|
|
107
|
+
queue: deque = deque(
|
|
108
|
+
sorted(
|
|
109
|
+
[name for name, deg in in_degree.items() if deg == 0],
|
|
110
|
+
key=lambda n: (
|
|
111
|
+
LAYER_ORDER.get(name_to_stack[n].layer, 99),
|
|
112
|
+
n,
|
|
113
|
+
),
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
result: List[StackPlan] = []
|
|
118
|
+
while queue:
|
|
119
|
+
current = queue.popleft()
|
|
120
|
+
result.append(name_to_stack[current])
|
|
121
|
+
|
|
122
|
+
# Collect and sort newly available nodes for determinism
|
|
123
|
+
newly_available: List[str] = []
|
|
124
|
+
for dependent in dependents[current]:
|
|
125
|
+
in_degree[dependent] -= 1
|
|
126
|
+
if in_degree[dependent] == 0:
|
|
127
|
+
newly_available.append(dependent)
|
|
128
|
+
|
|
129
|
+
# Sort by layer order then name for stable output
|
|
130
|
+
newly_available.sort(
|
|
131
|
+
key=lambda n: (
|
|
132
|
+
LAYER_ORDER.get(name_to_stack[n].layer, 99),
|
|
133
|
+
n,
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
queue.extend(newly_available)
|
|
137
|
+
|
|
138
|
+
if len(result) != len(self.stacks):
|
|
139
|
+
resolved = {s.name for s in result}
|
|
140
|
+
unresolved = [s.name for s in self.stacks if s.name not in resolved]
|
|
141
|
+
raise ValueError(f"Circular dependency detected among stacks: {unresolved}")
|
|
142
|
+
|
|
143
|
+
return result
|
|
144
|
+
|
|
145
|
+
def validate(self) -> List[str]:
|
|
146
|
+
"""Validate the composition plan for common issues.
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
List of warning/error messages (empty if valid).
|
|
150
|
+
"""
|
|
151
|
+
issues: List[str] = []
|
|
152
|
+
valid_layers = set(LAYER_ORDER.keys())
|
|
153
|
+
known_names = {s.name for s in self.stacks}
|
|
154
|
+
|
|
155
|
+
for stack in self.stacks:
|
|
156
|
+
if stack.layer not in valid_layers:
|
|
157
|
+
issues.append(
|
|
158
|
+
f"Stack '{stack.name}' has invalid layer "
|
|
159
|
+
f"'{stack.layer}'. Must be one of: "
|
|
160
|
+
f"{', '.join(valid_layers)}"
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
for dep in stack.depends_on:
|
|
164
|
+
if dep not in known_names:
|
|
165
|
+
issues.append(
|
|
166
|
+
f"Stack '{stack.name}' depends on unknown stack '{dep}'"
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
# Check layer ordering consistency
|
|
170
|
+
for dep in stack.depends_on:
|
|
171
|
+
if dep in known_names:
|
|
172
|
+
dep_stack = next(s for s in self.stacks if s.name == dep)
|
|
173
|
+
dep_order = LAYER_ORDER.get(dep_stack.layer, 99)
|
|
174
|
+
self_order = LAYER_ORDER.get(stack.layer, 99)
|
|
175
|
+
if dep_order > self_order:
|
|
176
|
+
issues.append(
|
|
177
|
+
f"Stack '{stack.name}' ({stack.layer}) "
|
|
178
|
+
f"depends on '{dep}' ({dep_stack.layer}) "
|
|
179
|
+
f"which is in a higher layer"
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
return issues
|