thothctl 0.30.3__tar.gz → 0.31.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.
Files changed (596) hide show
  1. {thothctl-0.30.3 → thothctl-0.31.0}/PKG-INFO +1 -1
  2. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/init/commands/env.py +47 -2
  3. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/init/commands/project.py +27 -0
  4. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/common/.thothcf_module.toml +2 -1
  5. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/document/iac_grunt_graph.py +139 -7
  6. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_template/project_templates.py +3 -0
  7. thothctl-0.31.0/src/thothctl/services/init/environment/install_skills.py +212 -0
  8. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/convert/get_project_data.py +1 -0
  9. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/version.py +1 -1
  10. thothctl-0.31.0/tests/test_install_skills.py +110 -0
  11. {thothctl-0.30.3 → thothctl-0.31.0}/.devcontainer/Dockerfile +0 -0
  12. {thothctl-0.30.3 → thothctl-0.31.0}/.devcontainer/README.md +0 -0
  13. {thothctl-0.30.3 → thothctl-0.31.0}/.devcontainer/devcontainer.json +0 -0
  14. {thothctl-0.30.3 → thothctl-0.31.0}/.github/workflows/docs.yml +0 -0
  15. {thothctl-0.30.3 → thothctl-0.31.0}/.github/workflows/python-publish.yml +0 -0
  16. {thothctl-0.30.3 → thothctl-0.31.0}/.gitignore +0 -0
  17. {thothctl-0.30.3 → thothctl-0.31.0}/.pre-commit-config.yaml +0 -0
  18. {thothctl-0.30.3 → thothctl-0.31.0}/.pydocstyle +0 -0
  19. {thothctl-0.30.3 → thothctl-0.31.0}/.readthedocs.yaml +0 -0
  20. {thothctl-0.30.3 → thothctl-0.31.0}/CHANGELOG.md +0 -0
  21. {thothctl-0.30.3 → thothctl-0.31.0}/CONTRIBUTING.md +0 -0
  22. {thothctl-0.30.3 → thothctl-0.31.0}/Dockerfile +0 -0
  23. {thothctl-0.30.3 → thothctl-0.31.0}/LICENSE +0 -0
  24. {thothctl-0.30.3 → thothctl-0.31.0}/README.md +0 -0
  25. {thothctl-0.30.3 → thothctl-0.31.0}/__init__.py +0 -0
  26. {thothctl-0.30.3 → thothctl-0.31.0}/docs/catalog/catalog-info.yaml +0 -0
  27. {thothctl-0.30.3 → thothctl-0.31.0}/docs/dashboard/README.md +0 -0
  28. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/ai-review/README.md +0 -0
  29. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/ai-review/agent_specifications.md +0 -0
  30. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/ai-review/agentcore.md +0 -0
  31. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/check/blast-radius.md +0 -0
  32. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/check/check_environment.md +0 -0
  33. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/check/check_iac.md +0 -0
  34. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/check/check_overview.md +0 -0
  35. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/check/check_project_iac.md +0 -0
  36. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/check/check_space.md +0 -0
  37. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/check/cost-analysis-quick-reference.md +0 -0
  38. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/check/cost-analysis.md +0 -0
  39. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/check/customizing_rules.md +0 -0
  40. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/check/deps-advanced.md +0 -0
  41. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/check/deps.md +0 -0
  42. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/check/drift-detection.md +0 -0
  43. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/check/plan.md +0 -0
  44. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/dashboard/dashboard_overview.md +0 -0
  45. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/document/customizing_docs.md +0 -0
  46. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/document/document_iac.md +0 -0
  47. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/document/document_overview.md +0 -0
  48. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/document/iac.md +0 -0
  49. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/document/mermaid_examples.md +0 -0
  50. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/document/mermaid_quickref.md +0 -0
  51. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/document/use_cases.md +0 -0
  52. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/generate/generate_components.md +0 -0
  53. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/generate/generate_iac.md +0 -0
  54. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/generate/generate_stacks.md +0 -0
  55. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/init/init.md +0 -0
  56. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/init/init_space.md +0 -0
  57. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/inventory/CHANGELOG.md +0 -0
  58. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/inventory/frameworks/terraform.md +0 -0
  59. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/inventory/frameworks/terragrunt.md +0 -0
  60. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/inventory/iac.md +0 -0
  61. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/inventory/inventory_iac.md +0 -0
  62. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/inventory/inventory_overview.md +0 -0
  63. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/list/list_overview.md +0 -0
  64. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/list/list_projects.md +0 -0
  65. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/list/list_spaces.md +0 -0
  66. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/mcp/mcp.md +0 -0
  67. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/project/iac.md +0 -0
  68. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/project/project_cleanup.md +0 -0
  69. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/project/project_convert.md +0 -0
  70. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/project/project_overview.md +0 -0
  71. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/project/project_upgrade.md +0 -0
  72. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/project/use_cases.md +0 -0
  73. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/remove/remove_overview.md +0 -0
  74. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/remove/remove_project.md +0 -0
  75. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/remove/remove_space.md +0 -0
  76. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/scan/iac.md +0 -0
  77. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/scan/scan_iac.md +0 -0
  78. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/scan/scan_overview.md +0 -0
  79. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/scan/use_cases.md +0 -0
  80. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/space/space_overview.md +0 -0
  81. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/upgrade/upgrade_overview.md +0 -0
  82. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/workflow/workflow_devsecops.md +0 -0
  83. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/commands/workflow/workflow_overview.md +0 -0
  84. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/concepts.md +0 -0
  85. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/cross_platform_support.md +0 -0
  86. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/framework_architecture.md +0 -0
  87. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/infrastructure_composition.md +0 -0
  88. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/policy_as_code.md +0 -0
  89. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/roadmap_fdi.md +0 -0
  90. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/software_architecture.md +0 -0
  91. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/space_configuration.md +0 -0
  92. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/specs/phase1.10_plan_validation.md +0 -0
  93. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/specs/phase1.9_composition_generation.md +0 -0
  94. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/specs/phase1_intent_to_iac.md +0 -0
  95. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/specs/phase2.5.1_autonomy_model.md +0 -0
  96. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/use_cases/README.md +0 -0
  97. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/use_cases/ai_dlc.md +0 -0
  98. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/use_cases/check_command.md +0 -0
  99. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/use_cases/devsecops_quickstart.md +0 -0
  100. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/use_cases/devsecops_sdlc.md +0 -0
  101. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/use_cases/inventory_command.md +0 -0
  102. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/use_cases/platform_engineering_templates.md +0 -0
  103. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/use_cases/space_management.md +0 -0
  104. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/use_cases/tasks/create_template.md +0 -0
  105. {thothctl-0.30.3 → thothctl-0.31.0}/docs/framework/use_cases/tasks/workflow_implementation_plan.md +0 -0
  106. {thothctl-0.30.3 → thothctl-0.31.0}/docs/how_it_works.md +0 -0
  107. {thothctl-0.30.3 → thothctl-0.31.0}/docs/img/commnad_init.png +0 -0
  108. {thothctl-0.30.3 → thothctl-0.31.0}/docs/img/framework/thothforge-framework.svg +0 -0
  109. {thothctl-0.30.3 → thothctl-0.31.0}/docs/img/framework/thothfr.png +0 -0
  110. {thothctl-0.30.3 → thothctl-0.31.0}/docs/img/icon-light.png +0 -0
  111. {thothctl-0.30.3 → thothctl-0.31.0}/docs/img/icon.png +0 -0
  112. {thothctl-0.30.3 → thothctl-0.31.0}/docs/img/init_project.gif +0 -0
  113. {thothctl-0.30.3 → thothctl-0.31.0}/docs/img/stable/scan_report_example.png +0 -0
  114. {thothctl-0.30.3 → thothctl-0.31.0}/docs/includes/abbreviations.md +0 -0
  115. {thothctl-0.30.3 → thothctl-0.31.0}/docs/index.md +0 -0
  116. {thothctl-0.30.3 → thothctl-0.31.0}/docs/installation/devcontainer_setup.md +0 -0
  117. {thothctl-0.30.3 → thothctl-0.31.0}/docs/installation/linux_installation.md +0 -0
  118. {thothctl-0.30.3 → thothctl-0.31.0}/docs/installation/windows_installation.md +0 -0
  119. {thothctl-0.30.3 → thothctl-0.31.0}/docs/javascripts/tablesort.js +0 -0
  120. {thothctl-0.30.3 → thothctl-0.31.0}/docs/mcp.md +0 -0
  121. {thothctl-0.30.3 → thothctl-0.31.0}/docs/navigation.md +0 -0
  122. {thothctl-0.30.3 → thothctl-0.31.0}/docs/quick_start.md +0 -0
  123. {thothctl-0.30.3 → thothctl-0.31.0}/docs/requirements.txt +0 -0
  124. {thothctl-0.30.3 → thothctl-0.31.0}/docs/stylesheets/extra-enhanced.css +0 -0
  125. {thothctl-0.30.3 → thothctl-0.31.0}/docs/stylesheets/extra.css +0 -0
  126. {thothctl-0.30.3 → thothctl-0.31.0}/docs/telemetry.md +0 -0
  127. {thothctl-0.30.3 → thothctl-0.31.0}/docs/template_engine/cli_commands_audit.md +0 -0
  128. {thothctl-0.30.3 → thothctl-0.31.0}/docs/template_engine/for_developers.md +0 -0
  129. {thothctl-0.30.3 → thothctl-0.31.0}/docs/template_engine/for_platform_engineers.md +0 -0
  130. {thothctl-0.30.3 → thothctl-0.31.0}/docs/template_engine/github_templates.md +0 -0
  131. {thothctl-0.30.3 → thothctl-0.31.0}/docs/template_engine/template_engine.md +0 -0
  132. {thothctl-0.30.3 → thothctl-0.31.0}/docs/toolkit_overview.md +0 -0
  133. {thothctl-0.30.3 → thothctl-0.31.0}/docs/troubleshooting/linux_troubleshooting.md +0 -0
  134. {thothctl-0.30.3 → thothctl-0.31.0}/docs/troubleshooting/macos_troubleshooting.md +0 -0
  135. {thothctl-0.30.3 → thothctl-0.31.0}/docs/troubleshooting/troubleshooting.md +0 -0
  136. {thothctl-0.30.3 → thothctl-0.31.0}/docs/troubleshooting/windows_troubleshooting.md +0 -0
  137. {thothctl-0.30.3 → thothctl-0.31.0}/docs/whats_new.md +0 -0
  138. {thothctl-0.30.3 → thothctl-0.31.0}/mkdocs.yaml +0 -0
  139. {thothctl-0.30.3 → thothctl-0.31.0}/pyproject.toml +0 -0
  140. {thothctl-0.30.3 → thothctl-0.31.0}/scripts/check_output_consistency.py +0 -0
  141. {thothctl-0.30.3 → thothctl-0.31.0}/scripts/run_mcp_server.sh +0 -0
  142. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/__init__.py +0 -0
  143. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/application/__init__.py +0 -0
  144. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/autocomplete.py +0 -0
  145. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/cli.py +0 -0
  146. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/__init__.py +0 -0
  147. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/ai_review/__init__.py +0 -0
  148. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/ai_review/cli.py +0 -0
  149. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/ai_review/commands/__init__.py +0 -0
  150. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/ai_review/commands/analyze.py +0 -0
  151. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/ai_review/commands/apply_fix.py +0 -0
  152. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/ai_review/commands/configure.py +0 -0
  153. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/ai_review/commands/configure_decisions.py +0 -0
  154. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/ai_review/commands/decide.py +0 -0
  155. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/ai_review/commands/history.py +0 -0
  156. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/ai_review/commands/improve.py +0 -0
  157. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/ai_review/commands/orchestrate.py +0 -0
  158. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/ai_review/commands/override.py +0 -0
  159. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/ai_review/commands/report.py +0 -0
  160. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/ai_review/commands/serve.py +0 -0
  161. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/check/__init__.py +0 -0
  162. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/check/cli.py +0 -0
  163. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/check/commands/__init__.py +0 -0
  164. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/check/commands/config.py +0 -0
  165. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/check/commands/environment.py +0 -0
  166. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/check/commands/iac.py +0 -0
  167. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/check/commands/project/__init__.py +0 -0
  168. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/check/commands/project/iac.py +0 -0
  169. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/check/commands/project.py +0 -0
  170. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/check/commands/space.py +0 -0
  171. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/dashboard/__init__.py +0 -0
  172. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/dashboard/cli.py +0 -0
  173. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/dashboard/commands/__init__.py +0 -0
  174. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/dashboard/commands/launch.py +0 -0
  175. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/document/__init__.py +0 -0
  176. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/document/cli.py +0 -0
  177. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/document/commands/__init__.py +0 -0
  178. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/document/commands/iac.py +0 -0
  179. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/generate/__init__.py +0 -0
  180. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/generate/cli.py +0 -0
  181. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/generate/commands/__init__.py +0 -0
  182. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/generate/commands/component.py +0 -0
  183. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/generate/commands/iac.py +0 -0
  184. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/generate/commands/stacks.py +0 -0
  185. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/init/__init__.py +0 -0
  186. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/init/cli.py +0 -0
  187. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/init/commands/__init__.py +0 -0
  188. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/init/commands/space.py +0 -0
  189. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/init/commands/template.py +0 -0
  190. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/inventory/__init__.py +0 -0
  191. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/inventory/cli.py +0 -0
  192. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/inventory/commands/__init__.py +0 -0
  193. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/inventory/commands/check.py +0 -0
  194. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/inventory/commands/iac.py +0 -0
  195. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/list/__init__.py +0 -0
  196. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/list/cli.py +0 -0
  197. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/list/commands/__init__.py +0 -0
  198. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/list/commands/projects.py +0 -0
  199. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/list/commands/spaces.py +0 -0
  200. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/list/commands/templates.py +0 -0
  201. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/mcp/__init__.py +0 -0
  202. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/mcp/cli.py +0 -0
  203. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/mcp/commands/__init__.py +0 -0
  204. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/mcp/commands/register.py +0 -0
  205. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/mcp/commands/server.py +0 -0
  206. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/mcp/commands/status.py +0 -0
  207. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/mcp/commands/stop.py +0 -0
  208. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/project/__init__.py +0 -0
  209. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/project/cli.py +0 -0
  210. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/project/commands/__init__.py +0 -0
  211. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/project/commands/bootstrap.py +0 -0
  212. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/project/commands/cleanup.py +0 -0
  213. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/project/commands/convert.py +0 -0
  214. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/project/commands/upgrade.py +0 -0
  215. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/quickstart/__init__.py +0 -0
  216. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/quickstart/cli.py +0 -0
  217. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/remove/__init__.py +0 -0
  218. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/remove/cli.py +0 -0
  219. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/remove/project.py +0 -0
  220. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/remove/space.py +0 -0
  221. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/scan/__init__.py +0 -0
  222. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/scan/cli.py +0 -0
  223. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/scan/commands/__init__.py +0 -0
  224. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/scan/commands/iac.py +0 -0
  225. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/space/__init__.py +0 -0
  226. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/space/cli.py +0 -0
  227. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/space/commands/__init__.py +0 -0
  228. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/space/commands/activate.py +0 -0
  229. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/space/commands/deactivate.py +0 -0
  230. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/space/commands/export_space.py +0 -0
  231. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/space/commands/import_space.py +0 -0
  232. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/space/commands/show.py +0 -0
  233. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/space/commands/update.py +0 -0
  234. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/upgrade/cli.py +0 -0
  235. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/workflow/__init__.py +0 -0
  236. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/workflow/cli.py +0 -0
  237. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/workflow/commands/__init__.py +0 -0
  238. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/workflow/commands/devsecops.py +0 -0
  239. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/commands/workflow/commands/run.py +0 -0
  240. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/common/.thothcf.setup.toml +0 -0
  241. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/common/.thothcf_home.toml +0 -0
  242. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/common/.thothcf_project.toml +0 -0
  243. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/common/.thothcf_template_parameters.toml +0 -0
  244. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/common/__init__.py +0 -0
  245. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/common/common.py +0 -0
  246. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/common/terragrunt/.thothcf_project.toml +0 -0
  247. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/config/__init__.py +0 -0
  248. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/config/constants.py +0 -0
  249. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/config/default_values.py +0 -0
  250. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/config/defaults.py +0 -0
  251. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/config/models.py +0 -0
  252. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/config/settings.py +0 -0
  253. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/config/template_config.py +0 -0
  254. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/config/template_configs.py +0 -0
  255. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/config/templates.py +0 -0
  256. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/config/validation.py +0 -0
  257. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/__init__.py +0 -0
  258. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/cli_ui.py +0 -0
  259. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/commands.py +0 -0
  260. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/config.py +0 -0
  261. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/integrations/__init__.py +0 -0
  262. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/integrations/azure_devops/__init__.py +0 -0
  263. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/integrations/azure_devops/get_azure_devops.py +0 -0
  264. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/integrations/azure_devops/pull_request_comments.py +0 -0
  265. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/integrations/github/get_github.py +0 -0
  266. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/integrations/github/pull_request_comments.py +0 -0
  267. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/integrations/integrate_messages_services/__init__.py +0 -0
  268. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/integrations/integrate_messages_services/microsoft_teams.py +0 -0
  269. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/integrations/integrate_messages_services/sent_message_teams.py +0 -0
  270. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/integrations/pattern_names.py +0 -0
  271. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/integrations/pr_comments/__init__.py +0 -0
  272. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/integrations/pr_comments/pr_comment_publisher.py +0 -0
  273. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/logger.py +0 -0
  274. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/telemetry.py +0 -0
  275. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/core/version_tools.py +0 -0
  276. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/domain/__init__.py +0 -0
  277. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/domain/interfaces/__init__.py +0 -0
  278. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/domain/models/__init__.py +0 -0
  279. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/mcp/README.md +0 -0
  280. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/mcp/__init__.py +0 -0
  281. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/mcp/server.py +0 -0
  282. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/__init__.py +0 -0
  283. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/__init__.py +0 -0
  284. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/agentcore/agentcore.json +0 -0
  285. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/ai_agent.py +0 -0
  286. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/analyzers/__init__.py +0 -0
  287. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/analyzers/code_reviewer.py +0 -0
  288. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/analyzers/context_builder.py +0 -0
  289. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/analyzers/report_analyzer.py +0 -0
  290. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/analyzers/risk_assessor.py +0 -0
  291. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/bedrock_agent_api.py +0 -0
  292. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/config/__init__.py +0 -0
  293. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/config/ai_settings.py +0 -0
  294. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/config/autonomy.py +0 -0
  295. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/config/decision_rules.py +0 -0
  296. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/decision_engine.py +0 -0
  297. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/main.py +0 -0
  298. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/memory.py +0 -0
  299. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/orchestrator.py +0 -0
  300. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/pr_decision_publisher.py +0 -0
  301. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/providers/__init__.py +0 -0
  302. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/providers/azure_provider.py +0 -0
  303. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/providers/bedrock_agent_provider.py +0 -0
  304. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/providers/bedrock_provider.py +0 -0
  305. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/providers/kiro_provider.py +0 -0
  306. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/providers/ollama_provider.py +0 -0
  307. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/providers/openai_provider.py +0 -0
  308. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/safety/__init__.py +0 -0
  309. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/safety/safety_guard.py +0 -0
  310. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/strands_agent.py +0 -0
  311. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/tracing.py +0 -0
  312. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/utils/__init__.py +0 -0
  313. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/utils/cost_tracker.py +0 -0
  314. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/utils/fix_patterns.py +0 -0
  315. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/utils/fix_prompts.py +0 -0
  316. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/utils/formatters.py +0 -0
  317. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/ai_review/utils/prompts.py +0 -0
  318. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/__init__.py +0 -0
  319. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/environment/__init__.py +0 -0
  320. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/environment/check_environment.py +0 -0
  321. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/org_policy_loader.py +0 -0
  322. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/__init__.py +0 -0
  323. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/blast_radius_service.py +0 -0
  324. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cfn_blast_radius_service.py +0 -0
  325. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/check_origin_version.py +0 -0
  326. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/check_project_structure.py +0 -0
  327. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/__init__.py +0 -0
  328. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/cost_analyzer.py +0 -0
  329. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/models/__init__.py +0 -0
  330. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/models/cloudformation_mapper.py +0 -0
  331. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/models/cost_models.py +0 -0
  332. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/__init__.py +0 -0
  333. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/aws_pricing_client.py +0 -0
  334. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/base_pricing.py +0 -0
  335. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/__init__.py +0 -0
  336. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/apigateway_pricing.py +0 -0
  337. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/bedrock_pricing.py +0 -0
  338. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/cloudwatch_pricing.py +0 -0
  339. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/dynamodb_pricing.py +0 -0
  340. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/ebs_pricing.py +0 -0
  341. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/ec2_pricing.py +0 -0
  342. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/ecr_pricing.py +0 -0
  343. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/ecs_pricing.py +0 -0
  344. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/eip_pricing.py +0 -0
  345. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/eks_pricing.py +0 -0
  346. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/elb_pricing.py +0 -0
  347. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/free_resources_pricing.py +0 -0
  348. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/kms_pricing.py +0 -0
  349. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/lambda_pricing.py +0 -0
  350. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/msk_pricing.py +0 -0
  351. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/rds_pricing.py +0 -0
  352. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/s3_pricing.py +0 -0
  353. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/secrets_manager_pricing.py +0 -0
  354. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/pricing/providers/vpc_pricing.py +0 -0
  355. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/cost/unified_cost_report.py +0 -0
  356. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/drift/__init__.py +0 -0
  357. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/drift/cfn_drift_service.py +0 -0
  358. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/drift/drift_ai.py +0 -0
  359. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/drift/drift_history.py +0 -0
  360. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/drift/drift_policy.py +0 -0
  361. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/drift/drift_report.py +0 -0
  362. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/drift/drift_service.py +0 -0
  363. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/drift/models.py +0 -0
  364. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/risk_assessment.py +0 -0
  365. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/project/validate_project_structure.py +0 -0
  366. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/rule_merger.py +0 -0
  367. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/rules_compiler.py +0 -0
  368. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/check/stack_optimizer/__init__.py +0 -0
  369. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/dashboard/__init__.py +0 -0
  370. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/dashboard/dashboard_service.py +0 -0
  371. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/dashboard/data_loader.py +0 -0
  372. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/document/__init__.py +0 -0
  373. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/document/architecture_renderer.py +0 -0
  374. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/document/create_documentation.py +0 -0
  375. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/document/files_content.py +0 -0
  376. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/document/files_scan.py +0 -0
  377. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/document/iac_documentation.py +0 -0
  378. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/document/iac_grunt_info.py +0 -0
  379. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/document/topology_generator.py +0 -0
  380. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/__init__.py +0 -0
  381. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_stacks/__init__.py +0 -0
  382. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_stacks/config_generator.py +0 -0
  383. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_stacks/remote_config_generation.py +0 -0
  384. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_stacks/stack_service.py +0 -0
  385. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_stacks/templates/terragrunt.hcl.j2 +0 -0
  386. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_stacks/terragrunt.hcl +0 -0
  387. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_template/__init__.py +0 -0
  388. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_template/config.yaml +0 -0
  389. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_template/create_code.py +0 -0
  390. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_template/create_component.py +0 -0
  391. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_template/create_component_service.py +0 -0
  392. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_template/create_stacks.py +0 -0
  393. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_template/create_template.py +0 -0
  394. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_template/files_content.py +0 -0
  395. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/create_template/github_template_loader.py +0 -0
  396. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/__init__.py +0 -0
  397. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/code_generator.py +0 -0
  398. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/composition_models.py +0 -0
  399. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/context_builder.py +0 -0
  400. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/generation_history.py +0 -0
  401. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/intent_decomposer.py +0 -0
  402. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/intent_service.py +0 -0
  403. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/models.py +0 -0
  404. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/parameter_resolver.py +0 -0
  405. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/plan_runner.py +0 -0
  406. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/plan_validator.py +0 -0
  407. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/project_assembler.py +0 -0
  408. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/prompts.py +0 -0
  409. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/scaffold_loader.py +0 -0
  410. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/state_resolver.py +0 -0
  411. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/generate/intent/validator.py +0 -0
  412. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/init/__init__.py +0 -0
  413. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/init/environment/__init__.py +0 -0
  414. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/init/environment/install_tools.py +0 -0
  415. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/init/environment/prerequisite_checker.py +0 -0
  416. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/init/environment/tool_packs.py +0 -0
  417. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/init/project/__init__.py +0 -0
  418. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/init/project/project.py +0 -0
  419. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/init/space/__init__.py +0 -0
  420. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/init/space/example_space.toml +0 -0
  421. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/init/space/export_import.py +0 -0
  422. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/init/space/inheritance.py +0 -0
  423. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/init/space/space.py +0 -0
  424. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/init/space/terraform_module_cache.py +0 -0
  425. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/__init__.py +0 -0
  426. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/cdk_parsers.py +0 -0
  427. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/cdk_sbom_service.py +0 -0
  428. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/changelog_parser.py +0 -0
  429. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/defectdojo_publisher.py +0 -0
  430. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/dtrack_publisher.py +0 -0
  431. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/inventory_service.py +0 -0
  432. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/models.py +0 -0
  433. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/module_compatibility_service.py +0 -0
  434. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/report_service.py +0 -0
  435. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/schema_compatibility_service.py +0 -0
  436. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/secobserve_publisher.py +0 -0
  437. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/terragrunt_parser.py +0 -0
  438. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/update_versions.py +0 -0
  439. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/inventory/version_service.py +0 -0
  440. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/mcp/README.md +0 -0
  441. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/mcp/__init__.py +0 -0
  442. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/mcp/simple_http_server.py +0 -0
  443. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/mcp/stdio_server.py +0 -0
  444. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/__init__.py +0 -0
  445. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/bootstrap/__init__.py +0 -0
  446. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/bootstrap/bootstrap_service.py +0 -0
  447. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/cleanup/__init__.py +0 -0
  448. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/cleanup/clean_project.py +0 -0
  449. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/cleanup/clean_space.py +0 -0
  450. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/convert/__init__.py +0 -0
  451. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/convert/conversion_service.py +0 -0
  452. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/convert/post_init.py +0 -0
  453. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/convert/project_converter.py +0 -0
  454. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/convert/project_defaults.py +0 -0
  455. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/convert/set_project_parameters.py +0 -0
  456. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/create_terramate/__init__.py +0 -0
  457. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/create_terramate/create_terramate_stacks.py +0 -0
  458. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/create_terramate/detect_changes_stacks.py +0 -0
  459. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/create_terramate/manage_terramate_stacks.py +0 -0
  460. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/upgrade/__init__.py +0 -0
  461. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/project/upgrade/upgrade_service.py +0 -0
  462. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/__init__.py +0 -0
  463. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/compliance_review.py +0 -0
  464. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/import_reports.py +0 -0
  465. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/models.py +0 -0
  466. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/report_parser.py +0 -0
  467. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/sarif_output.py +0 -0
  468. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/scan_history.py +0 -0
  469. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/scan_service.py +0 -0
  470. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/scanners/__init__.py +0 -0
  471. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/scanners/checkov.py +0 -0
  472. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/scanners/kics.py +0 -0
  473. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/scanners/opa.py +0 -0
  474. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/scanners/scan_reports.py +0 -0
  475. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/scanners/scanners.py +0 -0
  476. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/scanners/terraform_compliance.py +0 -0
  477. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/scanners/tfsec.py +0 -0
  478. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/scan/scanners/trivy.py +0 -0
  479. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/workflow/__init__.py +0 -0
  480. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/workflow/custom_workflow_engine.py +0 -0
  481. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/workflow/models.py +0 -0
  482. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/workflow/phases/__init__.py +0 -0
  483. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/workflow/phases/base.py +0 -0
  484. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/workflow/phases/build.py +0 -0
  485. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/workflow/phases/deploy.py +0 -0
  486. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/workflow/phases/develop.py +0 -0
  487. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/workflow/phases/monitor.py +0 -0
  488. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/workflow/phases/plan.py +0 -0
  489. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/workflow/phases/secure.py +0 -0
  490. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/workflow/phases/test.py +0 -0
  491. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/services/workflow/workflow_service.py +0 -0
  492. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/templates/ai_reports/pr_comment.md +0 -0
  493. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/templates/reports/inventory_report.html +0 -0
  494. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/templates/reports/inventory_report.js +0 -0
  495. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/templates/unified_report_styles.css +0 -0
  496. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/__init__.py +0 -0
  497. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/banner.py +0 -0
  498. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/__init__.py +0 -0
  499. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/create_compliance_html_reports.py +0 -0
  500. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/create_html_reports.py +0 -0
  501. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/delete_directory.py +0 -0
  502. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/fix_report_styling.py +0 -0
  503. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/render_scan_report.py +0 -0
  504. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/report_html_utils.py +0 -0
  505. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/templates/dashboard.html +0 -0
  506. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/templates/index_report.html +0 -0
  507. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/templates/individual_report.html +0 -0
  508. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/templates/simple_report.html +0 -0
  509. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/templates/unified_report_styles.css +0 -0
  510. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/templates/unified_scan_report.html +0 -0
  511. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/templates/unified_simple_report.html +0 -0
  512. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/common/templates/xunit_report.html +0 -0
  513. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/crypto.py +0 -0
  514. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/git_changes.py +0 -0
  515. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/manage_backend_resources/__init__.py +0 -0
  516. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/manage_backend_resources/manage_backend_resources.py +0 -0
  517. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/modules_ops/__init__.py +0 -0
  518. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/modules_ops/terraform_module_details.py +0 -0
  519. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/modules_ops/terraform_modules_fetcher.py +0 -0
  520. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/platform_utils.py +0 -0
  521. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/process_hcl/__init__.py +0 -0
  522. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/process_hcl/analyze_terraform_plan.py +0 -0
  523. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/process_hcl/graph_manager.py +0 -0
  524. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/process_hcl/graph_terragrunt_dependencies.py +0 -0
  525. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/process_hcl/process_terraform_file.py +0 -0
  526. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/process_hcl/risk_analyzing_terraform_plan.py +0 -0
  527. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/sync_workspaces/__init__.py +0 -0
  528. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/sync_workspaces/sync_terraform_workspaces.py +0 -0
  529. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/sync_workspaces/sync_terragrunt_workspaces.py +0 -0
  530. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/template_loader.py +0 -0
  531. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/utils/thoth_colors.py +0 -0
  532. {thothctl-0.30.3 → thothctl-0.31.0}/src/thothctl/wellcome_banner.py +0 -0
  533. {thothctl-0.30.3 → thothctl-0.31.0}/tests/conftest.py +0 -0
  534. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_agentcore_entrypoint.py +0 -0
  535. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_ai_apply_fix.py +0 -0
  536. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_ai_autonomy.py +0 -0
  537. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_ai_decision_engine.py +0 -0
  538. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_ai_fix_patterns.py +0 -0
  539. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_ai_memory.py +0 -0
  540. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_ai_orchestrator.py +0 -0
  541. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_ai_pr_decision.py +0 -0
  542. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_ai_safety_guard.py +0 -0
  543. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_aws_pricing_client.py +0 -0
  544. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_azure_devops_pr_comments.py +0 -0
  545. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_bedrock_pricing.py +0 -0
  546. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_cdk_inventory.py +0 -0
  547. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_cdk_language_selection.py +0 -0
  548. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_cfn_blast_radius.py +0 -0
  549. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_cfn_drift_detection.py +0 -0
  550. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_context_steering.py +0 -0
  551. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_cost_analyzer.py +0 -0
  552. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_cost_models.py +0 -0
  553. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_cost_policy_enforcement.py +0 -0
  554. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_cost_pr_comments.py +0 -0
  555. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_dashboard_loading_fix.py +0 -0
  556. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_dashboard_service.py +0 -0
  557. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_defectdojo_publisher.py +0 -0
  558. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_drift.py +0 -0
  559. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_drift_detection.py +0 -0
  560. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_dtrack_publisher.py +0 -0
  561. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_ec2_pricing.py +0 -0
  562. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_generate_iac_codegen.py +0 -0
  563. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_generate_iac_context.py +0 -0
  564. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_generate_iac_prompts.py +0 -0
  565. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_generate_iac_service.py +0 -0
  566. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_generate_iac_validator.py +0 -0
  567. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_github_pr_comments.py +0 -0
  568. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_iac_cost_integration.py +0 -0
  569. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_init_ai_tools.py +0 -0
  570. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_init_template_params.py +0 -0
  571. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_intent_quick_wins.py +0 -0
  572. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_intent_rules_integration.py +0 -0
  573. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_inventory_pr_comments.py +0 -0
  574. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_kics_scanner.py +0 -0
  575. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_kiro_provider.py +0 -0
  576. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_mermaid_edge_labels.py +0 -0
  577. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_new_cost_providers.py +0 -0
  578. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_opa_data_files.py +0 -0
  579. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_parallel_scan.py +0 -0
  580. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_plan_validation.py +0 -0
  581. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_platform_utils.py +0 -0
  582. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_pr_comment_publisher.py +0 -0
  583. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_provider_source_url_fix.py +0 -0
  584. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_provider_versions.py +0 -0
  585. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_rules_compiler.py +0 -0
  586. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_scan_cfn_support.py +0 -0
  587. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_scan_command.py +0 -0
  588. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_scan_pr_comments.py +0 -0
  589. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_space_command.py +0 -0
  590. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_space_management.py +0 -0
  591. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_stack_optimizer.py +0 -0
  592. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_template_url_fix.py +0 -0
  593. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_terragrunt_parser.py +0 -0
  594. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_topology_generator.py +0 -0
  595. {thothctl-0.30.3 → thothctl-0.31.0}/tests/test_workflow_integration.py +0 -0
  596. {thothctl-0.30.3 → thothctl-0.31.0}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: thothctl
