thothctl 0.14.2__tar.gz → 0.14.4__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 (481) hide show
  1. {thothctl-0.14.2 → thothctl-0.14.4}/PKG-INFO +1 -1
  2. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/inventory/CHANGELOG.md +9 -0
  3. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/inventory/inventory_iac.md +46 -0
  4. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/ai_agent.py +54 -58
  5. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/decision_engine.py +55 -48
  6. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/main.py +16 -9
  7. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/memory.py +14 -9
  8. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/orchestrator.py +79 -59
  9. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/providers/azure_provider.py +20 -17
  10. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/providers/bedrock_agent_provider.py +15 -6
  11. thothctl-0.14.4/src/thothctl/services/ai_review/providers/bedrock_provider.py +69 -0
  12. thothctl-0.14.4/src/thothctl/services/ai_review/providers/ollama_provider.py +79 -0
  13. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/providers/openai_provider.py +20 -17
  14. thothctl-0.14.4/src/thothctl/services/ai_review/tracing.py +123 -0
  15. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/inventory_service.py +15 -6
  16. thothctl-0.14.4/src/thothctl/version.py +2 -0
  17. thothctl-0.14.2/src/thothctl/services/ai_review/providers/bedrock_provider.py +0 -67
  18. thothctl-0.14.2/src/thothctl/services/ai_review/providers/ollama_provider.py +0 -80
  19. thothctl-0.14.2/src/thothctl/version.py +0 -2
  20. {thothctl-0.14.2 → thothctl-0.14.4}/.devcontainer/Dockerfile +0 -0
  21. {thothctl-0.14.2 → thothctl-0.14.4}/.devcontainer/README.md +0 -0
  22. {thothctl-0.14.2 → thothctl-0.14.4}/.devcontainer/devcontainer.json +0 -0
  23. {thothctl-0.14.2 → thothctl-0.14.4}/.github/workflows/python-publish.yml +0 -0
  24. {thothctl-0.14.2 → thothctl-0.14.4}/.gitignore +0 -0
  25. {thothctl-0.14.2 → thothctl-0.14.4}/.pre-commit-config.yaml +0 -0
  26. {thothctl-0.14.2 → thothctl-0.14.4}/.readthedocs.yaml +0 -0
  27. {thothctl-0.14.2 → thothctl-0.14.4}/AWS_PRICING_API_FINAL_REPORT.md +0 -0
  28. {thothctl-0.14.2 → thothctl-0.14.4}/AWS_PRICING_API_IMPLEMENTATION_PLAN.md +0 -0
  29. {thothctl-0.14.2 → thothctl-0.14.4}/AWS_PRICING_REFACTOR_REPORT.md +0 -0
  30. {thothctl-0.14.2 → thothctl-0.14.4}/Dockerfile +0 -0
  31. {thothctl-0.14.2 → thothctl-0.14.4}/LICENSE +0 -0
  32. {thothctl-0.14.2 → thothctl-0.14.4}/README.md +0 -0
  33. {thothctl-0.14.2 → thothctl-0.14.4}/TECHNICAL_DEBT_METRICS.md +0 -0
  34. {thothctl-0.14.2 → thothctl-0.14.4}/__init__.py +0 -0
  35. {thothctl-0.14.2 → thothctl-0.14.4}/docs/catalog/catalog-info.yaml +0 -0
  36. {thothctl-0.14.2 → thothctl-0.14.4}/docs/dashboard/README.md +0 -0
  37. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/ai-review/README.md +0 -0
  38. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/ai-review/agentcore.md +0 -0
  39. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/blast-radius.md +0 -0
  40. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/check_environment.md +0 -0
  41. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/check_iac.md +0 -0
  42. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/check_overview.md +0 -0
  43. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/check_project_iac.md +0 -0
  44. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/check_space.md +0 -0
  45. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/cost-analysis-quick-reference.md +0 -0
  46. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/cost-analysis.md +0 -0
  47. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/deps-advanced.md +0 -0
  48. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/deps.md +0 -0
  49. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/drift-detection.md +0 -0
  50. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/plan.md +0 -0
  51. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/document/document_iac.md +0 -0
  52. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/document/document_overview.md +0 -0
  53. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/document/iac.md +0 -0
  54. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/document/use_cases.md +0 -0
  55. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/generate/generate_components.md +0 -0
  56. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/generate/generate_stacks.md +0 -0
  57. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/init/init.md +0 -0
  58. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/init/init_space.md +0 -0
  59. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/inventory/frameworks/terraform.md +0 -0
  60. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/inventory/frameworks/terragrunt.md +0 -0
  61. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/inventory/iac.md +0 -0
  62. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/inventory/inventory_overview.md +0 -0
  63. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/list/list_overview.md +0 -0
  64. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/list/list_projects.md +0 -0
  65. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/list/list_spaces.md +0 -0
  66. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/mcp/mcp.md +0 -0
  67. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/project/iac.md +0 -0
  68. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/project/project_cleanup.md +0 -0
  69. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/project/project_convert.md +0 -0
  70. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/project/project_overview.md +0 -0
  71. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/project/project_upgrade.md +0 -0
  72. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/project/use_cases.md +0 -0
  73. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/remove/remove_overview.md +0 -0
  74. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/remove/remove_project.md +0 -0
  75. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/remove/remove_space.md +0 -0
  76. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/scan/iac.md +0 -0
  77. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/scan/scan_iac.md +0 -0
  78. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/scan/scan_overview.md +0 -0
  79. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/scan/use_cases.md +0 -0
  80. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/upgrade/upgrade_overview.md +0 -0
  81. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/concepts.md +0 -0
  82. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/cross_platform_support.md +0 -0
  83. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/framework_architecture.md +0 -0
  84. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/infrasctructure_composition.md +0 -0
  85. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/software_architecture.md +0 -0
  86. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/space_configuration.md +0 -0
  87. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/README.md +0 -0
  88. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/ai_dlc.md +0 -0
  89. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/check_command.md +0 -0
  90. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/devsecops_quickstart.md +0 -0
  91. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/devsecops_sdlc.md +0 -0
  92. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/inventory_command.md +0 -0
  93. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/platform_engineering_templates.md +0 -0
  94. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/space_management.md +0 -0
  95. {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/tasks/create_template.md +0 -0
  96. {thothctl-0.14.2 → thothctl-0.14.4}/docs/iac_devsecops_use_case.md +0 -0
  97. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/automate_tasks_command.png +0 -0
  98. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/commnad_init.png +0 -0
  99. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/create_component.gif +0 -0
  100. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/create_inventory.gif +0 -0
  101. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/doc_command.png +0 -0
  102. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/document_project_code.gif +0 -0
  103. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/framework/thothforge-framework.svg +0 -0
  104. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/framework/thothfr.png +0 -0
  105. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/iacpeerbot_summary.png +0 -0
  106. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/init_project.gif +0 -0
  107. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/inventory_command.png +0 -0
  108. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/notification_img.png +0 -0
  109. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/report_dependencies.png +0 -0
  110. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/report_dependencies_summary.png +0 -0
  111. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/restore_inventory_version.gif +0 -0
  112. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/reuse_project_pattern.gif +0 -0
  113. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/scan_code.gif +0 -0
  114. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/scan_command.png +0 -0
  115. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/sync_wk_command.png +0 -0
  116. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/transform_command.png +0 -0
  117. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/update_inventory_version.gif +0 -0
  118. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/validate_command.png +0 -0
  119. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/validate_environment.gif +0 -0
  120. {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/validate_project.gif +0 -0
  121. {thothctl-0.14.2 → thothctl-0.14.4}/docs/includes/abbreviations.md +0 -0
  122. {thothctl-0.14.2 → thothctl-0.14.4}/docs/index.md +0 -0
  123. {thothctl-0.14.2 → thothctl-0.14.4}/docs/installation/windows_installation.md +0 -0
  124. {thothctl-0.14.2 → thothctl-0.14.4}/docs/javascripts/tablesort.js +0 -0
  125. {thothctl-0.14.2 → thothctl-0.14.4}/docs/mcp.md +0 -0
  126. {thothctl-0.14.2 → thothctl-0.14.4}/docs/navigation.md +0 -0
  127. {thothctl-0.14.2 → thothctl-0.14.4}/docs/quick_start.md +0 -0
  128. {thothctl-0.14.2 → thothctl-0.14.4}/docs/requirements.txt +0 -0
  129. {thothctl-0.14.2 → thothctl-0.14.4}/docs/stylesheets/extra-enhanced.css +0 -0
  130. {thothctl-0.14.2 → thothctl-0.14.4}/docs/stylesheets/extra.css +0 -0
  131. {thothctl-0.14.2 → thothctl-0.14.4}/docs/telemetry.md +0 -0
  132. {thothctl-0.14.2 → thothctl-0.14.4}/docs/template_engine/github_templates.md +0 -0
  133. {thothctl-0.14.2 → thothctl-0.14.4}/docs/template_engine/template_engine.md +0 -0
  134. {thothctl-0.14.2 → thothctl-0.14.4}/docs/troubleshooting/linux_troubleshooting.md +0 -0
  135. {thothctl-0.14.2 → thothctl-0.14.4}/docs/troubleshooting/macos_troubleshooting.md +0 -0
  136. {thothctl-0.14.2 → thothctl-0.14.4}/docs/troubleshooting/troubleshooting.md +0 -0
  137. {thothctl-0.14.2 → thothctl-0.14.4}/docs/troubleshooting/windows_troubleshooting.md +0 -0
  138. {thothctl-0.14.2 → thothctl-0.14.4}/mkdocs.yaml +0 -0
  139. {thothctl-0.14.2 → thothctl-0.14.4}/pyproject.toml +0 -0
  140. {thothctl-0.14.2 → thothctl-0.14.4}/scripts/run_mcp_server.sh +0 -0
  141. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/__init__.py +0 -0
  142. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/application/__init__.py +0 -0
  143. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/autocomplete.py +0 -0
  144. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/cli.py +0 -0
  145. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/__init__.py +0 -0
  146. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/__init__.py +0 -0
  147. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/cli.py +0 -0
  148. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/__init__.py +0 -0
  149. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/analyze.py +0 -0
  150. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/apply_fix.py +0 -0
  151. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/configure.py +0 -0
  152. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/configure_decisions.py +0 -0
  153. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/decide.py +0 -0
  154. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/history.py +0 -0
  155. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/improve.py +0 -0
  156. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/orchestrate.py +0 -0
  157. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/override.py +0 -0
  158. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/report.py +0 -0
  159. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/serve.py +0 -0
  160. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/__init__.py +0 -0
  161. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/cli.py +0 -0
  162. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/commands/__init__.py +0 -0
  163. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/commands/environment.py +0 -0
  164. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/commands/iac.py +0 -0
  165. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/commands/project/__init__.py +0 -0
  166. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/commands/project/iac.py +0 -0
  167. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/commands/project.py +0 -0
  168. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/dashboard/__init__.py +0 -0
  169. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/dashboard/cli.py +0 -0
  170. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/dashboard/commands/__init__.py +0 -0
  171. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/dashboard/commands/launch.py +0 -0
  172. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/document/__init__.py +0 -0
  173. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/document/cli.py +0 -0
  174. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/document/commands/__init__.py +0 -0
  175. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/document/commands/iac.py +0 -0
  176. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/generate/__init__.py +0 -0
  177. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/generate/cli.py +0 -0
  178. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/generate/commands/__init__.py +0 -0
  179. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/generate/commands/component.py +0 -0
  180. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/generate/commands/stacks.py +0 -0
  181. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/init/__init__.py +0 -0
  182. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/init/cli.py +0 -0
  183. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/init/commands/__init__.py +0 -0
  184. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/init/commands/env.py +0 -0
  185. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/init/commands/project.py +0 -0
  186. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/init/commands/space.py +0 -0
  187. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/inventory/__init__.py +0 -0
  188. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/inventory/cli.py +0 -0
  189. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/inventory/commands/__init__.py +0 -0
  190. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/inventory/commands/check.py +0 -0
  191. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/inventory/commands/iac.py +0 -0
  192. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/list/__init__.py +0 -0
  193. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/list/cli.py +0 -0
  194. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/list/commands/__init__.py +0 -0
  195. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/list/commands/projects.py +0 -0
  196. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/list/commands/spaces.py +0 -0
  197. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/mcp/__init__.py +0 -0
  198. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/mcp/cli.py +0 -0
  199. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/mcp/commands/__init__.py +0 -0
  200. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/mcp/commands/register.py +0 -0
  201. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/mcp/commands/server.py +0 -0
  202. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/mcp/commands/status.py +0 -0
  203. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/mcp/commands/stop.py +0 -0
  204. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/project/__init__.py +0 -0
  205. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/project/cli.py +0 -0
  206. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/project/commands/__init__.py +0 -0
  207. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/project/commands/bootstrap.py +0 -0
  208. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/project/commands/cleanup.py +0 -0
  209. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/project/commands/convert.py +0 -0
  210. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/project/commands/upgrade.py +0 -0
  211. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/remove/__init__.py +0 -0
  212. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/remove/cli.py +0 -0
  213. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/remove/project.py +0 -0
  214. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/remove/space.py +0 -0
  215. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/scan/__init__.py +0 -0
  216. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/scan/cli.py +0 -0
  217. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/scan/commands/__init__.py +0 -0
  218. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/scan/commands/iac.py +0 -0
  219. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/upgrade/cli.py +0 -0
  220. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/.thothcf.setup.toml +0 -0
  221. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/.thothcf_home.toml +0 -0
  222. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/.thothcf_module.toml +0 -0
  223. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/.thothcf_project.toml +0 -0
  224. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/.thothcf_template_parameters.toml +0 -0
  225. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/__init__.py +0 -0
  226. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/common.py +0 -0
  227. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/terragrunt/.thothcf_project.toml +0 -0
  228. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/__init__.py +0 -0
  229. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/constants.py +0 -0
  230. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/default_values.py +0 -0
  231. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/defaults.py +0 -0
  232. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/models.py +0 -0
  233. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/settings.py +0 -0
  234. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/template_config.py +0 -0
  235. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/template_configs.py +0 -0
  236. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/templates.py +0 -0
  237. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/validation.py +0 -0
  238. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/__init__.py +0 -0
  239. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/cli_ui.py +0 -0
  240. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/commands.py +0 -0
  241. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/config.py +0 -0
  242. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/__init__.py +0 -0
  243. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/azure_devops/__init__.py +0 -0
  244. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/azure_devops/get_azure_devops.py +0 -0
  245. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/azure_devops/pull_request_comments.py +0 -0
  246. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/github/get_github.py +0 -0
  247. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/github/pull_request_comments.py +0 -0
  248. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/integrate_messages_services/__init__.py +0 -0
  249. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/integrate_messages_services/microsoft_teams.py +0 -0
  250. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/integrate_messages_services/sent_message_teams.py +0 -0
  251. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/pattern_names.py +0 -0
  252. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/pr_comments/__init__.py +0 -0
  253. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/pr_comments/pr_comment_publisher.py +0 -0
  254. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/logger.py +0 -0
  255. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/telemetry.py +0 -0
  256. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/version_tools.py +0 -0
  257. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/domain/__init__.py +0 -0
  258. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/domain/interfaces/__init__.py +0 -0
  259. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/domain/models/__init__.py +0 -0
  260. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/mcp/README.md +0 -0
  261. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/mcp/__init__.py +0 -0
  262. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/mcp/server.py +0 -0
  263. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/__init__.py +0 -0
  264. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/__init__.py +0 -0
  265. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/agentcore/agentcore.json +0 -0
  266. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/analyzers/__init__.py +0 -0
  267. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/analyzers/code_reviewer.py +0 -0
  268. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/analyzers/context_builder.py +0 -0
  269. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/analyzers/report_analyzer.py +0 -0
  270. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/analyzers/risk_assessor.py +0 -0
  271. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/bedrock_agent_api.py +0 -0
  272. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/config/__init__.py +0 -0
  273. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/config/ai_settings.py +0 -0
  274. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/config/decision_rules.py +0 -0
  275. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/pr_decision_publisher.py +0 -0
  276. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/providers/__init__.py +0 -0
  277. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/safety/__init__.py +0 -0
  278. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/safety/safety_guard.py +0 -0
  279. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/utils/__init__.py +0 -0
  280. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/utils/cost_tracker.py +0 -0
  281. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/utils/fix_patterns.py +0 -0
  282. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/utils/fix_prompts.py +0 -0
  283. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/utils/formatters.py +0 -0
  284. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/utils/prompts.py +0 -0
  285. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/__init__.py +0 -0
  286. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/environment/__init__.py +0 -0
  287. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/environment/check_environment.py +0 -0
  288. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/__init__.py +0 -0
  289. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/blast_radius_service.py +0 -0
  290. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/check_origin_version.py +0 -0
  291. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/check_project_structure.py +0 -0
  292. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/__init__.py +0 -0
  293. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/cost_analyzer.py +0 -0
  294. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/models/__init__.py +0 -0
  295. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/models/cloudformation_mapper.py +0 -0
  296. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/models/cost_models.py +0 -0
  297. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/__init__.py +0 -0
  298. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/aws_pricing_client.py +0 -0
  299. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/base_pricing.py +0 -0
  300. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/__init__.py +0 -0
  301. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/apigateway_pricing.py +0 -0
  302. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/bedrock_pricing.py +0 -0
  303. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/cloudwatch_pricing.py +0 -0
  304. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/dynamodb_pricing.py +0 -0
  305. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/ebs_pricing.py +0 -0
  306. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/ec2_pricing.py +0 -0
  307. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/ecs_pricing.py +0 -0
  308. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/eip_pricing.py +0 -0
  309. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/eks_pricing.py +0 -0
  310. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/elb_pricing.py +0 -0
  311. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/free_resources_pricing.py +0 -0
  312. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/kms_pricing.py +0 -0
  313. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/lambda_pricing.py +0 -0
  314. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/msk_pricing.py +0 -0
  315. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/rds_pricing.py +0 -0
  316. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/s3_pricing.py +0 -0
  317. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/secrets_manager_pricing.py +0 -0
  318. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/vpc_pricing.py +0 -0
  319. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/unified_cost_report.py +0 -0
  320. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/drift/__init__.py +0 -0
  321. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/drift/drift_ai.py +0 -0
  322. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/drift/drift_history.py +0 -0
  323. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/drift/drift_policy.py +0 -0
  324. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/drift/drift_report.py +0 -0
  325. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/drift/drift_service.py +0 -0
  326. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/drift/models.py +0 -0
  327. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/risk_assessment.py +0 -0
  328. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/validate_project_structure.py +0 -0
  329. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/dashboard/__init__.py +0 -0
  330. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/dashboard/dashboard_service.py +0 -0
  331. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/dashboard/data_loader.py +0 -0
  332. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/document/__init__.py +0 -0
  333. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/document/create_documentation.py +0 -0
  334. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/document/files_content.py +0 -0
  335. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/document/files_scan.py +0 -0
  336. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/document/iac_documentation.py +0 -0
  337. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/document/iac_grunt_graph.py +0 -0
  338. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/document/iac_grunt_info.py +0 -0
  339. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/__init__.py +0 -0
  340. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_stacks/__init__.py +0 -0
  341. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_stacks/config_generator.py +0 -0
  342. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_stacks/remote_config_generation.py +0 -0
  343. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_stacks/stack_service.py +0 -0
  344. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_stacks/templates/terragrunt.hcl.j2 +0 -0
  345. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/__init__.py +0 -0
  346. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/config.yaml +0 -0
  347. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/create_code.py +0 -0
  348. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/create_component.py +0 -0
  349. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/create_component_service.py +0 -0
  350. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/create_stacks.py +0 -0
  351. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/create_template.py +0 -0
  352. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/files_content.py +0 -0
  353. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/github_template_loader.py +0 -0
  354. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/project_templates.py +0 -0
  355. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/__init__.py +0 -0
  356. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/environment/__init__.py +0 -0
  357. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/environment/install_tools.py +0 -0
  358. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/project/__init__.py +0 -0
  359. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/project/project.py +0 -0
  360. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/space/__init__.py +0 -0
  361. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/space/example_space.toml +0 -0
  362. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/space/local_registry.py +0 -0
  363. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/space/space.py +0 -0
  364. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/space/space_config.py +0 -0
  365. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/space/space_service.py +0 -0
  366. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/__init__.py +0 -0
  367. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/changelog_parser.py +0 -0
  368. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/models.py +0 -0
  369. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/module_compatibility_service.py +0 -0
  370. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/report_service.py +0 -0
  371. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/schema_compatibility_service.py +0 -0
  372. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/terragrunt_parser.py +0 -0
  373. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/update_versions.py +0 -0
  374. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/version_service.py +0 -0
  375. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/mcp/README.md +0 -0
  376. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/mcp/__init__.py +0 -0
  377. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/mcp/amazon_q_server.py +0 -0
  378. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/mcp/example.py +0 -0
  379. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/mcp/service.py +0 -0
  380. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/mcp/simple_http_server.py +0 -0
  381. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/__init__.py +0 -0
  382. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/bootstrap/__init__.py +0 -0
  383. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/bootstrap/bootstrap_service.py +0 -0
  384. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/cleanup/__init__.py +0 -0
  385. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/cleanup/clean_project.py +0 -0
  386. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/cleanup/clean_space.py +0 -0
  387. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/convert/__init__.py +0 -0
  388. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/convert/conversion_service.py +0 -0
  389. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/convert/get_project_data.py +0 -0
  390. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/convert/post_init.py +0 -0
  391. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/convert/project_converter.py +0 -0
  392. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/convert/project_defaults.py +0 -0
  393. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/convert/set_project_parameters.py +0 -0
  394. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/create_terramate/__init__.py +0 -0
  395. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/create_terramate/create_terramate_stacks.py +0 -0
  396. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/create_terramate/detect_changes_stacks.py +0 -0
  397. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/create_terramate/manage_terramate_stacks.py +0 -0
  398. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/upgrade/__init__.py +0 -0
  399. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/upgrade/upgrade_service.py +0 -0
  400. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/__init__.py +0 -0
  401. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/compliance_review.py +0 -0
  402. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/import_reports.py +0 -0
  403. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scan_service.py +0 -0
  404. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/__init__.py +0 -0
  405. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/checkov.py +0 -0
  406. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/kics.py +0 -0
  407. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/opa.py +0 -0
  408. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/scan_reports.py +0 -0
  409. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/scanners.py +0 -0
  410. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/terraform_compliance.py +0 -0
  411. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/tfsec.py +0 -0
  412. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/trivy.py +0 -0
  413. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/templates/reports/inventory_report.html +0 -0
  414. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/templates/reports/inventory_report.js +0 -0
  415. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/templates/unified_report_styles.css +0 -0
  416. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/__init__.py +0 -0
  417. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/banner.py +0 -0
  418. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/__init__.py +0 -0
  419. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/create_compliance_html_reports.py +0 -0
  420. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/create_html_reports.py +0 -0
  421. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/delete_directory.py +0 -0
  422. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/fix_report_styling.py +0 -0
  423. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/report_html_utils.py +0 -0
  424. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/templates/dashboard.html +0 -0
  425. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/templates/index_report.html +0 -0
  426. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/templates/individual_report.html +0 -0
  427. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/templates/simple_report.html +0 -0
  428. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/templates/unified_report_styles.css +0 -0
  429. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/templates/unified_simple_report.html +0 -0
  430. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/templates/xunit_report.html +0 -0
  431. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/crypto.py +0 -0
  432. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/manage_backend_resources/__init__.py +0 -0
  433. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/manage_backend_resources/manage_backend_resources.py +0 -0
  434. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/modules_ops/__init__.py +0 -0
  435. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/modules_ops/terraform_module_details.py +0 -0
  436. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/modules_ops/terraform_modules_fetcher.py +0 -0
  437. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/platform_utils.py +0 -0
  438. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/process_hcl/__init__.py +0 -0
  439. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/process_hcl/analyze_terraform_plan.py +0 -0
  440. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/process_hcl/graph_manager.py +0 -0
  441. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/process_hcl/graph_terragrunt_dependencies.py +0 -0
  442. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/process_hcl/process_terraform_file.py +0 -0
  443. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/process_hcl/risk_analyzing_terraform_plan.py +0 -0
  444. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/sync_workspaces/__init__.py +0 -0
  445. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/sync_workspaces/sync_terraform_workspaces.py +0 -0
  446. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/sync_workspaces/sync_terragrunt_workspaces.py +0 -0
  447. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/template_loader.py +0 -0
  448. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/thoth_colors.py +0 -0
  449. {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/wellcome_banner.py +0 -0
  450. {thothctl-0.14.2 → thothctl-0.14.4}/tests/conftest.py +0 -0
  451. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_agentcore_entrypoint.py +0 -0
  452. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_aws_pricing_client.py +0 -0
  453. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_azure_devops_pr_comments.py +0 -0
  454. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_bedrock_pricing.py +0 -0
  455. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_cdk_language_selection.py +0 -0
  456. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_context_steering.py +0 -0
  457. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_cost_analyzer.py +0 -0
  458. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_cost_models.py +0 -0
  459. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_cost_pr_comments.py +0 -0
  460. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_dashboard_loading_fix.py +0 -0
  461. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_dashboard_service.py +0 -0
  462. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_drift.py +0 -0
  463. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_drift_detection.py +0 -0
  464. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_ec2_pricing.py +0 -0
  465. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_github_pr_comments.py +0 -0
  466. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_iac_cost_integration.py +0 -0
  467. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_inventory_pr_comments.py +0 -0
  468. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_kics_scanner.py +0 -0
  469. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_mermaid_edge_labels.py +0 -0
  470. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_new_cost_providers.py +0 -0
  471. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_parallel_scan.py +0 -0
  472. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_platform_utils.py +0 -0
  473. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_pr_comment_publisher.py +0 -0
  474. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_provider_source_url_fix.py +0 -0
  475. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_provider_versions.py +0 -0
  476. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_scan_pr_comments.py +0 -0
  477. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_space_command.py +0 -0
  478. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_space_config.py +0 -0
  479. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_template_url_fix.py +0 -0
  480. {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_terragrunt_parser.py +0 -0
  481. {thothctl-0.14.2 → thothctl-0.14.4}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: thothctl
3
- Version: 0.14.2
3
+ Version: 0.14.4
4
4
  Summary: A CLI for Developer Control Plane. Accelerate your cloud IaC deployments.
5
5
  Project-URL: Homepage, https://github.com/thothforge/thothctl
6
6
  Author-email: Alejandro Velez <velez94@pm.me>
@@ -1,5 +1,14 @@
1
1
  # ThothCTL Inventory Command Changelog
2
2
 
3
+ ## Version 0.14.3 - May 2026
4
+
5
+ ### 🔧 Fix: Weighted Technical Debt Scoring
6
+
7
+ - **Weighted formula**: Modules now carry 70% weight and providers 30% in debt score calculation
8
+ - **Fairer scoring**: A single outdated provider no longer inflates the score disproportionately
9
+ - **Consistent thresholds**: CDK risk levels aligned with the main formula (70/50/30)
10
+ - **Rationale**: Providers may be intentionally pinned (e.g., a module tested against a specific provider version), so they should not dominate the debt score
11
+
3
12
  ## Version 0.4.0 - July 2025
4
13
 
5
14
  ### 🎯 Major Improvements
@@ -197,6 +197,52 @@ The reports now include comprehensive provider data:
197
197
  - **Module Context**: Which module uses the provider
198
198
  - **Status**: Current, Outdated, or Unknown
199
199
 
200
+ ## Technical Debt Scoring 📊
201
+
202
+ When `--check-versions` is enabled, ThothCTL calculates a **technical debt score** that reflects how outdated your infrastructure is.
203
+
204
+ ### Weighted Formula
205
+
206
+ The debt score uses a weighted approach that separates module health from provider health:
207
+
208
+ ```
209
+ module_debt = outdated_modules / total_modules (weight: 70%)
210
+ provider_debt = outdated_providers / total_providers (weight: 30%)
211
+
212
+ debt_score = (module_debt × 0.7 + provider_debt × 0.3) × 100 + breaking_changes_penalty
213
+ ```
214
+
215
+ **Why weighted?** Modules define your architecture and are the primary source of risk. Providers are dependencies that may be intentionally pinned (e.g., a latest module tested against a specific provider version). A single outdated provider should not inflate the score disproportionately.
216
+
217
+ ### Breaking Changes Penalty
218
+
219
+ Each module or provider with detected breaking changes adds **+5 points** to the debt score (capped at 100%).
220
+
221
+ ### Risk Levels
222
+
223
+ | Debt Score | Risk Level | Meaning |
224
+ |-----------|------------|---------|
225
+ | ≥ 70% | **Critical** | Immediate action required |
226
+ | ≥ 50% | **High** | Plan upgrades soon |
227
+ | ≥ 30% | **Medium** | Schedule maintenance |
228
+ | < 30% | **Low** | Infrastructure is well-maintained |
229
+
230
+ ### Examples
231
+
232
+ | Scenario | Score | Risk |
233
+ |----------|-------|------|
234
+ | 2 modules current, 1/2 providers outdated | 15% | Low |
235
+ | 2/4 modules outdated, providers current | 35% | Medium |
236
+ | All modules and providers outdated | 100% | Critical |
237
+ | Everything current | 0% | Low |
238
+
239
+ ### Recommendations
240
+
241
+ The system auto-generates actionable recommendations based on the metrics:
242
+ - Update outdated modules/providers
243
+ - Review components with breaking changes before upgrading
244
+ - Confirmation when infrastructure is well-maintained (score < 20%)
245
+
200
246
  ## Framework Type Options
201
247
 
202
248
  ### Auto-detect Framework (Default)
@@ -20,6 +20,7 @@ from .utils.prompts import (
20
20
  SYSTEM_FULL_ANALYSIS,
21
21
  )
22
22
  from .utils.fix_prompts import SYSTEM_FIX_GENERATOR
23
+ from .tracing import span
23
24
 
24
25
  logger = logging.getLogger(__name__)
25
26
 
@@ -82,35 +83,37 @@ class AIReviewAgent:
82
83
  Calls InventoryService, ScanService, BlastRadiusService, and collects
83
84
  raw code to give the LLM a complete picture of the IaC project.
84
85
  """
85
- logger.info(f"Building rich context for {directory}")
86
- ctx = self.context_builder.build_context(directory)
87
-
88
- # If we got scan results through context building, compute basic risk
89
- basic_risk = None
90
- if ctx.scan_results.get("total_findings", 0) > 0:
91
- basic_risk = self.risk_assessor.assess_risk(ctx.scan_results)
92
-
93
- if not self.cost_tracker.check_budget():
94
- logger.warning("Budget limit reached")
95
- if basic_risk:
96
- return self._basic_analysis(ctx.scan_results, basic_risk)
97
- return self._empty_result()
98
-
99
- formatted = self.context_builder.format_for_ai(ctx)
100
- fallback = (lambda: self._basic_analysis(ctx.scan_results, basic_risk)) if basic_risk else self._empty_result
101
- result = self._call_ai(SYSTEM_FULL_ANALYSIS, formatted, "analyze_directory", fallback=fallback)
102
-
103
- # Attach context metadata so callers know what was collected
104
- result["_context"] = {
105
- "project_type": ctx.project_type,
106
- "modules_found": len(ctx.modules),
107
- "providers_found": len(ctx.providers),
108
- "scan_findings": ctx.scan_results.get("total_findings", 0),
109
- "blast_radius_components": ctx.blast_radius.get("total_components", 0),
110
- "code_files": len(ctx.code_files),
111
- "collection_notes": ctx.errors,
112
- }
113
- return result
86
+ with span("ai_agent.analyze_directory", {"directory": directory}) as s:
87
+ logger.info(f"Building rich context for {directory}")
88
+ ctx = self.context_builder.build_context(directory)
89
+
90
+ basic_risk = None
91
+ if ctx.scan_results.get("total_findings", 0) > 0:
92
+ basic_risk = self.risk_assessor.assess_risk(ctx.scan_results)
93
+
94
+ if not self.cost_tracker.check_budget():
95
+ logger.warning("Budget limit reached")
96
+ s.set_attribute("budget_exceeded", True)
97
+ if basic_risk:
98
+ return self._basic_analysis(ctx.scan_results, basic_risk)
99
+ return self._empty_result()
100
+
101
+ formatted = self.context_builder.format_for_ai(ctx)
102
+ fallback = (lambda: self._basic_analysis(ctx.scan_results, basic_risk)) if basic_risk else self._empty_result
103
+ result = self._call_ai(SYSTEM_FULL_ANALYSIS, formatted, "analyze_directory", fallback=fallback)
104
+
105
+ result["_context"] = {
106
+ "project_type": ctx.project_type,
107
+ "modules_found": len(ctx.modules),
108
+ "providers_found": len(ctx.providers),
109
+ "scan_findings": ctx.scan_results.get("total_findings", 0),
110
+ "blast_radius_components": ctx.blast_radius.get("total_components", 0),
111
+ "code_files": len(ctx.code_files),
112
+ "collection_notes": ctx.errors,
113
+ }
114
+ s.set_attribute("findings", ctx.scan_results.get("total_findings", 0))
115
+ s.set_attribute("code_files", len(ctx.code_files))
116
+ return result
114
117
 
115
118
  def review_code(self, directory: str) -> Dict[str, Any]:
116
119
  """Review raw IaC code with AI (no thothctl service context)."""
@@ -129,38 +132,31 @@ class AIReviewAgent:
129
132
 
130
133
  def generate_fixes(self, directory: str, scan_results: Dict = None,
131
134
  severity_filter: str = None) -> Dict[str, Any]:
132
- """Generate actionable code fixes for scan findings.
135
+ """Generate actionable code fixes for scan findings."""
136
+ with span("ai_agent.generate_fixes", {"directory": directory, "severity_filter": severity_filter or "all"}) as s:
137
+ if not scan_results:
138
+ analyzer = ReportAnalyzer()
139
+ reports_dir = Path(directory) / "Reports"
140
+ if reports_dir.exists():
141
+ scan_results = analyzer.parse_scan_results(str(reports_dir))
142
+ else:
143
+ analysis = self.analyze_directory(directory)
144
+ return self._fixes_from_analysis(analysis, directory)
133
145
 
134
- Args:
135
- directory: Path to IaC code
136
- scan_results: Pre-parsed scan results (or auto-collected)
137
- severity_filter: Only fix findings at this severity or above
138
- """
139
- # Collect scan results if not provided
140
- if not scan_results:
141
- analyzer = ReportAnalyzer()
142
- reports_dir = Path(directory) / "Reports"
143
- if reports_dir.exists():
144
- scan_results = analyzer.parse_scan_results(str(reports_dir))
145
- else:
146
- # Run analysis to get findings
147
- analysis = self.analyze_directory(directory)
148
- return self._fixes_from_analysis(analysis, directory)
149
-
150
- if scan_results.get("total_findings", 0) == 0:
151
- return {"fixes": [], "skipped": [], "summary": {"total_findings": 0, "fixes_generated": 0, "skipped": 0}}
152
-
153
- # Collect affected code files
154
- code_files = self.code_reviewer.collect_code_for_review(directory)
146
+ if scan_results.get("total_findings", 0) == 0:
147
+ return {"fixes": [], "skipped": [], "summary": {"total_findings": 0, "fixes_generated": 0, "skipped": 0}}
155
148
 
156
- if not self.cost_tracker.check_budget():
157
- return self._pattern_fixes(scan_results, code_files, severity_filter)
149
+ code_files = self.code_reviewer.collect_code_for_review(directory)
150
+
151
+ if not self.cost_tracker.check_budget():
152
+ s.set_attribute("fallback", "pattern_fixes")
153
+ return self._pattern_fixes(scan_results, code_files, severity_filter)
158
154
 
159
- # Build prompt with findings + code
160
- content = self._format_fix_request(scan_results, code_files, severity_filter)
161
- result = self._call_ai(SYSTEM_FIX_GENERATOR, content, "generate_fixes",
162
- fallback=lambda: self._pattern_fixes(scan_results, code_files, severity_filter))
163
- return result
155
+ content = self._format_fix_request(scan_results, code_files, severity_filter)
156
+ result = self._call_ai(SYSTEM_FIX_GENERATOR, content, "generate_fixes",
157
+ fallback=lambda: self._pattern_fixes(scan_results, code_files, severity_filter))
158
+ s.set_attribute("fixes_generated", len(result.get("fixes", [])))
159
+ return result
164
160
 
165
161
  def _format_fix_request(self, scan_results: Dict, code_files: Dict,
166
162
  severity_filter: str = None) -> str:
@@ -6,6 +6,7 @@ from typing import Dict, Any, List, Optional
6
6
 
7
7
  from .config.decision_rules import DecisionRules, BLOCKING_PATTERNS
8
8
  from .safety.safety_guard import SafetyGuard
9
+ from .tracing import span
9
10
 
10
11
  logger = logging.getLogger(__name__)
11
12
 
@@ -40,59 +41,65 @@ class DecisionEngine:
40
41
  repository: str = "", pr_id: str = "",
41
42
  pr_context: Optional[Dict] = None) -> DecisionResult:
42
43
  """Evaluate analysis results and return a decision."""
43
- summary = analysis.get("summary", {})
44
- risk_score = float(analysis.get("risk_score", 50))
45
- findings = analysis.get("findings", [])
46
- recommendations = analysis.get("recommendations", [])
47
-
48
- critical = summary.get("critical", 0)
49
- high = summary.get("high", 0)
50
- medium = summary.get("medium", 0)
51
- low = summary.get("low", 0)
52
-
53
- findings_summary = {"critical": critical, "high": high, "medium": medium, "low": low}
54
-
55
- # Check for blocking patterns in findings
56
- has_blocking = self._has_blocking_patterns(findings)
57
-
58
- # Determine raw decision
59
- decision, confidence, reason = self._compute_decision(
60
- risk_score, critical, high, medium, has_blocking, findings,
61
- )
62
-
63
- # Safety gate
64
- if decision != Decision.COMMENT and repository:
65
- allowed, safety_reason = self.safety.can_take_action(
66
- decision.value, confidence, repository, pr_context,
44
+ with span("decision_engine.evaluate", {"repository": repository, "pr_id": pr_id}) as s:
45
+ summary = analysis.get("summary", {})
46
+ risk_score = float(analysis.get("risk_score", 50))
47
+ findings = analysis.get("findings", [])
48
+ recommendations = analysis.get("recommendations", [])
49
+
50
+ critical = summary.get("critical", 0)
51
+ high = summary.get("high", 0)
52
+ medium = summary.get("medium", 0)
53
+ low = summary.get("low", 0)
54
+
55
+ findings_summary = {"critical": critical, "high": high, "medium": medium, "low": low}
56
+
57
+ has_blocking = self._has_blocking_patterns(findings)
58
+
59
+ decision, confidence, reason = self._compute_decision(
60
+ risk_score, critical, high, medium, has_blocking, findings,
67
61
  )
68
- if not allowed:
69
- return DecisionResult(
70
- decision=Decision.COMMENT,
71
- confidence=confidence,
72
- reason=reason,
73
- risk_score=risk_score,
74
- findings_summary=findings_summary,
75
- recommendations=recommendations,
76
- blocked_by_safety=True,
77
- safety_reason=safety_reason,
62
+
63
+ if decision != Decision.COMMENT and repository:
64
+ allowed, safety_reason = self.safety.can_take_action(
65
+ decision.value, confidence, repository, pr_context,
66
+ )
67
+ if not allowed:
68
+ s.set_attribute("decision", "comment")
69
+ s.set_attribute("blocked_by_safety", True)
70
+ s.set_attribute("safety_reason", safety_reason)
71
+ s.set_attribute("risk_score", risk_score)
72
+ return DecisionResult(
73
+ decision=Decision.COMMENT,
74
+ confidence=confidence,
75
+ reason=reason,
76
+ risk_score=risk_score,
77
+ findings_summary=findings_summary,
78
+ recommendations=recommendations,
79
+ blocked_by_safety=True,
80
+ safety_reason=safety_reason,
81
+ )
82
+
83
+ if decision != Decision.COMMENT and repository:
84
+ self.safety.record_action(
85
+ action=decision.value, repository=repository,
86
+ pr_id=pr_id, confidence=confidence, reason=reason,
78
87
  )
79
88
 
80
- # Record if taking action
81
- if decision != Decision.COMMENT and repository:
82
- self.safety.record_action(
83
- action=decision.value, repository=repository,
84
- pr_id=pr_id, confidence=confidence, reason=reason,
89
+ s.set_attribute("decision", decision.value)
90
+ s.set_attribute("confidence", confidence)
91
+ s.set_attribute("risk_score", risk_score)
92
+ s.set_attribute("has_blocking_patterns", has_blocking)
93
+
94
+ return DecisionResult(
95
+ decision=decision,
96
+ confidence=confidence,
97
+ reason=reason,
98
+ risk_score=risk_score,
99
+ findings_summary=findings_summary,
100
+ recommendations=recommendations,
85
101
  )
86
102
 
87
- return DecisionResult(
88
- decision=decision,
89
- confidence=confidence,
90
- reason=reason,
91
- risk_score=risk_score,
92
- findings_summary=findings_summary,
93
- recommendations=recommendations,
94
- )
95
-
96
103
  def _compute_decision(self, risk_score: float, critical: int, high: int,
97
104
  medium: int, has_blocking: bool,
98
105
  findings: List[Dict]) -> tuple:
@@ -27,6 +27,8 @@ from typing import Any, Dict
27
27
  from fastapi import FastAPI, Request
28
28
  from fastapi.responses import JSONResponse
29
29
 
30
+ from .tracing import span
31
+
30
32
  logger = logging.getLogger(__name__)
31
33
 
32
34
  app = FastAPI(title="ThothCTL AgentCore Agent", version="0.13.2")
@@ -62,15 +64,20 @@ async def invocations(request: Request):
62
64
  if not mode:
63
65
  mode = _detect_mode(prompt)
64
66
 
65
- try:
66
- result = _dispatch(
67
- mode=mode, directory=directory, provider=provider, model=model,
68
- roles=roles, repository=repository, run_id=run_id, prompt=prompt,
69
- )
70
- return JSONResponse(content={"result": result})
71
- except Exception as e:
72
- logger.exception("Invocation failed")
73
- return JSONResponse(status_code=500, content={"error": str(e)})
67
+ with span("invocations", {"mode": mode, "directory": directory,
68
+ "provider": provider, "repository": repository,
69
+ "run_id": run_id}) as s:
70
+ try:
71
+ result = _dispatch(
72
+ mode=mode, directory=directory, provider=provider, model=model,
73
+ roles=roles, repository=repository, run_id=run_id, prompt=prompt,
74
+ )
75
+ s.set_attribute("result.status", "ok")
76
+ return JSONResponse(content={"result": result})
77
+ except Exception as e:
78
+ logger.exception("Invocation failed")
79
+ s.set_attribute("result.status", "error")
80
+ return JSONResponse(status_code=500, content={"error": str(e)})
74
81
 
75
82
 
76
83
  # ── Existing REST endpoints (kept for direct API use) ───────────────
@@ -18,6 +18,8 @@ from datetime import datetime, timezone
18
18
  from pathlib import Path
19
19
  from typing import Any, Dict, List, Optional
20
20
 
21
+ from .tracing import span
22
+
21
23
  logger = logging.getLogger(__name__)
22
24
 
23
25
  LOCAL_SESSIONS_DIR = ".thothctl/ai_sessions"
@@ -101,18 +103,21 @@ class AgentMemory:
101
103
 
102
104
  def save_analysis(self, repo: str, analysis: Dict[str, Any], run_id: str = "") -> None:
103
105
  key = self._scoped_key(repo, "analysis", run_id)
104
- data = {
105
- "timestamp": datetime.now(timezone.utc).isoformat(),
106
- "repo": repo,
107
- "run_id": run_id,
108
- "analysis": analysis,
109
- }
110
- self._backend.write(key, data)
106
+ with span("memory.save_analysis", {"repo": repo, "run_id": run_id, "backend": self.mode}):
107
+ data = {
108
+ "timestamp": datetime.now(timezone.utc).isoformat(),
109
+ "repo": repo,
110
+ "run_id": run_id,
111
+ "analysis": analysis,
112
+ }
113
+ self._backend.write(key, data)
111
114
 
112
115
  def load_analysis(self, repo: str, run_id: str = "") -> Optional[Dict[str, Any]]:
113
116
  key = self._scoped_key(repo, "analysis", run_id)
114
- data = self._backend.read(key)
115
- return data.get("analysis") if data else None
117
+ with span("memory.load_analysis", {"repo": repo, "run_id": run_id, "backend": self.mode}) as s:
118
+ data = self._backend.read(key)
119
+ s.set_attribute("cache_hit", data is not None)
120
+ return data.get("analysis") if data else None
116
121
 
117
122
  # -- Session history (per session ID) --
118
123
 
@@ -25,6 +25,7 @@ from .config.ai_settings import AISettings, ProviderConfig
25
25
  from .analyzers.context_builder import ContextBuilder, IaCContext
26
26
  from .utils.cost_tracker import CostTracker
27
27
  from .memory import AgentMemory, MemoryConfig
28
+ from .tracing import span
28
29
 
29
30
  logger = logging.getLogger(__name__)
30
31
 
@@ -123,39 +124,48 @@ class AgentOrchestrator:
123
124
  if roles is None:
124
125
  roles = [AgentRole.SECURITY, AgentRole.ARCHITECTURE]
125
126
 
126
- # Build shared context once
127
- logger.info(f"Building context for {directory}")
128
- ctx = self.context_builder.build_context(directory)
129
-
130
- # Enrich context with previous analysis from memory
131
- if repository:
132
- previous = self.memory.load_analysis(repository, run_id=run_id)
133
- if previous:
134
- ctx.errors.append(f"Previous analysis loaded from memory ({repository})")
135
- self._inject_previous_context(ctx, previous)
136
-
137
- # Create tasks for requested roles
138
- tasks = self._create_tasks(ctx, roles)
139
-
140
- if not self.cost_tracker.check_budget():
141
- logger.warning("Budget exceeded — running offline agents only")
142
- return self._offline_result(ctx, roles)
143
-
144
- # Execute agents (parallel where possible)
145
- result = OrchestratorResult()
146
- self._execute_tasks(tasks, result)
147
-
148
- # If decision was requested, run it last with merged context
149
- if AgentRole.DECISION in roles:
150
- self._run_decision(result, ctx)
151
-
152
- result.cost = self.cost_tracker.get_cost_report("daily")
153
-
154
- # Persist results to memory
155
- if repository:
156
- self._save_to_memory(repository, result, run_id=run_id)
157
-
158
- return result
127
+ with span("orchestrator.run_agents", {
128
+ "directory": directory,
129
+ "roles": [r.value for r in roles],
130
+ "repository": repository,
131
+ "run_id": run_id,
132
+ }) as s:
133
+ # Build shared context once
134
+ logger.info(f"Building context for {directory}")
135
+ ctx = self.context_builder.build_context(directory)
136
+
137
+ # Enrich context with previous analysis from memory
138
+ if repository:
139
+ previous = self.memory.load_analysis(repository, run_id=run_id)
140
+ if previous:
141
+ ctx.errors.append(f"Previous analysis loaded from memory ({repository})")
142
+ self._inject_previous_context(ctx, previous)
143
+
144
+ # Create tasks for requested roles
145
+ tasks = self._create_tasks(ctx, roles)
146
+
147
+ if not self.cost_tracker.check_budget():
148
+ logger.warning("Budget exceeded — running offline agents only")
149
+ s.set_attribute("budget_exceeded", True)
150
+ return self._offline_result(ctx, roles)
151
+
152
+ # Execute agents (parallel where possible)
153
+ result = OrchestratorResult()
154
+ self._execute_tasks(tasks, result)
155
+
156
+ # If decision was requested, run it last with merged context
157
+ if AgentRole.DECISION in roles:
158
+ self._run_decision(result, ctx)
159
+
160
+ result.cost = self.cost_tracker.get_cost_report("daily")
161
+
162
+ # Persist results to memory
163
+ if repository:
164
+ self._save_to_memory(repository, result, run_id=run_id)
165
+
166
+ s.set_attribute("agents_executed", len(tasks))
167
+ s.set_attribute("errors", len(result.errors))
168
+ return result
159
169
 
160
170
  def run_single_agent(self, directory: str, role: AgentRole) -> Dict[str, Any]:
161
171
  """Run a single specialized agent."""
@@ -212,22 +222,23 @@ class AgentOrchestrator:
212
222
  if not tasks:
213
223
  return
214
224
 
215
- if self.max_parallel <= 1 or len(tasks) == 1:
216
- for task in tasks:
217
- self._run_task(task, result)
218
- else:
219
- with ThreadPoolExecutor(max_workers=min(self.max_parallel, len(tasks))) as pool:
220
- futures = {pool.submit(self._call_ai, task): task for task in tasks}
221
- for future in as_completed(futures):
222
- task = futures[future]
223
- try:
224
- ai_result = future.result()
225
- if task.post_process:
226
- ai_result = task.post_process(ai_result)
227
- setattr(result, task.role.value, ai_result)
228
- except Exception as e:
229
- logger.error(f"Agent {task.role.value} failed: {e}")
230
- result.errors.append(f"{task.role.value}: {e}")
225
+ with span("orchestrator.execute_tasks", {"task_count": len(tasks), "parallel": self.max_parallel > 1}):
226
+ if self.max_parallel <= 1 or len(tasks) == 1:
227
+ for task in tasks:
228
+ self._run_task(task, result)
229
+ else:
230
+ with ThreadPoolExecutor(max_workers=min(self.max_parallel, len(tasks))) as pool:
231
+ futures = {pool.submit(self._call_ai, task): task for task in tasks}
232
+ for future in as_completed(futures):
233
+ task = futures[future]
234
+ try:
235
+ ai_result = future.result()
236
+ if task.post_process:
237
+ ai_result = task.post_process(ai_result)
238
+ setattr(result, task.role.value, ai_result)
239
+ except Exception as e:
240
+ logger.error(f"Agent {task.role.value} failed: {e}")
241
+ result.errors.append(f"{task.role.value}: {e}")
231
242
 
232
243
  def _run_task(self, task: AgentTask, result: OrchestratorResult):
233
244
  """Run a single task synchronously."""
@@ -242,16 +253,25 @@ class AgentOrchestrator:
242
253
 
243
254
  def _call_ai(self, task: AgentTask) -> Dict[str, Any]:
244
255
  """Send task to AI provider and track cost."""
245
- ai_result = self._provider.analyze(task.system_prompt, task.context)
246
- usage = ai_result.pop("_usage", {})
247
- self.cost_tracker.record_usage(
248
- provider=self._provider.name,
249
- model=self._provider.model,
250
- input_tokens=usage.get("input_tokens", 0),
251
- output_tokens=usage.get("output_tokens", 0),
252
- operation=f"agent_{task.role.value}",
253
- )
254
- return ai_result
256
+ with span("orchestrator.call_ai", {
257
+ "agent.role": task.role.value,
258
+ "provider": self._provider.name,
259
+ "model": self._provider.model,
260
+ }) as s:
261
+ ai_result = self._provider.analyze(task.system_prompt, task.context)
262
+ usage = ai_result.pop("_usage", {})
263
+ input_tokens = usage.get("input_tokens", 0)
264
+ output_tokens = usage.get("output_tokens", 0)
265
+ s.set_attribute("tokens.input", input_tokens)
266
+ s.set_attribute("tokens.output", output_tokens)
267
+ self.cost_tracker.record_usage(
268
+ provider=self._provider.name,
269
+ model=self._provider.model,
270
+ input_tokens=input_tokens,
271
+ output_tokens=output_tokens,
272
+ operation=f"agent_{task.role.value}",
273
+ )
274
+ return ai_result
255
275
 
256
276
  def _run_decision(self, result: OrchestratorResult, ctx: IaCContext):
257
277
  """Run decision agent using merged results from other agents."""
@@ -4,6 +4,7 @@ import logging
4
4
  from typing import Dict, Any
5
5
 
6
6
  from ..config.ai_settings import ProviderConfig
7
+ from ..tracing import span
7
8
 
8
9
  logger = logging.getLogger(__name__)
9
10
 
@@ -35,23 +36,25 @@ class AzureOpenAIProvider:
35
36
 
36
37
  def analyze(self, system_prompt: str, user_content: str) -> Dict[str, Any]:
37
38
  """Send analysis request to Azure OpenAI and return parsed JSON response."""
38
- response = self.client.chat.completions.create(
39
- model=self.model,
40
- messages=[
41
- {"role": "system", "content": system_prompt},
42
- {"role": "user", "content": user_content},
43
- ],
44
- max_tokens=self.max_tokens,
45
- temperature=self.temperature,
46
- response_format={"type": "json_object"},
47
- )
48
- usage = response.usage
49
- result = json.loads(response.choices[0].message.content)
50
- result["_usage"] = {
51
- "input_tokens": usage.prompt_tokens,
52
- "output_tokens": usage.completion_tokens,
53
- }
54
- return result
39
+ with span("provider.azure.analyze", {"model": self.model}) as s:
40
+ response = self.client.chat.completions.create(
41
+ model=self.model,
42
+ messages=[
43
+ {"role": "system", "content": system_prompt},
44
+ {"role": "user", "content": user_content},
45
+ ],
46
+ max_tokens=self.max_tokens,
47
+ temperature=self.temperature,
48
+ response_format={"type": "json_object"},
49
+ )
50
+ usage = response.usage
51
+ result = json.loads(response.choices[0].message.content)
52
+ input_tokens = usage.prompt_tokens
53
+ output_tokens = usage.completion_tokens
54
+ result["_usage"] = {"input_tokens": input_tokens, "output_tokens": output_tokens}
55
+ s.set_attribute("tokens.input", input_tokens)
56
+ s.set_attribute("tokens.output", output_tokens)
57
+ return result
55
58
 
56
59
  @property
57
60
  def name(self) -> str: