drydock-cli 1.4.0__tar.gz → 1.5.1__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 (507) hide show
  1. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/PKG-INFO +1 -1
  2. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/PRD.md +32 -1
  3. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/agent_loop.py +136 -17
  4. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/cli.md +22 -0
  5. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/search_replace.py +0 -10
  6. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/pyproject.toml +1 -1
  7. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/deploy_to_github.sh +2 -1
  8. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/publish_to_pypi.sh +2 -1
  9. drydock_cli-1.5.1/scripts/test_bank.sh +78 -0
  10. drydock_cli-1.5.1/tests/test_bank_build.py +572 -0
  11. drydock_cli-1.5.1/tests/test_bank_debug.py +1111 -0
  12. drydock_cli-1.5.1/tests/test_bank_multiagent.py +698 -0
  13. drydock_cli-1.5.1/tests/test_bank_tools.py +472 -0
  14. drydock_cli-1.5.1/tests/test_bank_update.py +938 -0
  15. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_drydock_regression.py +2 -2
  16. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_drydock_tasks.py +36 -12
  17. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_loop_detection.py +65 -35
  18. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_smoke.py +2 -3
  19. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_user_issues.py +16 -11
  20. drydock_cli-1.5.1/tests/test_workloads.py +441 -0
  21. drydock_cli-1.5.1/tests/testbank_helpers.py +967 -0
  22. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/CODEOWNERS +0 -0
  23. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
  24. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  25. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  26. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/workflows/build-and-upload.yml +0 -0
  27. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/workflows/ci.yml +0 -0
  28. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/workflows/issue-labeler.yml +0 -0
  29. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.github/workflows/release.yml +0 -0
  30. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.gitignore +0 -0
  31. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.pre-commit-config.yaml +0 -0
  32. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.python-version +0 -0
  33. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.typos.toml +0 -0
  34. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.vscode/extensions.json +0 -0
  35. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.vscode/launch.json +0 -0
  36. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/.vscode/settings.json +0 -0
  37. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/AGENTS.md +0 -0
  38. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/CHANGELOG.md +0 -0
  39. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/CLAUDE.md +0 -0
  40. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/CONTRIBUTING.md +0 -0
  41. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/Drydock_rebrand.md +0 -0
  42. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/LICENSE +0 -0
  43. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/NOTICE +0 -0
  44. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/README.md +0 -0
  45. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/action.yml +0 -0
  46. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/distribution/zed/LICENSE +0 -0
  47. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/distribution/zed/extension.toml +0 -0
  48. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/distribution/zed/icons/mistral_vibe.svg +0 -0
  49. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/docs/README.md +0 -0
  50. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/docs/acp-setup.md +0 -0
  51. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/docs/proxy-setup.md +0 -0
  52. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/__init__.py +0 -0
  53. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/__init__.py +0 -0
  54. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/acp_agent_loop.py +0 -0
  55. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/acp_logger.py +0 -0
  56. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/entrypoint.py +0 -0
  57. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/__init__.py +0 -0
  58. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/base.py +0 -0
  59. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/builtins/bash.py +0 -0
  60. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/builtins/read_file.py +0 -0
  61. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/builtins/search_replace.py +0 -0
  62. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/builtins/todo.py +0 -0
  63. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/builtins/write_file.py +0 -0
  64. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/tools/session_update.py +0 -0
  65. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/acp/utils.py +0 -0
  66. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/__init__.py +0 -0
  67. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/autocompletion/__init__.py +0 -0
  68. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/autocompletion/base.py +0 -0
  69. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/autocompletion/path_completion.py +0 -0
  70. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/autocompletion/slash_command.py +0 -0
  71. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/cli.py +0 -0
  72. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/clipboard.py +0 -0
  73. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/commands.py +0 -0
  74. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/entrypoint.py +0 -0
  75. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/history_manager.py +0 -0
  76. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
  77. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
  78. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
  79. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/terminal_setup.py +0 -0
  80. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/__init__.py +0 -0
  81. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
  82. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/app.py +0 -0
  83. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/app.tcss +0 -0
  84. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/external_editor.py +0 -0
  85. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
  86. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
  87. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
  88. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
  89. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
  90. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
  91. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
  92. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
  93. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
  94. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
  95. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
  96. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
  97. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
  98. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
  99. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
  100. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
  101. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
  102. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
  103. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/compact.py +0 -0
  104. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
  105. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
  106. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
  107. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/loading.py +0 -0
  108. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/messages.py +0 -0
  109. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
  110. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
  111. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
  112. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
  113. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
  114. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
  115. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
  116. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
  117. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
  118. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/tools.py +0 -0
  119. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
  120. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
  121. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/windowing/history.py +0 -0
  122. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
  123. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/textual_ui/windowing/state.py +0 -0
  124. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/__init__.py +0 -0
  125. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
  126. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
  127. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
  128. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
  129. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
  130. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/update.py +0 -0
  131. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/cli/update_notifier/whats_new.py +0 -0
  132. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/__init__.py +0 -0
  133. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/agents/__init__.py +0 -0
  134. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/agents/manager.py +0 -0
  135. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/agents/models.py +0 -0
  136. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/auth/__init__.py +0 -0
  137. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/auth/crypto.py +0 -0
  138. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/auth/github.py +0 -0
  139. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/__init__.py +0 -0
  140. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/completers.py +0 -0
  141. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
  142. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
  143. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
  144. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/file_indexer/store.py +0 -0
  145. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
  146. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/fuzzy.py +0 -0
  147. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/path_prompt.py +0 -0
  148. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
  149. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/config/__init__.py +0 -0
  150. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/config/_settings.py +0 -0
  151. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/config/harness_files/__init__.py +0 -0
  152. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/config/harness_files/_harness_manager.py +0 -0
  153. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/config/harness_files/_paths.py +0 -0
  154. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/consultant.py +0 -0
  155. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/drydock_states.py +0 -0
  156. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/hooks.py +0 -0
  157. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/__init__.py +0 -0
  158. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/backend/anthropic.py +0 -0
  159. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/backend/base.py +0 -0
  160. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/backend/factory.py +0 -0
  161. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/backend/generic.py +0 -0
  162. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/backend/mistral.py +0 -0
  163. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
  164. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/backend/vertex.py +0 -0
  165. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/exceptions.py +0 -0
  166. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/format.py +0 -0
  167. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/message_utils.py +0 -0
  168. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/llm/types.py +0 -0
  169. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/logger.py +0 -0
  170. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/middleware.py +0 -0
  171. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/output_formatters.py +0 -0
  172. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/paths/__init__.py +0 -0
  173. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/paths/_local_config_walk.py +0 -0
  174. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/paths/_vibe_home.py +0 -0
  175. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/paths/conventions.py +0 -0
  176. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/plan_session.py +0 -0
  177. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/plugins.py +0 -0
  178. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/programmatic.py +0 -0
  179. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/__init__.py +0 -0
  180. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/compact.md +0 -0
  181. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/dangerous_directory.md +0 -0
  182. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/diagnostic.md +0 -0
  183. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/explore.md +0 -0
  184. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/planner.md +0 -0
  185. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/project_context.md +0 -0
  186. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/prompts/tests.md +0 -0
  187. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/proxy_setup.py +0 -0
  188. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/session/agent_memory.py +0 -0
  189. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/session/checkpoints.py +0 -0
  190. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/session/session_loader.py +0 -0
  191. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/session/session_logger.py +0 -0
  192. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/session/session_migration.py +0 -0
  193. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/session/state_file.py +0 -0
  194. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/skills/__init__.py +0 -0
  195. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/skills/manager.py +0 -0
  196. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/skills/models.py +0 -0
  197. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/skills/parser.py +0 -0
  198. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/slug.py +0 -0
  199. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/system_prompt.py +0 -0
  200. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/telemetry/__init__.py +0 -0
  201. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/telemetry/send.py +0 -0
  202. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/teleport/errors.py +0 -0
  203. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/teleport/git.py +0 -0
  204. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/teleport/nuage.py +0 -0
  205. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/teleport/teleport.py +0 -0
  206. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/teleport/types.py +0 -0
  207. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/base.py +0 -0
  208. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/ask_user_question.py +0 -0
  209. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/bash.py +0 -0
  210. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/cron.py +0 -0
  211. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
  212. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/glob_tool.py +0 -0
  213. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/grep.py +0 -0
  214. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/invoke_skill.py +0 -0
  215. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/lsp.py +0 -0
  216. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/mcp_resources.py +0 -0
  217. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/notebook_edit.py +0 -0
  218. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/powershell.py +0 -0
  219. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
  220. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
  221. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/bash.md +0 -0
  222. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/cron.md +0 -0
  223. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/glob.md +0 -0
  224. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/grep.md +0 -0
  225. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/invoke_skill.md +0 -0
  226. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/lsp.md +0 -0
  227. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/mcp_resources.md +0 -0
  228. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
  229. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/powershell.md +0 -0
  230. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
  231. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
  232. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
  233. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/task.md +0 -0
  234. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
  235. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/todo.md +0 -0
  236. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/tool_search.md +0 -0
  237. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
  238. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
  239. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/worktree.md +0 -0
  240. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
  241. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/read_file.py +0 -0
  242. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/task.py +0 -0
  243. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/task_manager.py +0 -0
  244. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/todo.py +0 -0
  245. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/tool_search.py +0 -0
  246. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/webfetch.py +0 -0
  247. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/websearch.py +0 -0
  248. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/worktree.py +0 -0
  249. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/builtins/write_file.py +0 -0
  250. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/injection_guard.py +0 -0
  251. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/manager.py +0 -0
  252. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/mcp/__init__.py +0 -0
  253. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/mcp/registry.py +0 -0
  254. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/mcp/tools.py +0 -0
  255. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/mcp_sampling.py +0 -0
  256. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/ui.py +0 -0
  257. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/tools/utils.py +0 -0
  258. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/trusted_folders.py +0 -0
  259. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/types.py +0 -0
  260. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/core/utils.py +0 -0
  261. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/onboarding/__init__.py +0 -0
  262. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/onboarding/base.py +0 -0
  263. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/onboarding/onboarding.tcss +0 -0
  264. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/onboarding/screens/__init__.py +0 -0
  265. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/onboarding/screens/api_key.py +0 -0
  266. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/onboarding/screens/welcome.py +0 -0
  267. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
  268. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
  269. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/__init__.py +0 -0
  270. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/batch/SKILL.md +0 -0
  271. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/create-presentation/SKILL.md +0 -0
  272. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/deep-research/SKILL.md +0 -0
  273. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/investigate/SKILL.md +0 -0
  274. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/review/SKILL.md +0 -0
  275. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/ship/SKILL.md +0 -0
  276. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/skills/simplify/SKILL.md +0 -0
  277. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock/whats_new.md +0 -0
  278. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock-acp.spec +0 -0
  279. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/drydock_terms.md +0 -0
  280. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/flake.lock +0 -0
  281. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/flake.nix +0 -0
  282. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/README.md +0 -0
  283. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/backup.sh +0 -0
  284. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/bump_version.py +0 -0
  285. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/install.sh +0 -0
  286. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/prepare_release.py +0 -0
  287. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/test_full.sh +0 -0
  288. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/scripts/test_smoke.sh +0 -0
  289. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/__init__.py +0 -0
  290. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/conftest.py +0 -0
  291. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_acp.py +0 -0
  292. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_agent_thought.py +0 -0
  293. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_bash.py +0 -0
  294. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_compact_session_updates.py +0 -0
  295. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_content.py +0 -0
  296. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_initialize.py +0 -0
  297. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_list_sessions.py +0 -0
  298. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_load_session.py +0 -0
  299. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_multi_session.py +0 -0
  300. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_new_session.py +0 -0
  301. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_proxy_setup_acp.py +0 -0
  302. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_read_file.py +0 -0
  303. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_search_replace.py +0 -0
  304. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_set_config_option.py +0 -0
  305. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_set_mode.py +0 -0
  306. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_set_model.py +0 -0
  307. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_tool_call_session_update.py +0 -0
  308. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_utils.py +0 -0
  309. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/acp/test_write_file.py +0 -0
  310. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_file_indexer.py +0 -0
  311. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_fuzzy.py +0 -0
  312. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
  313. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_path_completer_recursive.py +0 -0
  314. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_path_completion_controller.py +0 -0
  315. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
  316. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_slash_command_controller.py +0 -0
  317. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
  318. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/__init__.py +0 -0
  319. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/data/__init__.py +0 -0
  320. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/data/fireworks.py +0 -0
  321. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/data/mistral.py +0 -0
  322. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/test_anthropic_adapter.py +0 -0
  323. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/test_backend.py +0 -0
  324. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/test_reasoning_adapter.py +0 -0
  325. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
  326. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
  327. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
  328. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
  329. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_bell_notifications.py +0 -0
  330. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_braille_renderer.py +0 -0
  331. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_clipboard.py +0 -0
  332. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_commands.py +0 -0
  333. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_copy_shortcuts.py +0 -0
  334. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_external_editor.py +0 -0
  335. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_no_markup_static.py +0 -0
  336. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_question_app.py +0 -0
  337. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_spinner.py +0 -0
  338. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_switching_mode.py +0 -0
  339. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_ui_clipboard_notifications.py +0 -0
  340. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
  341. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_ui_session_resume.py +0 -0
  342. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/test_ui_skill_dispatch.py +0 -0
  343. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/textual_ui/__init__.py +0 -0
  344. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/cli/textual_ui/test_session_picker.py +0 -0
  345. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/conftest.py +0 -0
  346. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_agents.py +0 -0
  347. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_auth_crypto.py +0 -0
  348. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_auth_github.py +0 -0
  349. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_config_load_dotenv.py +0 -0
  350. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_config_paths.py +0 -0
  351. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_config_resolution.py +0 -0
  352. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_file_logging.py +0 -0
  353. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_plan_session.py +0 -0
  354. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_proxy_setup.py +0 -0
  355. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_slug.py +0 -0
  356. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_telemetry_send.py +0 -0
  357. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_teleport_git.py +0 -0
  358. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_teleport_nuage.py +0 -0
  359. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_teleport_service.py +0 -0
  360. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_trusted_folders.py +0 -0
  361. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/core/test_utils.py +0 -0
  362. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/e2e/common.py +0 -0
  363. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/e2e/conftest.py +0 -0
  364. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/e2e/mock_server.py +0 -0
  365. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/e2e/test_cli_tui_onboarding.py +0 -0
  366. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/e2e/test_cli_tui_streaming.py +0 -0
  367. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
  368. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/mock/__init__.py +0 -0
  369. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/mock/mock_backend_factory.py +0 -0
  370. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/mock/mock_entrypoint.py +0 -0
  371. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/mock/utils.py +0 -0
  372. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/onboarding/test_run_onboarding.py +0 -0
  373. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/onboarding/test_ui_onboarding.py +0 -0
  374. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/session/test_session_loader.py +0 -0
  375. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/session/test_session_logger.py +0 -0
  376. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/session/test_session_migration.py +0 -0
  377. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/skills/conftest.py +0 -0
  378. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/skills/test_manager.py +0 -0
  379. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/skills/test_models.py +0 -0
  380. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/skills/test_parser.py +0 -0
  381. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
  382. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
  383. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
  384. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
  385. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
  386. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
  387. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
  388. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
  389. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
  390. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
  391. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
  392. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
  393. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
  394. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
  395. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
  396. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
  397. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
  398. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
  399. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
  400. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
  401. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
  402. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
  403. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
  404. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
  405. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
  406. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
  407. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
  408. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
  409. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
  410. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
  411. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
  412. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
  413. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
  414. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
  415. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
  416. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
  417. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
  418. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
  419. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
  420. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
  421. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
  422. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
  423. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
  424. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
  425. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
  426. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
  427. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
  428. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
  429. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
  430. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
  431. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
  432. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
  433. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
  434. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
  435. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
  436. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
  437. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
  438. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
  439. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
  440. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
  441. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/base_snapshot_test_app.py +0 -0
  442. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/conftest.py +0 -0
  443. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/snap_compare.py +0 -0
  444. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
  445. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
  446. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
  447. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
  448. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
  449. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
  450. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
  451. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
  452. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
  453. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
  454. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
  455. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
  456. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
  457. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
  458. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/stubs/fake_backend.py +0 -0
  459. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/stubs/fake_client.py +0 -0
  460. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/stubs/fake_tool.py +0 -0
  461. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_agent_auto_compact.py +0 -0
  462. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_agent_backend.py +0 -0
  463. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_agent_observer_streaming.py +0 -0
  464. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_agent_stats.py +0 -0
  465. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_agent_tasks.py +0 -0
  466. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_agent_tool_call.py +0 -0
  467. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_agents.py +0 -0
  468. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_build_projects.py +0 -0
  469. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_cli_programmatic_preload.py +0 -0
  470. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_current_bugs.py +0 -0
  471. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_full_regression.py +0 -0
  472. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_history_manager.py +0 -0
  473. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_integration.py +0 -0
  474. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_message_id.py +0 -0
  475. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_message_merging.py +0 -0
  476. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_middleware.py +0 -0
  477. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_multi_agent.py +0 -0
  478. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_real_failures.py +0 -0
  479. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_real_issues.py +0 -0
  480. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_real_workflow.py +0 -0
  481. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_reasoning_content.py +0 -0
  482. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_system_prompt.py +0 -0
  483. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_tagged_text.py +0 -0
  484. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_ui_external_editor.py +0 -0
  485. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/test_ui_input_history.py +0 -0
  486. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_ask_user_question.py +0 -0
  487. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_bash.py +0 -0
  488. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_exit_plan_mode.py +0 -0
  489. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_grep.py +0 -0
  490. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_invoke_context.py +0 -0
  491. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_manager_get_tool_config.py +0 -0
  492. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_mcp.py +0 -0
  493. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_mcp_sampling.py +0 -0
  494. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_task.py +0 -0
  495. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_ui_bash_execution.py +0 -0
  496. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_webfetch.py +0 -0
  497. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/tools/test_websearch.py +0 -0
  498. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
  499. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
  500. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/test_do_update.py +0 -0
  501. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
  502. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/test_github_update_gateway.py +0 -0
  503. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
  504. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/test_ui_update_notification.py +0 -0
  505. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/test_update_use_case.py +0 -0
  506. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/tests/update_notifier/test_whats_new.py +0 -0
  507. {drydock_cli-1.4.0 → drydock_cli-1.5.1}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 1.4.0