3
- Version: 0.30.3
3
+ Version: 0.31.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
@@ -30,17 +30,24 @@ class EnvInitCommand(ClickCommand):
30
30
  operation_system: str,
31
31
  project_type: Optional[str] = None,
32
32
  with_aidlc: bool = False,
33
+ with_skills: Optional[str] = "all",
33
34
  **kwargs,
34
35
  ) -> None:
35
36
  """Execute environment initialization."""
36
37
  if project_type:
37
- self._init_env_with_pack(operation_system, project_type, with_aidlc)
38
+ self._init_env_with_pack(
39
+ operation_system, project_type, with_aidlc, with_skills
40
+ )
38
41
  else:
39
42
  # Legacy behavior: show all tools for manual selection
40
43
  bootstrap_env(so=operation_system)
41
44
 
42
45
  def _init_env_with_pack(
43
- self, operation_system: str, project_type: str, with_aidlc: bool = False
46
+ self,
47
+ operation_system: str,
48
+ project_type: str,
49
+ with_aidlc: bool = False,
50
+ with_skills: Optional[str] = "all",
44
51
  ) -> None:
45
52
  """Initialize environment using project-type tool pack."""
46
53
  from colorama import Fore
@@ -162,6 +169,36 @@ class EnvInitCommand(ClickCommand):
162
169
  # AI-DLC workflow rules (optional)
163
170
  self._handle_aidlc_installation(console, project_type, with_aidlc)
164
171
 
172
+ # AI agent skills (dynamic install from upstream repos)
173
+ self._handle_skills_installation(console, with_skills)
174
+
175
+ def _handle_skills_installation(self, console, with_skills: Optional[str]) -> None:
176
+ """Dynamically install AI agent skills into ./.kiro/skills/.
177
+
178
+ Skills require Kiro, so only install when a .kiro/ directory exists in the
179
+ current working directory.
180
+ """
181
+ from ....services.init.environment.install_skills import (
182
+ install_skills,
183
+ resolve_requested_skills,
184
+ )
185
+
186
+ names = resolve_requested_skills(with_skills or "")
187
+ if not names:
188
+ return
189
+
190
+ kiro_dir = Path.cwd() / ".kiro"
191
+ if not kiro_dir.exists():
192
+ console.print(
193
+ "[yellow]⏭️ Skipping skill install — no .kiro/ in current "
194
+ "directory (skills require Kiro).[/yellow]"
195
+ )
196
+ return
197
+
198
+ console.print()
199
+ console.print(f"[bold]🧠 Installing skill(s): {', '.join(names)}[/bold]")
200
+ install_skills(names, target_dir=str(Path.cwd()))
201
+
165
202
  def _handle_aidlc_installation(
166
203
  self, console, project_type: str, with_aidlc: bool
167
204
  ) -> None:
@@ -268,4 +305,12 @@ cli = EnvInitCommand.as_click_command(
268
305
  help="Install AI-DLC workflow rules for Kiro (.kiro/steering/). "
269
306
  "Non-interactive; in interactive mode, you'll be prompted.",
270
307
  ),
308
+ click.option(
309
+ "--with-skills",
310
+ default="all",
311
+ help="Dynamically install AI agent skills from their upstream repos into "
312
+ "./.kiro/skills/ (requires a .kiro/ directory). Defaults to 'all' "
313
+ "distributable skills. Use a comma-separated list (e.g. 'devsecops') to "
314
+ "select, or 'none' to opt out.",
315
+ ),
271
316
  )
@@ -93,6 +93,7 @@ class ProjectInitCommand(ClickCommand):
93
93
  language: str = None,
94
94
  ai_tools: Optional[str] = None,
95
95
  with_aidlc: bool = False,
96
+ with_skills: Optional[str] = "all",
96
97
  **kwargs,
97
98
  ) -> None:
98
99
  """Execute project initialization"""
@@ -213,6 +214,23 @@ class ProjectInitCommand(ClickCommand):
213
214
 
214
215
  install_aidlc_rules(target_dir=str(project_path))
215
216
 
217
+ # Dynamically install AI agent skills from their upstream repos.
218
+ # Skills live under .kiro/skills/, so only install when Kiro is kept.
219
+ if with_skills and (project_path / ".kiro").exists():
220
+ from ....services.init.environment.install_skills import (
221
+ install_skills,
222
+ resolve_requested_skills,
223
+ )
224
+
225
+ names = resolve_requested_skills(with_skills)
226
+ if names:
227
+ self.ui.print_info(f"🧠 Installing skill(s): {', '.join(names)}")
228
+ install_skills(names, target_dir=str(project_path))
229
+ elif with_skills:
230
+ self.ui.print_warning(
231
+ "Skipping skill install — .kiro/ was not kept (requires Kiro)."
232
+ )
233
+
216
234
  self.ui.print_success(f"✨ Project '{project_name}' initialized successfully!")
