teddy-cli 0.1.17.dev1383__tar.gz → 0.1.17.dev1385__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 (163) hide show
  1. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/PKG-INFO +1 -1
  2. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/pyproject.toml +1 -1
  3. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/markdown_plan_parser.py +53 -8
  4. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/parser_infrastructure.py +28 -21
  5. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/utils/paths.py +31 -7
  6. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/.gitignore +0 -0
  7. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/LICENSE +0 -0
  8. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/README.md +0 -0
  9. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/__init__.py +0 -0
  10. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/__main__.py +0 -0
  11. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/__init__.py +0 -0
  12. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/inbound/__init__.py +0 -0
  13. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/inbound/cli_formatter.py +0 -0
  14. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/inbound/cli_helpers.py +0 -0
  15. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/inbound/session_cli_handlers.py +0 -0
  16. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/inbound/textual_plan_reviewer.py +0 -0
  17. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_app.py +0 -0
  18. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_editor.py +0 -0
  19. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_execution.py +0 -0
  20. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_helpers.py +0 -0
  21. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_logic.py +0 -0
  22. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_previews.py +0 -0
  23. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_widgets.py +0 -0
  24. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/__init__.py +0 -0
  25. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/console_interactor.py +0 -0
  26. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/console_interactor_ask_loop.py +0 -0
  27. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/console_interactor_helpers.py +0 -0
  28. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/console_tooling.py +0 -0
  29. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/filesystem_helpers.py +0 -0
  30. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/litellm_adapter.py +0 -0
  31. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/local_file_system_adapter.py +0 -0
  32. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/local_repo_tree_generator.py +0 -0
  33. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/openrouter_hydrator.py +0 -0
  34. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/shell_adapter.py +0 -0
  35. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/shell_command_builder.py +0 -0
  36. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/suppressed_logging.py +0 -0
  37. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/system_environment_adapter.py +0 -0
  38. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/system_environment_inspector.py +0 -0
  39. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/system_time_adapter.py +0 -0
  40. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/terminal_quit_key_listener.py +0 -0
  41. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/web_scraper_adapter.py +0 -0
  42. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/web_searcher_adapter.py +0 -0
  43. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/adapters/outbound/yaml_config_adapter.py +0 -0
  44. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/container.py +0 -0
  45. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/__init__.py +0 -0
  46. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/__init__.py +0 -0
  47. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/models/__init__.py +0 -0
  48. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/models/action_ports.py +0 -0
  49. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/models/change_set.py +0 -0
  50. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/models/drift_report.py +0 -0
  51. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/models/exceptions.py +0 -0
  52. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/models/execution_report.py +0 -0
  53. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/models/orchestrator_ports.py +0 -0
  54. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/models/plan.py +0 -0
  55. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/models/planning_ports.py +0 -0
  56. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/models/project_context.py +0 -0
  57. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/models/report_assembly_data.py +0 -0
  58. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/models/session.py +0 -0
  59. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/models/shell_output.py +0 -0
  60. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/domain/models/web_search_results.py +0 -0
  61. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/__init__.py +0 -0
  62. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/inbound/__init__.py +0 -0
  63. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/inbound/edit_simulator.py +0 -0
  64. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/inbound/get_context_use_case.py +0 -0
  65. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/inbound/init.py +0 -0
  66. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/inbound/plan_parser.py +0 -0
  67. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/inbound/plan_reviewer.py +0 -0
  68. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/inbound/plan_validator.py +0 -0
  69. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/inbound/planning_use_case.py +0 -0
  70. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/inbound/run_plan_use_case.py +0 -0
  71. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/__init__.py +0 -0
  72. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/config_service.py +0 -0
  73. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/environment_inspector.py +0 -0
  74. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/execution_report_assembler.py +0 -0
  75. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/file_system_manager.py +0 -0
  76. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/llm_client.py +0 -0
  77. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/markdown_report_formatter.py +0 -0
  78. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/prompt_manager.py +0 -0
  79. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/quit_key_listener.py +0 -0
  80. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/repo_tree_generator.py +0 -0
  81. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/session_loop_guard.py +0 -0
  82. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/session_manager.py +0 -0
  83. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/session_repository.py +0 -0
  84. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/shell_executor.py +0 -0
  85. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/system_environment.py +0 -0
  86. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/time_service.py +0 -0
  87. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/user_interactor.py +0 -0
  88. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/web_scraper.py +0 -0
  89. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/ports/outbound/web_searcher.py +0 -0
  90. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/__init__.py +0 -0
  91. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/action_changeset_builder.py +0 -0
  92. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/action_diff_manager.py +0 -0
  93. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/action_dispatcher.py +0 -0
  94. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/action_executor.py +0 -0
  95. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/action_factory.py +0 -0
  96. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/action_parser_complex.py +0 -0
  97. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/action_parser_strategies.py +0 -0
  98. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/context_service.py +0 -0
  99. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/edit_simulator.py +0 -0
  100. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/execution_orchestrator.py +0 -0
  101. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/execution_report_assembler.py +0 -0
  102. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/init_service.py +0 -0
  103. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/markdown_report_formatter.py +0 -0
  104. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/parser_metadata.py +0 -0
  105. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/parser_reporting.py +0 -0
  106. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/plan_validator.py +0 -0
  107. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/planning_service.py +0 -0
  108. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/prompt_manager.py +0 -0
  109. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/session_lifecycle_manager.py +0 -0
  110. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/session_loop_guard.py +0 -0
  111. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/session_orchestrator.py +0 -0
  112. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/session_planner.py +0 -0
  113. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/session_pruning_service.py +0 -0
  114. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/session_replanner.py +0 -0
  115. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/session_repository.py +0 -0
  116. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/session_service.py +0 -0
  117. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/templates/execution_report.md.j2 +0 -0
  118. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/update_checker.py +0 -0
  119. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/validation_rules/__init__.py +0 -0
  120. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/validation_rules/edit.py +0 -0
  121. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/validation_rules/edit_matcher.py +0 -0
  122. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/validation_rules/edit_matcher_heuristics.py +0 -0
  123. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/validation_rules/execute.py +0 -0
  124. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/validation_rules/filesystem.py +0 -0
  125. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/validation_rules/helpers.py +0 -0
  126. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/services/validation_rules/message.py +0 -0
  127. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/utils/__init__.py +0 -0
  128. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/utils/diff.py +0 -0
  129. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/utils/editor_names.py +0 -0
  130. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/utils/interrupt_guard.py +0 -0
  131. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/utils/io.py +0 -0
  132. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/utils/markdown.py +0 -0
  133. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/utils/serialization.py +0 -0
  134. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/utils/session_notices.py +0 -0
  135. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/utils/stdin_ownership.py +0 -0
  136. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/utils/string.py +0 -0
  137. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/core/utils/terminal.py +0 -0
  138. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/prompts.py +0 -0
  139. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/registries/__init__.py +0 -0
  140. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/registries/infrastructure.py +0 -0
  141. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/registries/reviewer.py +0 -0
  142. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/registries/validators.py +0 -0
  143. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/MRP.md +0 -0
  144. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/__init__.py +0 -0
  145. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/config/__init__.py +0 -0
  146. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/config/config.yaml +0 -0
  147. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/config/init.context +0 -0
  148. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/config/prompts/architect.md +0 -0
  149. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/config/prompts/assistant.md +0 -0
  150. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/config/prompts/debugger.md +0 -0
  151. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/config/prompts/developer.md +0 -0
  152. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/config/prompts/pathfinder.md +0 -0
  153. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/config/prompts/prototyper.md +0 -0
  154. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/templates/ARCHITECTURE.md +0 -0
  155. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/templates/PROJECT.md +0 -0
  156. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/templates/case-file.md +0 -0
  157. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/templates/ci.md +0 -0
  158. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/templates/component-design.md +0 -0
  159. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/templates/makefile.md +0 -0
  160. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/templates/milestone.md +0 -0
  161. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/templates/pre-commit.md +0 -0
  162. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/src/teddy_executor/resources/templates/specification-document.md +0 -0
  163. {teddy_cli-0.1.17.dev1383 → teddy_cli-0.1.17.dev1385}/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.dev1383
3
+ Version: 0.1.17.dev1385
4
4
  Summary: The local-first, test-driven agentic engineering harness. Because you should own the means of development.
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.dev1383"
3
+ version = "0.1.17.dev1385"
4
4
  description = "The local-first, test-driven agentic engineering harness. Because you should own the means of development."
5
5
  readme = "README.md"
6
6
  keywords = [
@@ -110,6 +110,15 @@ class MarkdownPlanParser(IPlanParser):
110
110
  if current_disk is not None and current_disk.rstrip() != clean_content:
111
111
  path_obj.write_text(clean_content, encoding="utf-8", newline="")
112
112
 
113
+ @staticmethod
114
+ def _truncate_plan_content(clean_content: str, first_trailing_line: int) -> str:
115
+ """Drop the trailing paragraph run that starts at the given line."""
116
+ # Keep the splitlines basis. Mistletoe splits the document with
117
+ # splitlines(keepends=True), so form feeds and Unicode separators
118
+ # already advance its line numbers.
119
+ lines = clean_content.splitlines()
120
+ return "\n".join(lines[: first_trailing_line - 1]).rstrip()
121
+
113
122
  def parse(self, plan_content: str, plan_path: Optional[str] = None) -> Plan:
114
123
  """
115
124
  Parses the specified Markdown plan string into a structured Plan object.
@@ -135,10 +144,15 @@ class MarkdownPlanParser(IPlanParser):
135
144
 
136
145
  self._validate_mutual_exclusivity(doc)
137
146
 
138
- actions = self._parse_section_content(
147
+ actions, trailing_line = self._parse_section_content(
139
148
  stream, clean_content, section_heading, doc
140
149
  )
141
150
 
151
+ if trailing_line is not None:
152
+ clean_content = self._truncate_plan_content(
153
+ clean_content, trailing_line
154
+ )
155
+
142
156
  is_session = self._is_session_plan(plan_path)
143
157
 
144
158
  plan = Plan(
@@ -255,7 +269,7 @@ class MarkdownPlanParser(IPlanParser):
255
269
  clean_content: str,
256
270
  section_heading: Any,
257
271
  doc: Document,
258
- ) -> List[ActionData]:
272
+ ) -> tuple[List[ActionData], Optional[int]]:
259
273
  """Parses the content of either a ## Message or ## Action Plan section."""
260
274
  section_name = get_child_text(section_heading).strip()
261
275
  if "Message" in section_name:
@@ -270,14 +284,18 @@ class MarkdownPlanParser(IPlanParser):
270
284
  stream, node=section_heading, raw_content=raw_content
271
285
  )