3
+ Version: 1.5.1
4
4
  Summary: Drydock — nautical CLI coding agent
5
5
  Project-URL: Homepage, https://github.com/fbobe321/drydock
6
6
  Project-URL: Repository, https://github.com/fbobe321/drydock
@@ -1,7 +1,7 @@
1
1
  # DryDock — Local CLI Coding Agent
2
2
 
3
3
  **Repository:** https://github.com/fbobe321/drydock
4
- **PyPI:** https://pypi.org/project/drydock-cli/ (v1.1.5)
4
+ **PyPI:** https://pypi.org/project/drydock-cli/ (v1.5.0)
5
5
  **License:** Apache 2.0 (fork of [mistralai/mistral-vibe](https://github.com/mistralai/mistral-vibe))
6
6
  **Status:** Active development — continuous improvement running
7
7
 
@@ -21,6 +21,7 @@ Every change follows this pipeline:
21
21
  Scripts:
22
22
  - `scripts/test_smoke.sh` — quick smoke tests (every deploy)
23
23
  - `scripts/test_full.sh` — smoke + full regression (nightly)
24
+ - `scripts/test_bank.sh` — 83-test regression bank (10-18 hours, real vLLM)
24
25
  - `scripts/deploy_to_github.sh` — smoke tests → sync to GitHub (daily 4 AM)
25
26
  - `scripts/publish_to_pypi.sh` — smoke tests → bump → build → PyPI → GitHub
26
27
  - `scripts/backup.sh` — rsync to NAS (daily 3 AM)
@@ -248,3 +249,33 @@ Adding Python tools/agents doesn't matter if the prompt doesn't tell the model t
248
249
  - Shows exact syntax for delegation
249
250
  - Explicit WHEN to delegate rules (3+ files, reviews, bugs, planning)
250
251
  - WHEN NOT to delegate (simple fixes, quick questions)
252
+
253
+ ### Phase 11 (Mar 28): Agent Loop Hardening + 83-Test Regression Bank
254
+
255
+ User reported DryDock was unusable — model looped 12+ times running the same command, search_replace blocked legitimate files, basic tasks couldn't complete.
256
+
257
+ **Agent loop fixes (5 bugs):**
258
+ - Empty model response: retry 3x with nudge (model sometimes returns nothing)
259
+ - Invalid tool name recovery: model hallucinates `task_agent:`, now gets correct tool list
260
+ - Bash traceback guidance: extracts file:line from crash, directs model to read source
261
+ - Circuit breaker for successful repeats: blocks after 4 identical bash calls (was unlimited)
262
+ - Tighter loop detection: warning at 4 (was 8), force-stop at 8 (was 25)
263
+
264
+ **System prompt improvements:**
265
+ - Added debugging best practices: RUN → READ → FIX → VERIFY cycle
266
+ - Common bug pattern hints (TypeError, KeyError, IndexError, off-by-one)
267
+
268
+ **83-test regression bank (real vLLM backend, ~90 min):**
269
+
270
+ | Suite | Tests | Pass Rate |
271
+ |---|---|---|
272
+ | BUILD (easy/medium/hard) | 25 | 100% |
273
+ | DEBUG (easy/medium/hard) | 20 | 75% |
274
+ | UPDATE (easy/medium/hard) | 15 | 100% |
275
+ | MULTIAGENT | 10 | 100% |
276
+ | TOOLS | 13 | 100% |
277
+ | **Total** | **83** | **94%** |
278
+
279
+ Run with: `./scripts/test_bank.sh` (full) or `./scripts/test_bank.sh quick` (easy only, ~2h)
280
+
281
+ **Removed:** False-positive test file guard in search_replace that blocked any file in a directory containing "test" in its name.
@@ -124,8 +124,8 @@ class ToolDecision(BaseModel):
124
124
 
125
125
  MAX_TOOL_TURNS = 200 # Bug fixes rarely need more than 50 turns; 200 is generous ceiling
126
126
  MAX_API_ERRORS = 5
127
- REPEAT_WARNING_THRESHOLD = 8 # Same exact call 8+ times before warning
128
- REPEAT_FORCE_STOP_THRESHOLD = 25 # Same exact call 25+ times before force-stop
127
+ REPEAT_WARNING_THRESHOLD = 4 # Same exact call 4+ times before warning
128
+ REPEAT_FORCE_STOP_THRESHOLD = 8 # Same exact call 8+ times before force-stop
129
129
 
130
130
  logger = logging.getLogger(__name__)
131
131
 
@@ -192,6 +192,7 @@ class AgentLoop:
192
192
  # Key: hash(tool_name + args), Value: (count, last_result_snippet)
193
193
  self._tool_call_history: dict[str, tuple[int, str]] = {}
194
194
  self._consecutive_circuit_breaker_fires: int = 0
195
+ self._empty_responses: int = 0
195
196
 
196
197
  system_prompt = get_universal_system_prompt(
197
198
  self.tool_manager, self.config, self.skill_manager, self.agent_manager
@@ -534,9 +535,19 @@ class AgentLoop:
534
535
  stopped_by_middleware=True,
535
536
  )
536
537
  return
537
- # Inject error notice ALWAYS append to last tool result
538
- # vLLM/Mistral rejects user messages after tool messages
539
- error_text = f"API error occurred: {e}. Please continue with your task."
538
+ # Check if the error is about invalid function/tool name
539
+ error_str = str(e)
540
+ if "Function name" in error_str or "function" in error_str.lower() and "must be" in error_str.lower():
541
+ # Model hallucinated a tool name — give it the correct list
542
+ available = ", ".join(sorted(self.tool_manager.available_tools.keys())[:15])
543
+ error_text = (
544
+ f"ERROR: You tried to call a tool that does not exist. "
545
+ f"Available tools: {available}. "
546
+ f"Use one of these exact tool names. "
547
+ f"For subagent delegation, use 'task'. For file search, use 'grep'."
548
+ )
549
+ else:
550
+ error_text = f"API error occurred: {e}. Please continue with your task."
540
551
  self._inject_system_note(error_text)
541
552
  continue
542
553
 
@@ -616,6 +627,41 @@ class AgentLoop:
616
627
  f"Consider stopping to verify your approach."
617
628
  )
618
629
 
630
+ # Post-edit bash loop: model made edits but now loops on bash
631
+ # trying to test code that keeps failing
632
+ if has_made_edit and bash_count >= 3:
633
+ # Count consecutive bash calls at end of tool history
634
+ consecutive_bash = 0
635
+ for tc_name in reversed(self._recent_tool_names()):
636
+ if tc_name in ("bash", "run_command"):
637
+ consecutive_bash += 1
638
+ else:
639
+ break
640
+ if consecutive_bash >= 4:
641
+ self._inject_system_note(
642
+ "You have run 4+ bash commands in a row after editing files. "
643
+ "Each one failed or gave the same result. STOP running bash. "
644
+ "Read the error message carefully, then use search_replace "
645
+ "to fix the actual code. Running the same command again will "
646
+ "not give a different result."
647
+ )
648
+
649
+ # Detect bash file creation (touch, echo >, cat <<)
650
+ for msg in reversed(self.messages[-3:]):
651
+ if msg.role == Role.assistant and msg.tool_calls:
652
+ for tc in msg.tool_calls:
653
+ if tc.function and tc.function.name in ("bash", "run_command"):
654
+ cmd = ""
655
+ try:
656
+ cmd = json.loads(tc.function.arguments or "{}").get("command", "")
657
+ except (json.JSONDecodeError, AttributeError):
658
+ pass
659
+ if any(kw in cmd for kw in ("touch ", "echo ", "cat <<", "printf ", "> ")):
660
+ self._inject_system_note(
661
+ f"Do NOT use bash to create files. Use write_file instead. "
662
+ f"bash touch/echo/cat does not create proper code files."
663
+ )
664
+
619
665
  # Bash abuse detection: model uses bash instead of proper tools
620
666
  if not has_made_edit and bash_count >= 3:
621
667
  if bash_count == 3:
@@ -670,10 +716,26 @@ class AgentLoop:
670
716
 
671
717
  should_break_loop = last_message.role != Role.tool
672
718
 
719
+ # Handle empty response (no content AND no tools) — retry
720
+ if (should_break_loop and last_message.role == Role.assistant
721
+ and not last_message.content and not last_message.tool_calls):
722
+ empty_response_count = getattr(self, '_empty_responses', 0) + 1
723
+ self._empty_responses = empty_response_count
724
+ if empty_response_count <= 3:
725
+ should_break_loop = False
726
+ self._inject_system_note(
727
+ "Your response was empty. You MUST call a tool. "
728
+ "Start by reading the relevant file with read_file, "
729
+ "or run the failing command with bash to see the error."
730
+ )
731
+ logger.warning("Empty model response — nudging (attempt %d)", empty_response_count)
732
+ continue
733
+ # After 3 empty responses, let it exit
734
+
673
735
  # If model gives text without tool calls and hasn't edited anything,
674
736
  # nudge it to make an edit instead of just describing what to do.
675
737
  # Never let the agent exit without at least attempting an edit.
676
- if should_break_loop and not has_made_edit and tool_turns >= 2:
738
+ if should_break_loop and not has_made_edit and tool_turns >= 1:
677
739
  text_without_action += 1
678
740
  # Always continue — don't let the agent exit without editing
679
741
  should_break_loop = False
@@ -742,8 +804,8 @@ class AgentLoop:
742
804
  if rep == "FORCE_STOP":
743
805
  repeat_warnings += 1
744
806
  logger.warning("Detected infinite loop: same tool call %d+ times (warning %d)", REPEAT_FORCE_STOP_THRESHOLD, repeat_warnings)
745
- if repeat_warnings >= 12:
746
- # True last resortonly stop after many redirects
807
+ if repeat_warnings >= 5:
808
+ # Stop after 5 redirects model is not recovering
747
809
  yield AssistantEvent(
748
810
  content="\n\n[Stopping: exhausted all retry attempts.]\n",
749
811
  stopped_by_middleware=True,
@@ -773,7 +835,7 @@ class AgentLoop:
773
835
  else:
774
836
  repeat_warnings += 1
775
837
  logger.warning("Detected repeated tool calls (warning %.1f, investigation=%s)", repeat_warnings, is_investigation_warning)
776
- if repeat_warnings >= 15:
838
+ if repeat_warnings >= 6:
777
839
  yield AssistantEvent(
778
840
  content="\n\n[Stopping: too many repeated actions despite warnings.]\n",
779
841
  stopped_by_middleware=True,
@@ -792,7 +854,13 @@ class AgentLoop:
792
854
  elif stuck_tool in ("grep",):
793
855
  nudge = " You have been SEARCHING repeatedly. Pick the most relevant file from your search results and READ it, then make your edit."
794
856
  elif stuck_tool in ("bash", "run_command"):
795
- nudge = " You have been running bash commands repeatedly without making progress. STOP testing and make your code edit with search_replace now. If your fix doesn't work, try a DIFFERENT approach."
857
+ nudge = (
858
+ " You have been running the SAME bash command repeatedly. "
859
+ "Running the same command again will give the same result. "
860
+ "If it succeeded but didn't do what you expected, READ the source code "
861
+ "to understand WHY, then FIX the code with search_replace. "
862
+ "If it failed, try a DIFFERENT command or approach."
863
+ )
796
864
  if repeat_warnings >= 4:
797
865
  # Escalated: replace tool result with strong directive
798
866
  warning_text = (
@@ -935,10 +1003,19 @@ class AgentLoop:
935
1003
  count, last_result = self._tool_call_history.get(sig, (0, ""))
936
1004
  is_failed = last_result.startswith("FAILED:") if last_result else False
937
1005
 
938
- # ONLY block commands that FAILED — successful commands are allowed to repeat.
939
- # The model legitimately runs ls, git status, etc. multiple times during work.
940
- # Loop detection (_check_tool_call_repetition) handles pattern-based loops.
941
- if not (is_failed and count >= 2):
1006
+ # Block failed commands after 2 repeats.
1007
+ # Block SUCCESSFUL commands after 4 repeats the model should not
1008
+ # run the exact same command with the exact same args 5+ times.
1009
+ # Read-only checks (ls, pwd, git status) get a higher threshold.
1010
+ tool_name = tool_call.tool_name
1011
+ is_readonly = tool_name in ("grep", "read_file", "glob", "ls")
1012
+ success_threshold = 6 if is_readonly else 4
1013
+
1014
+ if is_failed and count >= 2:
1015
+ pass # will be blocked below
1016
+ elif not is_failed and count >= success_threshold:
1017
+ pass # will be blocked below
1018
+ else:
942
1019
  return None
943
1020
 
944
1021
  if count >= 2:
@@ -1161,6 +1238,35 @@ class AgentLoop:
1161
1238
  "Add more surrounding context lines to old_str to make it unique.]"
1162
1239
  )
1163
1240
 
1241
+ # RECOVERY: Relative import error — tell model to use absolute imports or -m
1242
+ if tool_call.tool_name in ("bash", "run_command") and "relative import with no known parent" in str(exc):
1243
+ self._inject_system_note(
1244
+ "The error 'relative import with no known parent package' means you are "
1245
+ "running a package file directly (python3 pkg/file.py). Fix: either "
1246
+ "(1) change 'from .module import X' to 'from pkg.module import X' (absolute imports), or "
1247
+ "(2) run with 'python3 -m pkg' instead of 'python3 pkg/file.py'. "
1248
+ "Use search_replace to change the imports to absolute imports NOW."
1249
+ )
1250
+
1251
+ # RECOVERY: After bash failure with traceback, extract file/line and
1252
+ # inject a STRONG system note (not just error text) to force read→fix
1253
+ if tool_call.tool_name in ("bash", "run_command") and "Traceback" in str(exc):
1254
+ import re
1255
+ tb_matches = re.findall(r'File "([^"]+)", line (\d+)', str(exc))
1256
+ if tb_matches:
1257
+ tb_file, tb_line = tb_matches[-1]
1258
+ if not tb_file.startswith("/home") and "site-packages" not in tb_file:
1259
+ error_msg += (
1260
+ f"\n\n[NEXT STEP: Read {tb_file} around line {tb_line} "
1261
+ f"with read_file, then fix it with search_replace.]"
1262
+ )
1263
+ # Also inject as system note — harder for model to ignore
1264
+ self._inject_system_note(
1265
+ f"STOP running bash. The error is at {tb_file}:{tb_line}. "
1266
+ f"Use read_file to read that file, then search_replace to fix the bug. "
1267
+ f"Do NOT run another bash command until you have fixed the code."
1268
+ )
1269
+
1164
1270
  yield ToolResultEvent(
1165
1271
  tool_name=tool_call.tool_name,
1166
1272
  tool_class=tool_call.tool_class,
@@ -1485,11 +1591,11 @@ class AgentLoop:
1485
1591
  # Lower thresholds catch loops where the model uses the same tool
1486
1592
  # with slightly different args (e.g., grep with different paths).
1487
1593
  if last_tool in ("bash", "run_command"):
1488
- same_tool_limit = 8
1594
+ same_tool_limit = 5
1489
1595
  elif last_tool in ("grep", "read_file"):
1490
- same_tool_limit = 10 # investigation tools need some room
1596
+ same_tool_limit = 7 # investigation tools need some room
1491
1597
  else:
1492
- same_tool_limit = 6
1598
+ same_tool_limit = 5
1493
1599
  if (
1494
1600
  len(tool_names) >= same_tool_limit
1495
1601
  and all(n == tool_names[-1] for n in tool_names[-same_tool_limit:])
@@ -1529,6 +1635,19 @@ class AgentLoop:
1529
1635
 
1530
1636
  return None
1531
1637
 
1638
+ def _recent_tool_names(self, limit: int = 10) -> list[str]:
1639
+ """Return recent tool names from message history (most recent last)."""
1640
+ names: list[str] = []
1641
+ for msg in reversed(self.messages):
1642
+ if msg.role == Role.assistant and msg.tool_calls:
1643
+ for tc in msg.tool_calls:
1644
+ if tc.function and tc.function.name:
1645
+ names.append(tc.function.name)
1646
+ if len(names) >= limit:
1647
+ break
1648
+ names.reverse()
1649
+ return names
1650
+
1532
1651
  def _prune_repeated_tool_calls(self) -> None:
1533
1652
  """Remove duplicate tool call/result pairs from recent history.
1534
1653
 
@@ -223,6 +223,28 @@ Error Handling:
223
223
  - After ANY error, your next action must be DIFFERENT from what just failed.
224
224
  - Never run the same failing command twice — the result won't change.
225
225
 
226
+ Python Package Rules:
227
+ When creating Python packages (directories with __init__.py):
228
+ - Use ABSOLUTE imports, not relative. Write `from mypackage.module import X`, NOT `from .module import X`
229
+ - To run a package: `python3 -m mypackage` (requires __main__.py), NOT `python3 mypackage/main.py`
230
+ - Relative imports (from .foo) ONLY work with `python3 -m`, not direct file execution
231
+ - If you get "attempted relative import with no known parent package", switch to absolute imports
232
+
233
+ Debugging Best Practices:
234
+ When fixing bugs, follow this cycle: RUN → READ → FIX → VERIFY.
235
+ 1. RUN the failing command to see the exact error (traceback, assertion, etc.)
236
+ 2. READ the source file at the line mentioned in the traceback
237
+ 3. FIX the bug with search_replace — common patterns:
238
+ - TypeError (str + int): add type conversion (int(), float(), str())
239
+ - KeyError: add .get() with default, or check key existence
240
+ - IndexError: fix loop bounds or add bounds check
241
+ - ImportError: fix the import path, use absolute imports, or run with python3 -m
242
+ - Off-by-one: check if index starts at 0 or 1
243
+ - Missing return value: check if function returns in all paths
244
+ 4. VERIFY by running the command again — if it still fails, read the NEW error
245
+
246
+ CRITICAL: After fixing a bug, ALWAYS run the command again to verify. Never assume your fix worked.
247
+
226
248
  Context Budget:
227
249
  Your context window is your most important resource. Every grep result and file read consumes it.
228
250
  Performance degrades as context fills. Budget your investigation:
@@ -119,16 +119,6 @@ class SearchReplace(
119
119
  ) -> AsyncGenerator[ToolStreamEvent | SearchReplaceResult, None]:
120
120
  file_path, search_replace_blocks = self._prepare_and_validate_args(args)
121
121
 
122
- # BLOCK editing test files — the bug is in source code, not tests
123
- file_str = str(file_path)
124
- if ("/tests/" in file_str or "/test_" in file_str or
125
- file_str.endswith("_test.py") or "/testing/" in file_str):
126
- raise ToolError(
127
- f"BLOCKED: You are trying to edit a test file ({file_path.name}). "
128
- f"The bug is in LIBRARY SOURCE code, not tests. "
129
- f"Use grep to find the corresponding source file and edit that instead."
130
- )
131
-
132
122
  # Injection guard: scan replacement content for suspicious patterns
133
123
  from drydock.core.tools.injection_guard import check_content_for_injection
134
124
  if warning := check_content_for_injection(args.content, args.file_path):
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "drydock-cli"
3
- version = "1.4.0"
3
+ version = "1.5.1"
4
4
  description = "Drydock — nautical CLI coding agent"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -37,7 +37,8 @@ AUTH_URL="https://${GITHUB_TOKEN}@github.com/fbobe321/drydock.git"
37
37
 
38
38
  log "Running regression tests..."
39
39
  cd "$DRYDOCK_SRC"
40
- if ! python3 -m pip install -q "pytest>=9.0" 2>/dev/null; python3 -m pytest tests/test_drydock_regression.py tests/test_drydock_tasks.py tests/test_loop_detection.py tests/test_agent_tasks.py tests/test_integration.py tests/test_user_issues.py tests/test_real_issues.py \
40
+ python3 -m pip install -q "pytest>=9.0" 2>/dev/null
41
+ if ! python3 -m pytest tests/test_drydock_regression.py tests/test_drydock_tasks.py tests/test_loop_detection.py tests/test_agent_tasks.py tests/test_integration.py tests/test_user_issues.py tests/test_real_issues.py \
41
42
  -p no:xdist -p no:cov --override-ini="addopts=" -q 2>&1; then
42
43
  log "TESTS FAILED — deploy aborted. Fix the tests before deploying."
43
44
  exit 1
@@ -25,7 +25,8 @@ PYPI_TOKEN=$(cat "$TOKEN_FILE")
25
25
 
26
26
  # --- Run tests ---
27
27
  log "Running regression tests..."
28
- if ! $PYTHON -m pip install -q "pytest>=9.0" 2>/dev/null; $PYTHON -m pytest tests/test_drydock_regression.py tests/test_drydock_tasks.py tests/test_loop_detection.py tests/test_agent_tasks.py tests/test_integration.py tests/test_user_issues.py tests/test_real_issues.py \
28
+ $PYTHON -m pip install -q "pytest>=9.0" 2>/dev/null
29
+ if ! $PYTHON -m pytest tests/test_drydock_regression.py tests/test_drydock_tasks.py tests/test_loop_detection.py tests/test_agent_tasks.py tests/test_integration.py tests/test_user_issues.py tests/test_real_issues.py \
29
30
  -p no:xdist -p no:cov --override-ini="addopts=" -q 2>&1; then
30
31
  log "TESTS FAILED — publish aborted."
31
32
  exit 1
@@ -0,0 +1,78 @@
1
+ #!/bin/bash
2
+ # TEST BANK — Full regression suite against real vLLM backend.
3
+ # Requires vLLM at localhost:8000. Takes 10-18 hours.
4
+ #
5
+ # Usage:
6
+ # ./scripts/test_bank.sh # Run everything
7
+ # ./scripts/test_bank.sh build # Run only build tests
8
+ # ./scripts/test_bank.sh debug # Run only debug tests
9
+ # ./scripts/test_bank.sh update # Run only update tests
10
+ # ./scripts/test_bank.sh multi # Run only multi-agent tests
11
+ # ./scripts/test_bank.sh tools # Run only tool integration tests
12
+ # ./scripts/test_bank.sh quick # Run only easy tests (~2 hours)
13
+
14
+ set -euo pipefail
15
+ cd "$(dirname "$0")/.."
16
+
17
+ pip install -q "pytest>=9.0" pytest-asyncio httpx 2>/dev/null
18
+
19
+ COMMON_ARGS="-v -s -p no:xdist -p no:cov --override-ini=addopts="
20
+ CATEGORY="${1:-all}"
21
+ TIMESTAMP=$(date +%Y%m%d_%H%M%S)
22
+ LOG_DIR="test_bank_results"
23
+ mkdir -p "$LOG_DIR"
24
+
25
+ run_suite() {
26
+ local name="$1"
27
+ local file="$2"
28
+ local extra="${3:-}"
29
+ echo ""
30
+ echo "================================================================"
31
+ echo " $name — $(date)"
32
+ echo "================================================================"
33
+ local logfile="$LOG_DIR/${name}_${TIMESTAMP}.log"
34
+ python3 -m pytest "$file" $COMMON_ARGS $extra 2>&1 | tee "$logfile"
35
+ echo ""
36
+ echo "Results saved to: $logfile"
37
+ }
38
+
39
+ case "$CATEGORY" in
40
+ build)
41
+ run_suite "BUILD" "tests/test_bank_build.py"
42
+ ;;
43
+ debug)
44
+ run_suite "DEBUG" "tests/test_bank_debug.py"
45
+ ;;
46
+ update)
47
+ run_suite "UPDATE" "tests/test_bank_update.py"
48
+ ;;
49
+ multi)
50
+ run_suite "MULTI-AGENT" "tests/test_bank_multiagent.py"
51
+ ;;
52
+ tools)
53
+ run_suite "TOOLS" "tests/test_bank_tools.py"
54
+ ;;
55
+ quick)
56
+ echo "=== QUICK TEST BANK (Easy tests only, ~2 hours) ==="
57
+ run_suite "BUILD-EASY" "tests/test_bank_build.py" "-k TestBuildEasy"
58
+ run_suite "DEBUG-EASY" "tests/test_bank_debug.py" "-k TestDebugEasy"
59
+ run_suite "UPDATE-EASY" "tests/test_bank_update.py" "-k TestUpdateEasy"
60
+ run_suite "TOOLS" "tests/test_bank_tools.py"
61
+ ;;
62
+ all)
63
+ echo "=== FULL TEST BANK — Estimated 10-18 hours ==="
64
+ echo "=== Started: $(date) ==="
65
+ run_suite "BUILD" "tests/test_bank_build.py"
66
+ run_suite "DEBUG" "tests/test_bank_debug.py"
67
+ run_suite "UPDATE" "tests/test_bank_update.py"
68
+ run_suite "MULTI-AGENT" "tests/test_bank_multiagent.py"
69
+ run_suite "TOOLS" "tests/test_bank_tools.py"
70
+ echo ""
71
+ echo "=== FULL TEST BANK COMPLETE — $(date) ==="
72
+ echo "Results in: $LOG_DIR/"
73
+ ;;
74
+ *)
75
+ echo "Usage: $0 {all|build|debug|update|multi|tools|quick}"
76
+ exit 1
77
+ ;;
78
+ esac