217
235
 
218
236
  def _select_template(
@@ -710,4 +728,13 @@ cli = ProjectInitCommand.as_click_command(help="Initialize a new project")(
710
728
  help="Install AI-DLC workflow rules for Kiro (.kiro/steering/). "
711
729
  "Provides structured requirement → design → implementation workflows.",
712
730
  ),
731
+ click.option(
732
+ "--with-skills",
733
+ default="all",
734
+ help="Dynamically install AI agent skills from their upstream repos into "
735
+ ".kiro/skills/ (keeps canonical skills in sync, avoids scaffold drift). "
736
+ "Defaults to 'all' distributable skills. Use a comma-separated list "
737
+ "(e.g. 'devsecops') to select, or 'none' to opt out. Only skills with an "
738
+ "upstream repo are installable; scaffold-bundled skills are left untouched.",
739
+ ),
713
740
  )
@@ -33,7 +33,8 @@ name = "catalog"
33
33
  mandatory = false
34
34
  content = [
35
35
  "catalog-info.yaml",
36
- "mkdocs.yaml"
36
+ "mkdocs.yaml",
37
+ "zensical.toml"
37
38
  ]
38
39
  type= "child"
39
40
  [[project_structure.folders]]
@@ -431,16 +431,23 @@ class DependencyGraphGenerator:
431
431
  def _generate_graph(self, directory: Path) -> Optional[str]:
432
432
  """Generate graph using terragrunt.
433
433
 
434
- Runs `terragrunt dag graph` from the resolved directory:
435
- - For a leaf stack: runs from the stack itself, showing only its
436
- direct dependencies (scoped relative graph).
437
- - For a stacks root: runs from the root, showing the full DAG.
434
+ To show the COMPLETE dependency DAG (full blast radius) for the stack
435
+ being documented, `terragrunt dag graph` is run from the terragrunt
436
+ project root (where ``root.hcl`` lives). Running from a leaf only
437
+ reports that unit's *direct* dependencies, which hides transitive
438
+ dependencies (dependencies-of-dependencies).
439
+
440
+ The full-project DAG from the root is then filtered down to only the
441
+ nodes reachable from the current stack (its transitive dependency
442
+ closure), so each stack's graph shows its complete hierarchy without
443
+ unrelated sibling stacks.
438
444
  """
439
- graph_dir = self._resolve_graph_directory(directory)
445
+ resolved = directory.resolve()
446
+ run_dir, stack_key = self._compute_run_context(resolved)
440
447
 
441
448
  command = ["terragrunt", "dag", "graph", "--non-interactive"]
442
449
 
443
- stdout, stderr, return_code = self.executor.execute(command, graph_dir)
450
+ stdout, stderr, return_code = self.executor.execute(command, run_dir)
444
451
 
445
452
  if return_code != 0:
446
453
  self.logger.error("Terragrunt command failed: %s", stderr)
@@ -454,8 +461,26 @@ class DependencyGraphGenerator:
454
461
  )
455
462
  return None
456
463
 
464
+ # If we ran from the terragrunt root for a specific stack, filter the
465
+ # full DAG down to that stack's transitive dependency closure.
466
+ if stack_key is not None:
467
+ filtered = self._filter_dag_to_stack(stdout, stack_key)
468
+ if filtered is None:
469
+ # Stack not found in DAG or has no dependencies — nothing to render
470
+ self.logger.debug(
471
+ "Stack %s not found in DAG or has no dependencies", stack_key
472
+ )
473
+ return None
474
+ stdout = filtered
475
+ # Re-check for emptiness after filtering (isolated stack)
476
+ if "->" not in stdout.strip():
477
+ self.logger.debug(
478
+ "Isolated stack %s (no dependencies), skipping graph", stack_key
479
+ )
480
+ return None
481
+
457
482
  # Also skip if the only node is "." with no edges (isolated stack)
458
- if '"."' in stripped and "->" not in stripped:
483
+ if '"."' in stdout.strip() and "->" not in stdout.strip():
459
484
  self.logger.debug(
460
485
  "Isolated stack %s (no dependencies), skipping graph", directory
461
486
  )
@@ -516,6 +541,113 @@ class DependencyGraphGenerator:
516
541
  current = parent
517
542
  return directory
518
543
 
544
+ def _compute_run_context(self, directory: Path):
545
+ """Decide where to run `terragrunt dag graph` and which node to focus.
546
+
547
+ Returns a tuple ``(run_dir, stack_key)``:
548
+ - ``run_dir``: directory to run ``terragrunt dag graph`` from.
549
+ - ``stack_key``: the current stack's node key as it appears in the DAG
550
+ produced from ``run_dir`` (i.e. the stack path relative to the
551
+ terragrunt root), or ``None`` when ``directory`` is itself a
552
+ stacks root and the full DAG should be rendered as-is.
553
+
554
+ For a leaf stack we run from the terragrunt root so the DAG includes
555
+ transitive dependencies, then filter to this stack's closure.
556
+ """
557
+ resolved = directory.resolve()
558
+
559
+ # Is this directory itself a stacks root (has multiple child units)?
560
+ child_hcl_files = [
561
+ f
562
+ for f in resolved.rglob("terragrunt.hcl")
563
+ if ".terragrunt-cache" not in str(f) and f.parent != resolved
564
+ ]
565
+ if len(child_hcl_files) > 1:
566
+ # Already a root/aggregate context — render the full DAG as-is.
567
+ return resolved, None
568
+
569
+ # Leaf stack: run from the terragrunt root for the complete DAG.
570
+ root = self._find_terragrunt_root(resolved)
571
+ if root == resolved:
572
+ # No root.hcl found above — fall back to running from the leaf.
573
+ return resolved, None
574
+
575
+ try:
576
+ stack_key = str(resolved.relative_to(root))
577
+ except ValueError:
578
+ # resolved is not under root — fall back to leaf behavior.
579
+ return resolved, None
580
+
581
+ return root, stack_key
582
+
583
+ def _filter_dag_to_stack(self, dot_content: str, stack_key: str):
584
+ """Filter a full-project DAG to a stack's transitive dependency closure.
585
+
586
+ Parses the DOT graph, performs a DFS from ``stack_key`` following
587
+ dependency edges, and emits a new DOT containing only the reachable
588
+ nodes/edges. The focal stack's node is relabeled to ``"."`` so the
589
+ downstream path-simplification (which maps ``"."`` to the stack name)
590
+ continues to work.
591
+
592
+ Returns the filtered DOT string, or ``None`` if the stack has no
593
+ node in the graph or no dependency edges.
594
+ """
595
+ import re
596
+
597
+ # Normalize key (strip any trailing slash)
598
+ stack_key = stack_key.rstrip("/")
599
+
600
+ # Parse edges: source -> target
601
+ adjacency = {}
602
+ all_nodes = set()
603
+ edge_re = re.compile(r'"([^"]+)"\s*->\s*"([^"]+)"')
604
+ node_re = re.compile(r'^\s*"([^"]+)"\s*;')
605
+ for line in dot_content.split("\n"):
606
+ m = edge_re.search(line)
607
+ if m:
608
+ src, dst = m.group(1), m.group(2)
609
+ adjacency.setdefault(src, set()).add(dst)
610
+ all_nodes.add(src)
611
+ all_nodes.add(dst)
612
+ continue
613
+ nm = node_re.match(line)
614
+ if nm:
615
+ all_nodes.add(nm.group(1))
616
+
617
+ if stack_key not in all_nodes:
618
+ return None
619
+
620
+ # DFS from the stack following dependency edges (transitive closure).
621
+ reachable = set()
622
+ stack = [stack_key]
623
+ while stack:
624
+ node = stack.pop()
625
+ if node in reachable:
626
+ continue
627
+ reachable.add(node)
628
+ for nxt in adjacency.get(node, ()): # dependencies of node
629
+ if nxt not in reachable:
630
+ stack.append(nxt)
631
+
632
+ # If the stack has no outgoing dependency edges, there is nothing
633
+ # meaningful to render.
634
+ if not adjacency.get(stack_key):
635
+ return None
636
+
637
+ def relabel(node: str) -> str:
638
+ return "." if node == stack_key else node
639
+
640
+ # Rebuild DOT with only reachable nodes/edges.
641
+ lines = ["digraph {"]
642
+ for node in sorted(reachable):
643
+ lines.append(f'\t"{relabel(node)}" ;')
644
+ for src in sorted(reachable):
645
+ for dst in sorted(adjacency.get(src, ())):
646
+ if dst in reachable:
647
+ lines.append(f'\t"{relabel(src)}" -> "{relabel(dst)}";')
648
+ lines.append("}")
649
+ return "\n".join(lines)
650
+
519
651
  def _parse_terragrunt_hcl(self, hcl_path: Path) -> dict:
520
652
  """Parse a terragrunt.hcl file to extract dependency information."""
521
653
  import hcl2
@@ -29,6 +29,7 @@ terraform_template = [
29
29
  "name": "catalog",
30
30
  "contents": [
31
31
  {"type": "file", "name": "mkdocs.yaml"},
32
+ {"type": "file", "name": "zensical.toml"},
32
33
  {"type": "file", "name": "catalog-info.yaml"},
33
34
  {
34
35
  "type": "directory",
@@ -126,6 +127,7 @@ terragrunt_template = [
126
127
  "name": "catalog",
127
128
  "contents": [
128
129
  {"type": "file", "name": "mkdocs.yaml"},
130
+ {"type": "file", "name": "zensical.toml"},
129
131
  {"type": "file", "name": "catalog-info.yaml"},
130
132
  {
131
133
  "type": "directory",
@@ -213,6 +215,7 @@ terraform_module_template = [
213
215
  "name": "catalog",
214
216
  "contents": [
215
217
  {"type": "file", "name": "mkdocs.yaml"},
218
+ {"type": "file", "name": "zensical.toml"},
216
219
  {"type": "file", "name": "catalog-info.yaml"},
217
220
  {
218
221
  "type": "directory",
@@ -0,0 +1,212 @@
1
+ """Dynamic installation of AI agent skills from upstream Git repositories.
2
+
3
+ Skills are reusable knowledge packages that live under ``.kiro/skills/<name>/``.
4
+ Historically they were baked into every scaffold template, which caused drift
5
+ between a scaffold's embedded copy and the canonical upstream repository.
6
+
7
+ This module installs skills *dynamically* at ``init`` time from their upstream
8
+ GitHub repositories (mirroring ``install_aidlc_rules``), so the canonical repo
9
+ is the single source of truth.
10
+
11
+ Only skills that have a known upstream repository are dynamically installable.
12
+ Skills authored by third parties or carrying scaffold-local modifications
13
+ (e.g. ``terraform-skill``) are intentionally NOT in the registry — they stay
14
+ bundled in the scaffold and are never overwritten by this installer.
15
+ """
16
+
17
+ import io
18
+ import shutil
19
+ import tempfile
20
+ import zipfile
21
+ from pathlib import Path
22
+ from typing import Dict, List, Optional
23
+
24
+ import requests
25
+ from colorama import Fore
26
+
27
+ # ---------------------------------------------------------------------------
28
+ # Skill registry
29
+ # ---------------------------------------------------------------------------
30
+ # Maps a skill name to its upstream source. Add an entry here when a skill gets
31
+ # a canonical GitHub repository so it can be installed dynamically.
32
+ #
33
+ # repo : "owner/name" GitHub repository slug.
34
+ # ref : git ref (branch/tag) to download when no release is published.
35
+ # use_release: if True, prefer the latest GitHub release asset/zipball,
36
+ # falling back to ``ref`` when there is no release.
37
+ # subdir : path *inside* the downloaded archive that contains the skill
38
+ # payload (SKILL.md + references/). "" means the archive root.
39
+ #
40
+ # NOTE ON INTENTIONAL OMISSIONS:
41
+ # - terraform-skill → third-party (Anton Babenko), scaffold-local mods; DO NOT auto-install.
42
+ # - thothctl-framework → no upstream repo yet; scaffold-bundled.
43
+ # - iac-versioning-commits → no upstream repo yet; scaffold-bundled.
44
+ SKILL_REGISTRY: Dict[str, Dict] = {
45
+ "devsecops": {
46
+ "repo": "thothforge/thothctl-devsecops-skill",
47
+ "ref": "main",
48
+ "use_release": True,
49
+ "subdir": "",
50
+ },
51
+ }
52
+
53
+
54
+ def available_skills() -> List[str]:
55
+ """Return the names of skills that can be installed dynamically."""
56
+ return sorted(SKILL_REGISTRY.keys())
57
+
58
+
59
+ def _resolve_zip_url(repo: str, ref: str, use_release: bool) -> Optional[str]:
60
+ """Resolve a downloadable zip URL for a repo.
61
+
62
+ Prefers the latest release when ``use_release`` is set and a release exists;
63
+ otherwise falls back to the branch/tag zipball.
64
+ """
65
+ if use_release:
66
+ api_url = f"https://api.github.com/repos/{repo}/releases/latest"
67
+ try:
68
+ resp = requests.get(api_url, timeout=30)
69
+ if resp.status_code == 200:
70
+ data = resp.json()
71
+ for asset in data.get("assets", []):
72
+ if asset.get("name", "").endswith(".zip"):
73
+ return asset["browser_download_url"]
74
+ if data.get("zipball_url"):
75
+ return data["zipball_url"]
76
+ except requests.RequestException:
77
+ # Fall through to branch zipball.
78
+ pass
79
+
80
+ # Branch/tag zipball (works even without any published release).
81
+ return f"https://api.github.com/repos/{repo}/zipball/{ref}"
82
+
83
+
84
+ def _find_skill_payload(extract_root: Path, subdir: str) -> Optional[Path]:
85
+ """Locate the directory holding SKILL.md inside an extracted archive.
86
+
87
+ GitHub zipballs wrap everything in a single top-level ``<owner>-<repo>-<sha>/``
88
+ directory, so we search for SKILL.md rather than assuming a fixed depth.
89
+ """
90
+ # Enter the single wrapper directory produced by GitHub zipballs, if present.
91
+ entries = [p for p in extract_root.iterdir() if p.is_dir()]
92
+ search_root = entries[0] if len(entries) == 1 else extract_root
93
+
94
+ if subdir:
95
+ candidate = search_root / subdir
96
+ return candidate if (candidate / "SKILL.md").exists() else None
97
+
98
+ # subdir == "" → the skill payload is at the archive root.
99
+ if (search_root / "SKILL.md").exists():
100
+ return search_root
101
+
102
+ # Fallback: first directory that directly contains a SKILL.md.
103
+ for skill_md in search_root.rglob("SKILL.md"):
104
+ return skill_md.parent
105
+ return None
106
+
107
+
108
+ def install_skill(skill_name: str, target_dir: str = ".") -> bool:
109
+ """Install a single skill from its upstream repo into ``.kiro/skills/<name>/``.
110
+
111
+ :param skill_name: Registry key (see ``SKILL_REGISTRY``).
112
+ :param target_dir: Project root directory (where ``.kiro/`` lives).
113
+ :return: True on success, False otherwise.
114
+ """
115
+ entry = SKILL_REGISTRY.get(skill_name)
116
+ if not entry:
117
+ print(
118
+ f"{Fore.YELLOW}⚠️ Skill '{skill_name}' has no upstream repository; "
119
+ f"skipping dynamic install (it is bundled in the scaffold).{Fore.RESET}"
120
+ )
121
+ return False
122
+
123
+ repo = entry["repo"]
124
+ ref = entry.get("ref", "main")
125
+ use_release = entry.get("use_release", False)
126
+ subdir = entry.get("subdir", "")
127
+
128
+ print(f"{Fore.MAGENTA}Installing skill '{skill_name}' from {repo}...{Fore.RESET}")
129
+
130
+ zip_url = _resolve_zip_url(repo, ref, use_release)
131
+ if not zip_url:
132
+ print(f"{Fore.RED}❌ Could not resolve a download URL for {repo}{Fore.RESET}")
133
+ return False
134
+
135
+ try:
136
+ zip_response = requests.get(zip_url, timeout=60, allow_redirects=True)
137
+ zip_response.raise_for_status()
138
+
139
+ with tempfile.TemporaryDirectory() as tmpdir:
140
+ tmp_path = Path(tmpdir)
141
+ with zipfile.ZipFile(io.BytesIO(zip_response.content)) as zf:
142
+ zf.extractall(tmp_path)
143
+
144
+ payload = _find_skill_payload(tmp_path, subdir)
145
+ if not payload:
146
+ print(
147
+ f"{Fore.RED}❌ Could not find SKILL.md in {repo} "
148
+ f"(subdir='{subdir or '<root>'}'){Fore.RESET}"
149
+ )
150
+ return False
151
+
152
+ dst = Path(target_dir) / ".kiro" / "skills" / skill_name
153
+ dst.parent.mkdir(parents=True, exist_ok=True)
154
+ if dst.exists():
155
+ shutil.rmtree(dst)
156
+ # Copy payload contents into .kiro/skills/<skill_name>/
157
+ shutil.copytree(payload, dst)
158
+ # Drop any VCS metadata that may have ridden along.
159
+ for junk in (".git", ".github"):
160
+ junk_path = dst / junk
161
+ if junk_path.exists():
162
+ shutil.rmtree(junk_path, ignore_errors=True)
163
+
164
+ print(
165
+ f"{Fore.GREEN} ✅ Installed skill '{skill_name}' → "
166
+ f".kiro/skills/{skill_name}/{Fore.RESET}"
167
+ )
168
+ return True
169
+
170
+ except requests.RequestException as e:
171
+ print(f"{Fore.RED}❌ Failed to download skill '{skill_name}': {e}{Fore.RESET}")
172
+ return False
173
+ except (zipfile.BadZipFile, OSError) as e:
174
+ print(f"{Fore.RED}❌ Failed to extract skill '{skill_name}': {e}{Fore.RESET}")
175
+ return False
176
+
177
+
178
+ def install_skills(skill_names: List[str], target_dir: str = ".") -> Dict[str, bool]:
179
+ """Install multiple skills. Returns a map of skill_name → success."""
180
+ results: Dict[str, bool] = {}
181
+ for name in skill_names:
182
+ results[name] = install_skill(name, target_dir=target_dir)
183
+ return results
184
+
185
+
186
+ def resolve_requested_skills(requested: str) -> List[str]:
187
+ """Translate a CLI ``--with-skills`` value into concrete registry names.
188
+
189
+ Accepts:
190
+ - "all" → every skill in the registry
191
+ - "none"/"false"/"off"/"" → nothing (opt-out)
192
+ - "devsecops,foo" → comma-separated explicit list
193
+ Unknown names are warned about and dropped.
194
+ """
195
+ if not requested:
196
+ return []
197
+ normalized = requested.strip().lower()
198
+ if normalized in ("none", "false", "off", "no"):
199
+ return []
200
+ if normalized == "all":
201
+ return available_skills()
202
+
203
+ names = [n.strip() for n in requested.split(",") if n.strip()]
204
+ valid, unknown = [], []
205
+ for n in names:
206
+ (valid if n in SKILL_REGISTRY else unknown).append(n)
207
+ if unknown:
208
+ print(
209
+ f"{Fore.YELLOW}⚠️ Unknown/undistributable skill(s): {', '.join(unknown)}. "
210
+ f"Available: {', '.join(available_skills())}{Fore.RESET}"
211
+ )
212
+ return valid
@@ -40,6 +40,7 @@ def replace_template_placeholders(
40
40
  ".terraform.lock.hcl",
41
41
  "catalog-info.yaml",
42
42
  "mkdocs.yaml",
43
+ "zensical.toml",
43
44
  "pdf",
44
45
  "dot",
45
46
  "gif",
@@ -1,3 +1,3 @@
1
1
  """Version module."""
2
2
 
3
- __version__ = "0.30.3"
3
+ __version__ = "0.31.0"
@@ -0,0 +1,110 @@
1
+ """Tests for dynamic skill installation (install_skills)."""
2
+
3
+ import io
4
+ import zipfile
5
+ from unittest.mock import MagicMock, patch
6
+
7
+ from thothctl.services.init.environment import install_skills
8
+
9
+
10
+ def _make_github_zipball(files: dict) -> bytes:
11
+ """Build an in-memory zip that mimics a GitHub zipball.
12
+
13
+ GitHub wraps everything under a single top-level ``<owner>-<repo>-<sha>/``
14
+ directory. ``files`` maps archive-relative paths (under that wrapper) to
15
+ their text content.
16
+ """
17
+ buf = io.BytesIO()
18
+ wrapper = "thothforge-thothctl-devsecops-skill-abc1234"
19
+ with zipfile.ZipFile(buf, "w") as zf:
20
+ for rel, content in files.items():
21
+ zf.writestr(f"{wrapper}/{rel}", content)
22
+ return buf.getvalue()
23
+
24
+
25
+ def test_resolve_requested_skills_all():
26
+ assert install_skills.resolve_requested_skills("all") == install_skills.available_skills()
27
+
28
+
29
+ def test_resolve_requested_skills_explicit_and_unknown():
30
+ # Known skill kept, unknown dropped.
31
+ result = install_skills.resolve_requested_skills("devsecops,does-not-exist")
32
+ assert result == ["devsecops"]
33
+
34
+
35
+ def test_resolve_requested_skills_empty():
36
+ assert install_skills.resolve_requested_skills("") == []
37
+ assert install_skills.resolve_requested_skills(None) == []
38
+
39
+
40
+ def test_resolve_requested_skills_optout_keywords():
41
+ for word in ("none", "None", "NONE", "false", "off", "no"):
42
+ assert install_skills.resolve_requested_skills(word) == [], word
43
+
44
+
45
+ def test_install_skill_unknown_returns_false(tmp_path):
46
+ assert install_skills.install_skill("terraform-skill", target_dir=str(tmp_path)) is False
47
+ # Nothing should have been written.
48
+ assert not (tmp_path / ".kiro").exists()
49
+
50
+
51
+ def test_install_skill_devsecops_from_zipball(tmp_path):
52
+ """install_skill downloads, finds SKILL.md, and copies into .kiro/skills/<name>/."""
53
+ zip_bytes = _make_github_zipball(
54
+ {
55
+ "SKILL.md": "# DevSecOps Skill\n",
56
+ "references/sdlc_phases.md": "phases\n",
57
+ "references/command_reference.md": "commands\n",
58
+ # Simulate VCS junk that must be stripped.
59
+ ".github/workflows/ci.yml": "ci\n",
60
+ }
61
+ )
62
+
63
+ fake_release = MagicMock()
64
+ fake_release.status_code = 404 # force zipball fallback (no release)
65
+
66
+ fake_zip = MagicMock()
67
+ fake_zip.content = zip_bytes
68
+ fake_zip.raise_for_status = MagicMock()
69
+
70
+ def fake_get(url, *args, **kwargs):
71
+ if "releases/latest" in url:
72
+ return fake_release
73
+ return fake_zip
74
+
75
+ with patch.object(install_skills.requests, "get", side_effect=fake_get):
76
+ ok = install_skills.install_skill("devsecops", target_dir=str(tmp_path))
77
+
78
+ assert ok is True
79
+ dst = tmp_path / ".kiro" / "skills" / "devsecops"
80
+ assert (dst / "SKILL.md").exists()
81
+ assert (dst / "references" / "sdlc_phases.md").exists()
82
+ assert (dst / "references" / "command_reference.md").exists()
83
+ # VCS junk stripped.
84
+ assert not (dst / ".github").exists()
85
+
86
+
87
+ def test_install_skill_overwrites_existing(tmp_path):
88
+ """Re-installing replaces a stale copy rather than merging into it."""
89
+ dst = tmp_path / ".kiro" / "skills" / "devsecops"
90
+ dst.mkdir(parents=True)
91
+ (dst / "STALE.md").write_text("old")
92
+
93
+ zip_bytes = _make_github_zipball({"SKILL.md": "# fresh\n"})
94
+ fake_release = MagicMock()
95
+ fake_release.status_code = 404
96
+ fake_zip = MagicMock()
97
+ fake_zip.content = zip_bytes
98
+ fake_zip.raise_for_status = MagicMock()
99
+
100
+ with patch.object(
101
+ install_skills.requests,
102
+ "get",
103
+ side_effect=lambda url, *a, **k: fake_release if "releases/latest" in url else fake_zip,
104
+ ):
105
+ ok = install_skills.install_skill("devsecops", target_dir=str(tmp_path))
106
+
107
+ assert ok is True
108
+ assert (dst / "SKILL.md").exists()
109
+ # Stale file from the previous copy must be gone.
110
+ assert not (dst / "STALE.md").exists()