272
286
  ]
273
- else:
274
- actions = self._parse_actions(stream, doc)
275
- return actions
287
+ return actions, None
288
+ return self._parse_actions(stream, doc)
276
289
 
277
290
  def _parse_actions(
278
291
  self, stream: _PeekableStream, doc: Document
279
- ) -> List[ActionData]:
280
- from mistletoe.block_token import BlockCode, CodeFence, ThematicBreak
292
+ ) -> tuple[List[ActionData], Optional[int]]:
293
+ from mistletoe.block_token import (
294
+ BlockCode,
295
+ CodeFence,
296
+ Paragraph,
297
+ ThematicBreak,
298
+ )
281
299
 
282
300
  actions: List[ActionData] = []
283
301
  # 'Action Plan' heading is already consumed by _parse_strict_top_level.
@@ -294,6 +312,12 @@ class MarkdownPlanParser(IPlanParser):
294
312
  stream.next()
295
313
  continue
296
314
 
315
+ # A paragraph run that reaches the document end carries no plan
316
+ # instruction. Report where the real plan ends so the caller can
317
+ # persist the stripped content.
318
+ if isinstance(node, Paragraph):
319
+ return actions, self._trailing_run_strip_line(stream, actions, doc)
320
+
297
321
  # Accumulate offending node and raise structural error
298
322
  offending_nodes = consume_content_until_next_action(
299
323
  stream, self._valid_actions
@@ -333,6 +357,27 @@ class MarkdownPlanParser(IPlanParser):
333
357
  parse_method = self._dispatch_map[cleaned_action_type]
334
358
  actions.append(parse_method(stream, node=action_heading))
335
359
 
336
- return actions
360
+ return actions, None
361
+
362
+ def _trailing_run_strip_line(
363
+ self, stream: _PeekableStream, actions: List[ActionData], doc: Document
364
+ ) -> int:
365
+ """Return the first line of a trailing paragraph run, or raise."""
366
+ from mistletoe.block_token import Paragraph
367
+
368
+ trailing_run: List[Any] = [stream.next()]
369
+ while stream.has_next() and isinstance(stream.peek(), Paragraph):
370
+ trailing_run.append(stream.next())
371
+
372
+ first_line = getattr(trailing_run[0], "line_number", None)
373
+ if actions and not stream.has_next() and first_line:
374
+ return first_line
375
+
376
+ raise InvalidPlanError(
377
+ format_structural_mismatch_msg(
378
+ doc, "a Level 3 Action Heading", -1, trailing_run
379
+ ),
380
+ offending_nodes=trailing_run,
381
+ )
337
382
 
338
383
  # Structural formatting logic moved to parser_infrastructure.py
@@ -3,6 +3,8 @@ import re
3
3
  from typing import Any, List, Optional, Iterator, TYPE_CHECKING
4
4
  from urllib.parse import unquote
5
5
 
6
+ from teddy_executor.core.utils.paths import strip_format_characters
7
+
6
8
 
7
9
  # Insert a space after `#` on the first line if missing (e.g., `#Title` -> `# Title`)
8
10
  # Only normalizes the first line to avoid corrupting code fences or shebangs.
@@ -111,15 +113,18 @@ def _looks_like_url(path: str) -> bool:
111
113
 
112
114
 
113
115
  def normalize_path(path: str) -> str:
114
- result = path.replace("\\", "/")
116
+ result = strip_format_characters(path).replace("\\", "/")
115
117
  # Preserve URLs intact — percent-encoded symbols (%20, %23, %3F, etc.)
116
118
  # have structural meaning in URLs and must not be decoded.
117
119
  if _looks_like_url(result):
118
120
  return result
119
- return unquote(result)
121
+ # Percent-encoded invisible characters decode into the same trap, so the
122
+ # scrubbing runs again on the decoded result.
123
+ return strip_format_characters(unquote(result))
120
124
 
121
125
 
122
126
  def normalize_link_target(target: str) -> str:
127
+ target = strip_format_characters(target)
123
128
  if target.startswith(("http://", "https://")):
124
129
  return target
125
130
  is_abs = os.path.isabs(target)
@@ -244,34 +249,36 @@ def translate_setup_commands(
244
249
  return cwd, env
245
250
 
246
251
 
252
+ def _coerce_numeric(value: Any, expected_type: type) -> Any:
253
+ """Coerce a value to int or float, falling back to a leading-number match."""
254
+ try:
255
+ return expected_type(value)
256
+ except (ValueError, TypeError):
257
+ pattern = r"^(\d+)" if expected_type is int else r"^(\d+(?:\.\d+)?)"
258
+ match = re.match(pattern, str(value).strip())
259
+ return expected_type(match.group(1)) if match else None
260
+
261
+
262
+ def _coerce_bool(value: Any) -> bool:
263
+ """Treat the case-insensitive text ``true`` as the only truthy string."""
264
+ if isinstance(value, str):
265
+ return value.strip().lower() == "true"
266
+ return bool(value)
267
+
268
+
247
269
  def coerce_param(value: Any, expected_type: type) -> Any:
248
270
  """
249
271
  Best-effort coercion of a raw parameter value to the expected type.
250
272
  If coercion fails entirely, returns None (caller should remove/ignore param).
251
273
  """
252
- if value is None:
253
- return None
254
- if isinstance(value, expected_type):
274
+ if value is None or isinstance(value, expected_type):
255
275
  return value
256
276
 
257
- if expected_type is int:
258
- try:
259
- return int(value)
260
- except (ValueError, TypeError):
261
- match = re.match(r"^(\d+)", str(value).strip())
262
- return int(match.group(1)) if match else None
263
-
264
- if expected_type is float:
265
- try:
266
- return float(value)
267
- except (ValueError, TypeError):
268
- match = re.match(r"^(\d+(?:\.\d+)?)", str(value).strip())
269
- return float(match.group(1)) if match else None
277
+ if expected_type is int or expected_type is float:
278
+ return _coerce_numeric(value, expected_type)
270
279
 
271
280
  if expected_type is bool:
272
- if isinstance(value, str):
273
- return value.strip().lower() == "true"
274
- return bool(value)
281
+ return _coerce_bool(value)
275
282
 
276
283
  return value
277
284
 
@@ -2,13 +2,15 @@
2
2
 
3
3
  Single-sources the path-normalization pipeline (Markdown-link target
4
4
  extraction plus backslash -> slash conversion, exact ``./`` prefix stripping,
5
- and leading-slash stripping) so every consumer delegates to one implementation
6
- and the behaviour cannot drift across modules. Also hosts ``prefer_markdown``,
7
- the single source of the "a pre-authored ``.md`` prompt wins over a stale
8
- ``.xml`` with the same stem" rule shared by every prompt resolver.
5
+ leading-slash stripping, and format-character scrubbing) so every consumer
6
+ delegates to one implementation and the behaviour cannot drift across modules.
7
+ Also hosts ``prefer_markdown``, the single source of the "a pre-authored
8
+ ``.md`` prompt wins over a stale ``.xml`` with the same stem" rule shared by
9
+ every prompt resolver.
9
10
  """
10
11
 
11
12
  import re
13
+ import unicodedata
12
14
  from pathlib import Path
13
15
  from typing import Iterable, Optional, TypeVar
14
16
 
@@ -16,6 +18,26 @@ _LINK_PATTERN = re.compile(r"\[.*\]\((.*)\)")
16
18
  _MARKDOWN_SUFFIX = ".md"
17
19
  _T = TypeVar("_T", str, Path)
18
20
 
21
+ # The zero-width joiner and non-joiner are format characters, but they carry
22
+ # shaping semantics: they bind emoji sequences and control cursive joining in
23
+ # Arabic and Indic scripts, so a real file name can legitimately contain them.
24
+ _PRESERVED_FORMAT_CHARACTERS = frozenset("\u200c\u200d")
25
+
26
+
27
+ def strip_format_characters(value: str) -> str:
28
+ """Remove format characters that occupy space but render as nothing.
29
+
30
+ Zero-width spaces, byte-order marks, soft hyphens, and bidi controls survive
31
+ every other normalization step. A path that carries one names a different
32
+ file than the one it displays, so the removal happens before any other
33
+ transformation. Shaping joiners stay because they change adjacent glyphs.
34
+ """
35
+ return "".join(
36
+ char
37
+ for char in value
38
+ if char in _PRESERVED_FORMAT_CHARACTERS or unicodedata.category(char) != "Cf"
39
+ )
40
+
19
41
 
20
42
  def normalize_resource_path(resource_str: str) -> str:
21
43
  """Extracts the path from a Markdown link, or normalizes a raw path string.
@@ -24,16 +46,18 @@ def normalize_resource_path(resource_str: str) -> str:
24
46
  other input is treated as a raw path and stripped of surrounding whitespace.
25
47
  Both branches then normalize backslashes to forward slashes, strip an exact
26
48
  leading ``./`` (preserving leading dots such as ``.hidden``), and strip any
27
- leading ``/``.
49
+ leading ``/``. Invisible format characters are removed first, so a path
50
+ never names a different file than the one it displays.
28
51
  """
29
- match = _LINK_PATTERN.search(resource_str)
52
+ scrubbed = strip_format_characters(resource_str)
53
+ match = _LINK_PATTERN.search(scrubbed)
30
54
  if match:
31
55
  normalized = match.group(1).replace("\\", "/")
32
56
  if normalized.startswith("./"):
33
57
  normalized = normalized.removeprefix("./")
34
58
  return normalized.lstrip("/")
35
59
 
36
- normalized = resource_str.strip().replace("\\", "/")
60
+ normalized = scrubbed.strip().replace("\\", "/")
37
61
  if normalized.startswith("./"):
38
62
  normalized = normalized.removeprefix("./")
39
63
  return normalized.lstrip("/")