teddy-cli 0.1.17.dev1183__tar.gz → 0.1.17.dev1185__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 (159) hide show
  1. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/PKG-INFO +1 -1
  2. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/pyproject.toml +1 -1
  3. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/MRP.xml +4 -4
  4. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/config/prompts/debugger.xml +3 -3
  5. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/config/prompts/developer.xml +1 -1
  6. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/templates/PROJECT.md +7 -1
  7. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/templates/makefile.md +38 -3
  8. teddy_cli-0.1.17.dev1185/src/teddy_executor/resources/templates/pre-commit.md +149 -0
  9. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/.gitignore +0 -0
  10. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/LICENSE +0 -0
  11. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/__init__.py +0 -0
  12. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/__main__.py +0 -0
  13. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/__init__.py +0 -0
  14. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/inbound/__init__.py +0 -0
  15. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/inbound/cli_formatter.py +0 -0
  16. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/inbound/cli_helpers.py +0 -0
  17. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/inbound/session_cli_handlers.py +0 -0
  18. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/inbound/textual_plan_reviewer.py +0 -0
  19. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_app.py +0 -0
  20. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_editor.py +0 -0
  21. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_execution.py +0 -0
  22. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_helpers.py +0 -0
  23. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_logic.py +0 -0
  24. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_previews.py +0 -0
  25. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_widgets.py +0 -0
  26. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/__init__.py +0 -0
  27. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/console_interactor.py +0 -0
  28. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/console_interactor_ask_loop.py +0 -0
  29. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/console_interactor_helpers.py +0 -0
  30. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/console_tooling.py +0 -0
  31. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/filesystem_helpers.py +0 -0
  32. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/litellm_adapter.py +0 -0
  33. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/local_file_system_adapter.py +0 -0
  34. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/local_repo_tree_generator.py +0 -0
  35. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/openrouter_hydrator.py +0 -0
  36. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/shell_adapter.py +0 -0
  37. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/shell_command_builder.py +0 -0
  38. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/suppressed_logging.py +0 -0
  39. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/system_environment_adapter.py +0 -0
  40. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/system_environment_inspector.py +0 -0
  41. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/system_time_adapter.py +0 -0
  42. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/terminal_quit_key_listener.py +0 -0
  43. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/web_scraper_adapter.py +0 -0
  44. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/web_searcher_adapter.py +0 -0
  45. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/adapters/outbound/yaml_config_adapter.py +0 -0
  46. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/container.py +0 -0
  47. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/__init__.py +0 -0
  48. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/domain/__init__.py +0 -0
  49. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/domain/models/__init__.py +0 -0
  50. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/domain/models/action_ports.py +0 -0
  51. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/domain/models/change_set.py +0 -0
  52. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/domain/models/exceptions.py +0 -0
  53. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/domain/models/execution_report.py +0 -0
  54. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/domain/models/orchestrator_ports.py +0 -0
  55. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/domain/models/plan.py +0 -0
  56. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/domain/models/planning_ports.py +0 -0
  57. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/domain/models/project_context.py +0 -0
  58. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/domain/models/report_assembly_data.py +0 -0
  59. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/domain/models/session.py +0 -0
  60. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/domain/models/shell_output.py +0 -0
  61. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/domain/models/web_search_results.py +0 -0
  62. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/__init__.py +0 -0
  63. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/inbound/__init__.py +0 -0
  64. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/inbound/edit_simulator.py +0 -0
  65. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/inbound/get_context_use_case.py +0 -0
  66. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/inbound/init.py +0 -0
  67. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/inbound/plan_parser.py +0 -0
  68. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/inbound/plan_reviewer.py +0 -0
  69. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/inbound/plan_validator.py +0 -0
  70. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/inbound/planning_use_case.py +0 -0
  71. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/inbound/run_plan_use_case.py +0 -0
  72. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/__init__.py +0 -0
  73. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/config_service.py +0 -0
  74. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/environment_inspector.py +0 -0
  75. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/execution_report_assembler.py +0 -0
  76. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/file_system_manager.py +0 -0
  77. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/llm_client.py +0 -0
  78. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/markdown_report_formatter.py +0 -0
  79. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/prompt_manager.py +0 -0
  80. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/quit_key_listener.py +0 -0
  81. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/repo_tree_generator.py +0 -0
  82. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/session_loop_guard.py +0 -0
  83. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/session_manager.py +0 -0
  84. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/session_repository.py +0 -0
  85. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/shell_executor.py +0 -0
  86. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/system_environment.py +0 -0
  87. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/time_service.py +0 -0
  88. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/user_interactor.py +0 -0
  89. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/web_scraper.py +0 -0
  90. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/ports/outbound/web_searcher.py +0 -0
  91. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/__init__.py +0 -0
  92. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/action_changeset_builder.py +0 -0
  93. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/action_diff_manager.py +0 -0
  94. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/action_dispatcher.py +0 -0
  95. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/action_executor.py +0 -0
  96. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/action_factory.py +0 -0
  97. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/action_parser_complex.py +0 -0
  98. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/action_parser_strategies.py +0 -0
  99. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/context_service.py +0 -0
  100. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/edit_simulator.py +0 -0
  101. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/execution_orchestrator.py +0 -0
  102. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/execution_report_assembler.py +0 -0
  103. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/init_service.py +0 -0
  104. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/markdown_plan_parser.py +0 -0
  105. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/markdown_report_formatter.py +0 -0
  106. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/parser_infrastructure.py +0 -0
  107. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/parser_metadata.py +0 -0
  108. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/parser_reporting.py +0 -0
  109. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/plan_validator.py +0 -0
  110. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/planning_service.py +0 -0
  111. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/prompt_manager.py +0 -0
  112. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/session_lifecycle_manager.py +0 -0
  113. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/session_loop_guard.py +0 -0
  114. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/session_orchestrator.py +0 -0
  115. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/session_planner.py +0 -0
  116. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/session_pruning_service.py +0 -0
  117. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/session_replanner.py +0 -0
  118. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/session_repository.py +0 -0
  119. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/session_service.py +0 -0
  120. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/templates/execution_report.md.j2 +0 -0
  121. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/update_checker.py +0 -0
  122. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/validation_rules/__init__.py +0 -0
  123. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/validation_rules/edit.py +0 -0
  124. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/validation_rules/edit_matcher.py +0 -0
  125. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/validation_rules/edit_matcher_heuristics.py +0 -0
  126. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/validation_rules/execute.py +0 -0
  127. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/validation_rules/filesystem.py +0 -0
  128. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/validation_rules/helpers.py +0 -0
  129. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/services/validation_rules/message.py +0 -0
  130. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/utils/__init__.py +0 -0
  131. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/utils/diff.py +0 -0
  132. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/utils/interrupt_guard.py +0 -0
  133. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/utils/io.py +0 -0
  134. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/utils/markdown.py +0 -0
  135. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/utils/serialization.py +0 -0
  136. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/utils/stdin_ownership.py +0 -0
  137. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/utils/string.py +0 -0
  138. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/core/utils/terminal.py +0 -0
  139. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/prompts.py +0 -0
  140. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/registries/__init__.py +0 -0
  141. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/registries/infrastructure.py +0 -0
  142. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/registries/reviewer.py +0 -0
  143. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/registries/validators.py +0 -0
  144. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/__init__.py +0 -0
  145. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/config/__init__.py +0 -0
  146. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/config/config.yaml +0 -0
  147. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/config/init.context +0 -0
  148. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/config/prompts/architect.xml +0 -0
  149. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/config/prompts/assistant.xml +0 -0
  150. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/config/prompts/pathfinder.xml +0 -0
  151. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/config/prompts/prototyper.xml +0 -0
  152. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/templates/ARCHITECTURE.md +0 -0
  153. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/templates/case-file.md +0 -0
  154. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/templates/ci.md +0 -0
  155. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/templates/component-design.md +0 -0
  156. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/templates/milestone.md +0 -0
  157. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/templates/specification-document.md +0 -0
  158. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/templates/task-brief.md +0 -0
  159. {teddy_cli-0.1.17.dev1183 → teddy_cli-0.1.17.dev1185}/src/teddy_executor/resources/templates/vertical-slice.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: teddy-cli
3
- Version: 0.1.17.dev1183
3
+ Version: 0.1.17.dev1185
4
4
  Summary: A local-first, file-based AI coding workflow that applies the UNIX philosophy to AI collaboration.
5
5
  Author: Raphael Atteritano
6
6
  License: AGPL-3.0-only
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "teddy-cli"
3
- version = "0.1.17.dev1183"
3
+ version = "0.1.17.dev1185"
4
4
  description = "A local-first, file-based AI coding workflow that applies the UNIX philosophy to AI collaboration."
5
5
  authors = [{ name = "Raphael Atteritano" }]
6
6
  license = { text = "AGPL-3.0-only" }
@@ -50,7 +50,7 @@ WIP & REMINDERS:
50
50
  The entire commit cycle (test, stage, commit, push) MUST occur in a dedicated Version Control turn.
51
51
  1. Pre-conditions: Clean up temporary files (spikes/, .tmp/). If unsure of changes, `EXECUTE git add . && git diff HEAD`.
52
52
  2. Commit Message: Use Conventional Commits '<type>(<scope>): <description>' wrapped in single quotes. Use imperative mood. Append ! for breaking changes.
53
- 3. Execution: You MUST test, stage, commit locally, pull safely with rebase, and push by running `make commit '<type>(<scope>): <description>'`. If a `Makefile` does not exist in the project root, you MUST first create one following the template at `docs/templates/makefile.md`. To bypass pre-commit checks (e.g., for known false positives), use `make commit '<type>(<scope>): <description>' no-verify`.
53
+ 3. Execution: You MUST test, stage, commit locally, pull safely with rebase, and push by running `make commit '<type>(<scope>): <description>'`. To bypass pre-commit checks (e.g., for known false positives), use `make commit '<type>(<scope>): <description>' no-verify`.
54
54
  4. Post-conditions: All tests MUST pass (post-commit hook enforces this; never bypass). Pre-commit may be bypassed with --no-verify if needed to bypass non-trivial quality gate failures (like file length). If pre-commit is bypassed, you MUST make a follow-up cleanup commit that resolves the bypassed issues before resuming feature work, and log the debt in PROJECT.md if it cannot be resolved immediately.
55
55
  </rule>
56
56
 
@@ -79,11 +79,11 @@ WIP & REMINDERS:
79
79
  7. You are strictly forbidden from wasting turns sending a `## Message` to the user about a validation error. Validation errors are internal formatting mistakes; silently fix and resubmit.
80
80
  </rule>
81
81
 
82
- <rule n="10" name="Conflict Resolution Protocol">If any git rebase/pull fails or conflicts: 1. Identify conflicted files via `git status`. 2. `READ` and surgically `EDIT` those files to resolve conflict markers. 3. Run the full test suite to verify correctness. 4. Stage resolved files via `git add`. 5. Complete the rebase via `EXECUTE git rebase --continue`.</rule>
82
+ <rule n="10" name="Conflict Resolution Protocol">If any git rebase/pull fails or conflicts: 1. Identify conflicted files via `git status`. 2. `READ` and surgically `EDIT` those files to resolve conflict markers. 3. Run the full test suite via `make test` to verify correctness. 4. Stage resolved files via `git add`. 5. Complete the rebase via `EXECUTE git rebase --continue`.</rule>
83
83
  <rule n="11" name="Programmatic Edits">You may use `EXECUTE` with bash tools to modify files when surgical `EDIT` matching is brittle or for bulk changes. You MUST scope these actions to specific files and chain a verification command to output the results. Example: `sed 's/old/new/g' <file> > <file>.tmp && mv <file>.tmp <file> && git grep "new_string" <file>`</rule>
84
84
 
85
- <rule n="12" name="Template-First Documentation">
86
- <description>Before creating or modifying a documentation file under docs/, you MUST first READ the corresponding template from docs/templates/. Templates define the required structure and format for each artifact type. Template files are named by artifact type (e.g., specification-document.md, task-brief.md, case-file.md, PROJECT.md, ARCHITECTURE.md). If no template exists for your artifact, READ the most similar one as a reference.</description>
85
+ <rule n="12" name="Template-First Documentation & Tooling">
86
+ <description>Before creating or modifying a documentation file under docs/, you MUST first READ the corresponding template from docs/templates/. Templates define the required structure and format for each artifact type. Template files are named by artifact type (e.g., specification-document.md, task-brief.md, case-file.md, PROJECT.md, ARCHITECTURE.md, ci.md, pre-commit.md, makefile.md). If no template exists for your artifact, READ the most similar one as a reference. The same template-first principle governs project tooling: before invoking any project command (e.g., `make commit`, `make probe`, `make logs`, `make test`), if the `Makefile` does not exist in the project root you MUST create one following the template at `docs/templates/makefile.md`; and if the `Makefile` already exists but lacks the required target, you MUST add that target following that same template. The `makefile.md` template defines how the targets SHOULD look (usage, recipe, and cross-platform conventions). Likewise, project infrastructure configuration is template-first: when creating or modifying a CI workflow you MUST follow `docs/templates/ci.md`, and when setting up or modifying pre-commit hooks (including the post-commit test gate) you MUST follow `docs/templates/pre-commit.md`; create either file if it does not exist.</description>
87
87
  </rule>
88
88
 
89
89
  <rule n="13" name="Communication Hygiene">
@@ -13,7 +13,7 @@
13
13
  <phase n="1" name="Reproduction">
14
14
  <goal>Gather context and build/verify an end-to-end Minimal Reproducible Example (MRE).</goal>
15
15
  <step n="1" name="Case File Check">If a Case File was not provided in the initial context, you MUST CREATE one following the Case File Blueprint.</step>
16
- <step n="2" name="Context & History Gathering">Use `EXECUTE` (`git grep`, `git log -n 5 --stat`), `READ`, and `RESEARCH` to understand the codebase, recent changes, and identify the last known green CI run or commit. For historical CI failures, do NOT try to read the entire log. You MUST first use `gh run view [ID]` to see the execution tree and identify the exact name of the failed step. Then, extract ONLY that step's logs (stripping ANSI and boilerplate) by executing: `gh run view [ID] --log | awk -F'\t' '$2=="[FAILED_STEP_NAME]" { if(j!=$1){j=$1; print "\n["j"]"} l=$3; p=index(l,"Z "); if(p>0)l=substr(l,p+2); gsub(/\x1B\[[0-9;]*[a-zA-Z]/, "", l); gsub(/\^\[\[[0-9;]*[a-zA-Z]/, "", l); if(l ~ /^##\[group\]Run /){k=1;next} if(k && l ~ /^##\[endgroup\]/){k=0;next} if(k)next; if(l ~ /^##\[group\]/ || l ~ /^##\[endgroup\]/)next; gsub(/^##\[error\]/, "Error: ", l); print l }'`.</step>
16
+ <step n="2" name="Context & History Gathering">Use `EXECUTE` (`git grep`, `git log -n 5 --stat`), `READ`, and `RESEARCH` to understand the codebase, recent changes, and identify the last known green CI run or commit. For historical CI failures, do NOT try to read the entire log. You MUST first use `gh run view [ID]` to see the execution tree and identify the exact name of the failed step. Then, extract ONLY that step's logs (stripping ANSI and boilerplate) by executing `make logs [ID] '[FAILED_STEP_NAME]'` (see [docs/templates/makefile.md](docs/templates/makefile.md) for the CI Log Extraction target).</step>
17
17
  <step n="3" name="Diagnostic MRE & Platform Check">CREATE a self-contained MRE script (`spikes/debug/{{NN}}-{{bug_title}}-mre.{{ext}}`) that imports the target components directly from `src/` to reproduce the symptom of the bug. It MUST fail currently. If the bug depends on specific environment conditions, mock them inside the script without permanently changing the host. Immediately after execution, `EDIT` the Case File to establish the causal baseline. If the bug is platform-specific (e.g., fails in CI but passes locally), immediately pivot to the Remote Probing Protocol (RPP) and skip local reproduction. If you determine the bug is platform-specific after a local attempt, you MUST NOT continue local work; transition to Remote Probing for all subsequent checks.</step>
18
18
  </phase>
19
19
 
@@ -61,7 +61,7 @@
61
61
  <step n="2" name="Red Phase">EXECUTE the newly created regression test in isolation to confirm it fails (RED). This empirically proves the test correctly captures the original bug. If the test passes, it does not accurately reproduce the bug; return to step 1 and refine the test.</step>
62
62
  <step n="3" name="Apply Fix">Apply the verified hypothesis from the shadow file to the target production file(s) in `src/`. Execute the regression test again to confirm it now passes (GREEN). This proves the fix resolves the specific bug.</step>
63
63
  <step n="4" name="MRE Re-Verification">Re-run the original MRE script against the fixed production code to confirm the exact original symptom is resolved. This ensures the regression test did not accidentally over-specify or under-specify the bug; the original reproduction scenario must still pass against the real fixed code.</step>
64
- <step n="5" name="Integration Verification">EXECUTE the entire test suite (acceptance, unit and integration) to ensure no regressions were introduced. If any test fails, revert all changes via `git reset --hard` and return to the Investigation phase.</step>
64
+ <step n="5" name="Integration Verification">EXECUTE `make test` to run the entire suite (acceptance, unit and integration) and ensure no regressions were introduced. If any test fails, revert all changes via `git reset --hard` and return to the Investigation phase.</step>
65
65
  </phase>
66
66
 
67
67
  <phase n="7" name="Version Control">
@@ -82,7 +82,7 @@
82
82
  <description>For CI/platform-specific bugs that cannot be probed locally.</description>
83
83
  1. Pre-flight Check: Verify that `.github/workflows/debug.yml` exists. You MUST first READ docs/templates/ci.md before creating or modifying the debug workflow. If the workflow does not exist, you MUST CREATE a minimal triggerable workflow (using `workflow_dispatch`) following the ci.md template, and commit it before proceeding.
84
84
  2. Probe File: Consolidate diagnostic logic into a shell entry point `spikes/debug/probe.sh`. Before writing the probe script, first READ the makefile.md template at `docs/templates/makefile.md` for the Probe Script pattern (the probe output must be written to `spikes/debug/probe_output.txt` for artifact upload). You SHOULD use the "Heredoc" pattern to keep the probe to a single file.
85
- 3. Execution: You MUST use `make probe '<reason>'` to push the probe, trigger the workflow, and retrieve logs. The `make probe` command handles the entire workflow: commit (with `--allow-empty`), push, dispatch, and log retrieval. If a `Makefile` does not exist in the project root, you MUST first create one following the template at `docs/templates/makefile.md`.
85
+ 3. Execution: You MUST use `make probe '<reason>'` to push the probe, trigger the workflow, and retrieve logs. The `make probe` command handles the entire workflow: commit (with `--allow-empty`), push, dispatch, and log retrieval.
86
86
  </rule>
87
87
  </workflow>
88
88
 
@@ -69,7 +69,7 @@
69
69
  <phase n="3" name="Integration">
70
70
  <goal>Mandatory Gate ensuring continuous integration scoped at the deliverable level.</goal>
71
71
  <step n="1" name="Global Test Run">
72
- Run the full test suite (no filters). If it passes, proceed to Phase 4. If it fails, proceed to Fault Evaluation.
72
+ Run the full test suite via `make test` (no filters). If it passes, proceed to Phase 4. If it fails, proceed to Fault Evaluation.
73
73
  </step>
74
74
  <step n="2" name="Fault Evaluation">
75
75
  Classify the failure using this empirical rule: If fixing the global suite requires modifying ANY application code outside the exact scope of your current deliverable, it is a Systemic Regression. If the fix ONLY requires modifying the current deliverable's components or updating existing test files, it is a Local Flaw.
@@ -17,7 +17,12 @@ Defines the high-level artifact lifecycle and conventions for project management
17
17
 
18
18
  ### Required Topics:
19
19
  - **Artifact Lifecycle:** How work flows (e.g., Spec → Milestone → Slice).
20
- - **Numbering:** Sequential MM-NN format, 00 prefix for ad-hoc work.
20
+ - **Numbering:** Artifacts are numbered sequentially using a per-type filename convention so agents can infer the correct filename:
21
+ - **Vertical Slices:** `MM-NN-name.md` (in `docs/project/slices/`) — `MM` is the target Milestone number and `NN` is the sequence number within that milestone.
22
+ - **Milestones:** `MM-name.md` (in `docs/project/milestones/`).
23
+ - **Case Files (Debugger):** `NN-name.md` — numbered sequentially.
24
+ - **Task Briefs:** `NN-name.md` (in `docs/project/tasks/`) — numbered sequentially.
25
+ - **Ad-hoc work (not tied to a milestone):** `00-NN-name.md` — `00` is used as the Milestone prefix. Ad-hoc slices are NOT tracked in Milestone documents or the Roadmap.
21
26
  - **Archiving Policy:** When and how completed artifacts are archived or deleted.
22
27
  - **Spec Organization:** Organize specification documents by lifecycle into two subfolders: `docs/project/specs/invariants/` (formats, contracts, and workflows of record — long-lived system invariants) and `docs/project/specs/features/` (to-be-implemented initiatives that feed the Spec → Milestone → Slice lifecycle — deleted per the Archiving Policy once implemented).
23
28
  - **Run Environment:** Specify the project's designated environment/dependency manager (e.g., `uv`, `poetry`, `pip`) and prefix ALL execution commands with its runner (e.g., `uv run pytest`). The chosen runner MUST be reflected in the `Makefile`.
@@ -39,6 +44,7 @@ Before creating or modifying any documentation artifact, agents MUST read the co
39
44
  | `ARCHITECTURE.md` | System architecture document |
40
45
  | `makefile.md` | Makefile (VCP commit + Remote Probing Protocol commands) |
41
46
  | `ci.md` | CI workflow template (debug workflow for the Remote Probing Protocol) |
47
+ | `pre-commit.md` | Pre-commit framework setup (pre-commit + post-commit test gate) |
42
48
 
43
49
  These files live in `docs/templates/` and are created or refreshed by `teddy init templates`.
44
50
 
@@ -14,7 +14,7 @@ make commit 'fix(tests): resolve flaky assertion' no-verify
14
14
  ```
15
15
 
16
16
  **What is `.PHONY`?**
17
- `.PHONY` is a Makefile directive that declares `commit`, `probe`, and `test` as phony targets — they do not correspond to actual files. Without `.PHONY`, if a file named `commit` or `probe` existed in the directory (e.g., a script called `commit`), Make would see it as up-to-date and skip the target entirely. By declaring them phony, Make always runs the recipe when you call `make commit`, `make probe`, or `make test`.
17
+ `.PHONY` is a Makefile directive that declares `commit`, `probe`, `test`, and `logs` as phony targets — they do not correspond to actual files. Without `.PHONY`, if a file named `commit` or `probe` existed in the directory (e.g., a script called `commit`), Make would see it as up-to-date and skip the target entirely. By declaring them phony, Make always runs the recipe when you call `make commit`, `make probe`, or `make test`.
18
18
 
19
19
  ### Test
20
20
  ```shell
@@ -32,6 +32,14 @@ make probe 'investigate windows path handling'
32
32
  **Why does `probe` need a reason?**
33
33
  The Remote Probing Protocol requires a reason string because it is passed as the `reason` input to the GitHub Actions workflow dispatch command (`gh workflow run debug.yml --field reason='...'`). The reason documents what the probe is investigating and appears in the workflow run metadata.
34
34
 
35
+ ### Logs
36
+ ```shell
37
+ make logs 12345 'Run tests'
38
+ ```
39
+
40
+ **Why does `logs` take two arguments?**
41
+ The first argument is the GitHub Actions run ID (as shown by `gh run list`); the second is the exact name of a step in that run's execution tree (as shown by `gh run view <id>`). The target extracts ONLY that step's logs, stripping ANSI escapes and GitHub's group/boilerplate markers so you see the failure without the noise of the full log. See the [CI Log Extraction](#ci-log-extraction) section for the recipe.
42
+
35
43
  ## Probe Script
36
44
 
37
45
  The Debugger's Remote Probing Protocol pushes a local `spikes/debug/probe.sh` script to the CI runner via a workflow dispatch. The probe script MUST output diagnostics to `spikes/debug/probe_output.txt` so the workflow can upload it as an artifact for retrieval.
@@ -124,10 +132,37 @@ probe:
124
132
 
125
133
  **Usage:** `make probe 'investigate windows path handling'`
126
134
 
135
+ ## CI Log Extraction
136
+
137
+ The Debugger's Reproduction phase needs to read the logs of a specific failed CI step without drowning in the full run log. The `make logs` target wraps the `gh run view <id> --log | awk ...` pipeline that isolates the named step's output, strips ANSI escapes, and removes GitHub's `##[group]`/`##[endgroup]` boilerplate.
138
+
139
+ ### Example
140
+
141
+ ```makefile
142
+ logs: LOGS_RUN := $(word 1,$(filter-out logs,$(MAKECMDGOALS)))
143
+ logs: LOGS_STEP := $(wordlist 2,99,$(filter-out logs,$(MAKECMDGOALS)))
144
+
145
+ logs:
146
+ @[ -n "$(LOGS_RUN)" ] || { echo "Usage: make logs <run-id> '<step-name>'"; exit 1; }
147
+ @gh run view "$(LOGS_RUN)" --log | awk -F'\t' -v step="$(LOGS_STEP)" '$$2==step { if(j!=$$1){j=$$1; print "\n["j"]"} l=$$3; p=index(l,"Z "); if(p>0)l=substr(l,p+2); gsub(/\x1B\[[0-9;]*[a-zA-Z]/, "", l); gsub(/\^\[\[[0-9;]*[a-zA-Z]/, "", l); if(l ~ /^##\[group\]Run /){k=1;next} if(k && l ~ /^##\[endgroup\]/){k=0;next} if(k)next; if(l ~ /^##\[group\]/ || l ~ /^##\[endgroup\]/)next; gsub(/^##\[error\]/, "Error: ", l); print l }'
148
+
149
+ %:
150
+ @:
151
+ ```
152
+
153
+ **Usage:**
154
+ - `make logs 12345 'Run tests'` — extract the logs of the step named `Run tests` from run `12345`.
155
+ - First discover the run ID and the failed step name with `gh run view 12345` (the execution tree), then pass both to `make logs`.
156
+
157
+ **How it works:**
158
+ - `$(filter-out logs,$(MAKECMDGOALS))` drops the target name from the goal list; `$(word 1, ...)` takes the run ID and `$(wordlist 2,99, ...)` takes the (space-containing) step name.
159
+ - The `awk` program matches rows whose second tab-separated field equals the step name via `-v step=...`, trims the leading timestamp, strips ANSI escape sequences, and removes GitHub's group boilerplate, prefixing `##[error]` lines with `Error: `.
160
+ - It reuses the same cross-platform Make constructs as the other targets (see [Cross-Platform Design](#cross-platform-design)); the `%: @:` catch-all prevents the extra `make` goals from being treated as files.
161
+
127
162
  ## Implementation Notes
128
163
 
129
164
  - This project uses `uv run` as its designated runner.
130
165
  - Pre-commit hooks include: ruff, mypy, detect-secrets, pip-audit.
131
166
  - Post-commit hook lives at `.githooks/post-commit.py` and runs the full `uv run pytest` suite.
132
- - Ensure `gh` (GitHub CLI) is authenticated for Remote Probing.
133
- - Refer to the Debugger's rule 11 in the agent XML for the exact awk command to extract CI logs.
167
+ - Ensure `gh` (GitHub CLI) is authenticated for both the Remote Probing Protocol and CI Log Extraction.
168
+ - The `make logs` target abstracts the Debugger's CI-log extraction (Phase 1, Step 2). See [CI Log Extraction](#ci-log-extraction).
@@ -0,0 +1,149 @@
1
+ # Pre-Commit Template
2
+
3
+ > **⚠️ This is an example template.** Adapt the runner, hook set, and tool-specific details (e.g., `uv run`, the pre-commit hook list) to match your project's actual setup. The concrete examples shown may not work verbatim in all environments.
4
+
5
+ This template documents how to set up the [Pre-commit](https://pre-commit.com/) framework as the project's local quality gate. It runs fast checks before a commit is recorded and the full test suite after, keeping the repository green-to-green.
6
+
7
+ Pre-commit has two stages:
8
+
9
+ - **`pre-commit`** — fast checks (formatters, linters, type checkers, secret scanners), scoped strictly to the files being committed.
10
+ - **`post-commit`** — the full test suite, run after the commit is recorded. If it fails, the commit is reverted while keeping the changes staged. This stage is **not** affected by `--no-verify` and is the only truly unskippable gate.
11
+
12
+ ## 1. Install the Pre-commit framework
13
+
14
+ ```shell
15
+ uv tool install pre-commit # or: pip install pre-commit # or: brew install pre-commit
16
+ pre-commit --version
17
+ ```
18
+
19
+ ## 2. Create `.pre-commit-config.yaml`
20
+
21
+ Place this in the project root. Start with the universal hooks, then add security and project-local hooks that shell out to the project runner.
22
+
23
+ ```yaml
24
+ # Exclude experimental sandboxes from every hook.
25
+ exclude: '^spikes/'
26
+ repos:
27
+ # ── Universal (every project) ──
28
+ - repo: https://github.com/pre-commit/pre-commit-hooks
29
+ rev: v6.0.0
30
+ hooks:
31
+ - id: trailing-whitespace
32
+ - id: end-of-file-fixer
33
+ - id: check-toml
34
+ - id: check-added-large-files
35
+ args: ['--maxkb=500']
36
+ - id: check-case-conflict
37
+ - id: check-merge-conflict
38
+
39
+ # ── Secrets & security ──
40
+ - repo: https://github.com/Yelp/detect-secrets
41
+ rev: v1.5.0
42
+ hooks:
43
+ - id: detect-secrets
44
+ args: ['--baseline', '.secrets.baseline']
45
+ - repo: https://github.com/PyCQA/bandit
46
+ rev: 1.7.9
47
+ hooks:
48
+ - id: bandit
49
+ args: ["-c", "pyproject.toml"]
50
+ exclude: ^(tests|spikes)/
51
+
52
+ # ── Language-specific: run tools through the project runner ──
53
+ - repo: local
54
+ hooks:
55
+ - id: ruff-lint
56
+ name: Ruff Linter
57
+ entry: uv run ruff check --fix --force-exclude
58
+ language: system
59
+ types: [python]
60
+ require_serial: true
61
+ - id: ruff-format
62
+ name: Ruff Formatter
63
+ entry: uv run ruff format --force-exclude
64
+ language: system
65
+ types: [python]
66
+ require_serial: true
67
+ - id: mypy
68
+ name: Mypy
69
+ entry: uv run mypy
70
+ language: system
71
+ types: [python]
72
+ require_serial: true
73
+
74
+ # ── Post-commit test gate (unskippable) ──
75
+ - repo: local
76
+ hooks:
77
+ - id: post-commit-test-gate
78
+ name: Post-commit test gate
79
+ entry: uv run python .githooks/post-commit.py
80
+ language: system
81
+ stages: [post-commit]
82
+ always_run: true
83
+ pass_filenames: false
84
+ ```
85
+
86
+ **Tip:** Pin exact `rev` tags so every teammate runs identical checks.
87
+
88
+ ## 3. Install the hooks
89
+
90
+ ```shell
91
+ pre-commit install # pre-commit stage
92
+ pre-commit install --hook-type post-commit # post-commit test gate
93
+ ```
94
+
95
+ `pre-commit install` writes the runner into `.git/hooks/`. The pre-commit stage runs only against the files you have staged; the post-commit stage runs the full suite after every commit.
96
+
97
+ ## 4. Run hooks manually
98
+
99
+ ```shell
100
+ pre-commit run --all-files # run all pre-commit hooks against the repo (first setup)
101
+ pre-commit run ruff-lint --all-files # run a single hook
102
+ ```
103
+
104
+ `--all-files` is for the initial setup only; normal commits check just the staged files.
105
+
106
+ ## 5. The post-commit test gate
107
+
108
+ The post-commit stage is the unskippable safety net. It invokes a project script (e.g. `.githooks/post-commit.py`) that:
109
+
110
+ 1. Verifies the runner and test framework are available, printing a clear, actionable error if not.
111
+ 2. Runs the full test suite via the project's test command (e.g. `make test` / `uv run pytest`).
112
+ 3. On failure, reverts the commit with `git reset --soft HEAD~1`, keeping the changes staged for investigation.
113
+
114
+ ```python
115
+ # .githooks/post-commit.py (sketch)
116
+ import subprocess
117
+ import sys
118
+
119
+
120
+ def main() -> None:
121
+ # Pre-flight: verify the runner + test framework are available.
122
+ # Run the full suite.
123
+ result = subprocess.run(["uv", "run", "pytest", "--tb=short", "-q"])
124
+ # On failure, revert the commit but keep the changes staged.
125
+ if result.returncode != 0:
126
+ print("TESTS FAILED \u2014 reverting commit")
127
+ subprocess.run(["git", "reset", "--soft", "HEAD~1"], check=True)
128
+ sys.exit(1)
129
+
130
+
131
+ if __name__ == "__main__":
132
+ main()
133
+ ```
134
+
135
+ Because the hook is declared with `stages: [post-commit]`, `git commit --no-verify` cannot bypass it.
136
+
137
+ ## 6. Bypass (emergency only)
138
+
139
+ ```shell
140
+ git commit --no-verify # skip the pre-commit stage for this commit
141
+ SKIP=ruff-lint git commit # skip a single hook
142
+ ```
143
+
144
+ The **post-commit test gate is never bypassable**. Treat a pre-commit bypass as a temporary measure followed by a cleanup commit that resolves the underlying issue.
145
+
146
+ ## Reference
147
+ - [ARCHITECTURE.md Template](./ARCHITECTURE.md) — pre-commit + post-commit conventions.
148
+ - [Makefile Template](./makefile.md) — `make test` and the VCP commit workflow.
149
+ - [Pre-commit documentation](https://pre-commit.com/)