drydock-cli 0.7.3__tar.gz → 0.8.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (467) hide show
  1. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/PKG-INFO +2 -1
  2. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/cli.py +1 -1
  3. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/external_editor.py +1 -1
  4. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/agent_loop.py +43 -9
  5. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/auth/github.py +1 -1
  6. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/config/_settings.py +1 -1
  7. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/logger.py +1 -1
  8. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/programmatic.py +1 -1
  9. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/search_replace.py +6 -3
  10. drydock_cli-0.8.0/drydock/core/tools/builtins/websearch.py +133 -0
  11. drydock_cli-0.8.0/drydock/skills/investigate/SKILL.md +67 -0
  12. drydock_cli-0.8.0/drydock/skills/review/SKILL.md +67 -0
  13. drydock_cli-0.8.0/drydock/skills/ship/SKILL.md +65 -0
  14. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/pyproject.toml +5 -1
  15. drydock_cli-0.8.0/scripts/backup.sh +84 -0
  16. drydock_cli-0.8.0/tests/test_current_bugs.py +150 -0
  17. drydock_cli-0.7.3/drydock/core/tools/builtins/websearch.py +0 -158
  18. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/CODEOWNERS +0 -0
  19. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
  20. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  21. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  22. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/workflows/build-and-upload.yml +0 -0
  23. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/workflows/ci.yml +0 -0
  24. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/workflows/issue-labeler.yml +0 -0
  25. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.github/workflows/release.yml +0 -0
  26. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.gitignore +0 -0
  27. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.pre-commit-config.yaml +0 -0
  28. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.python-version +0 -0
  29. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.typos.toml +0 -0
  30. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.vscode/extensions.json +0 -0
  31. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.vscode/launch.json +0 -0
  32. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/.vscode/settings.json +0 -0
  33. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/AGENTS.md +0 -0
  34. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/CHANGELOG.md +0 -0
  35. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/CLAUDE.md +0 -0
  36. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/CONTRIBUTING.md +0 -0
  37. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/Drydock_rebrand.md +0 -0
  38. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/LICENSE +0 -0
  39. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/NOTICE +0 -0
  40. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/PRD.md +0 -0
  41. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/README.md +0 -0
  42. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/action.yml +0 -0
  43. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/distribution/zed/LICENSE +0 -0
  44. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/distribution/zed/extension.toml +0 -0
  45. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/distribution/zed/icons/mistral_vibe.svg +0 -0
  46. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/docs/README.md +0 -0
  47. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/docs/acp-setup.md +0 -0
  48. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/docs/proxy-setup.md +0 -0
  49. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/__init__.py +0 -0
  50. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/__init__.py +0 -0
  51. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/acp_agent_loop.py +0 -0
  52. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/acp_logger.py +0 -0
  53. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/entrypoint.py +0 -0
  54. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/__init__.py +0 -0
  55. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/base.py +0 -0
  56. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/builtins/bash.py +0 -0
  57. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/builtins/read_file.py +0 -0
  58. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/builtins/search_replace.py +0 -0
  59. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/builtins/todo.py +0 -0
  60. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/builtins/write_file.py +0 -0
  61. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/tools/session_update.py +0 -0
  62. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/acp/utils.py +0 -0
  63. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/__init__.py +0 -0
  64. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/autocompletion/__init__.py +0 -0
  65. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/autocompletion/base.py +0 -0
  66. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/autocompletion/path_completion.py +0 -0
  67. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/autocompletion/slash_command.py +0 -0
  68. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/clipboard.py +0 -0
  69. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/commands.py +0 -0
  70. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/entrypoint.py +0 -0
  71. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/history_manager.py +0 -0
  72. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
  73. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
  74. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
  75. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/terminal_setup.py +0 -0
  76. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/__init__.py +0 -0
  77. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
  78. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/app.py +0 -0
  79. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/app.tcss +0 -0
  80. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
  81. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
  82. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
  83. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
  84. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
  85. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
  86. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
  87. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
  88. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
  89. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
  90. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
  91. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
  92. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
  93. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
  94. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
  95. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
  96. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
  97. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
  98. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/compact.py +0 -0
  99. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
  100. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
  101. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
  102. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/loading.py +0 -0
  103. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/messages.py +0 -0
  104. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
  105. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
  106. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
  107. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
  108. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
  109. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
  110. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
  111. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
  112. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
  113. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/tools.py +0 -0
  114. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
  115. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
  116. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/windowing/history.py +0 -0
  117. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
  118. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/textual_ui/windowing/state.py +0 -0
  119. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/__init__.py +0 -0
  120. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
  121. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
  122. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
  123. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
  124. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
  125. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/update.py +0 -0
  126. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/cli/update_notifier/whats_new.py +0 -0
  127. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/__init__.py +0 -0
  128. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/agents/__init__.py +0 -0
  129. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/agents/manager.py +0 -0
  130. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/agents/models.py +0 -0
  131. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/auth/__init__.py +0 -0
  132. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/auth/crypto.py +0 -0
  133. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/__init__.py +0 -0
  134. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/completers.py +0 -0
  135. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
  136. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
  137. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
  138. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/file_indexer/store.py +0 -0
  139. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
  140. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/fuzzy.py +0 -0
  141. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/path_prompt.py +0 -0
  142. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
  143. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/config/__init__.py +0 -0
  144. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/config/harness_files/__init__.py +0 -0
  145. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/config/harness_files/_harness_manager.py +0 -0
  146. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/config/harness_files/_paths.py +0 -0
  147. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/consultant.py +0 -0
  148. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/drydock_states.py +0 -0
  149. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/__init__.py +0 -0
  150. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/backend/anthropic.py +0 -0
  151. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/backend/base.py +0 -0
  152. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/backend/factory.py +0 -0
  153. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/backend/generic.py +0 -0
  154. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/backend/mistral.py +0 -0
  155. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
  156. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/backend/vertex.py +0 -0
  157. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/exceptions.py +0 -0
  158. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/format.py +0 -0
  159. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/message_utils.py +0 -0
  160. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/llm/types.py +0 -0
  161. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/middleware.py +0 -0
  162. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/output_formatters.py +0 -0
  163. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/paths/__init__.py +0 -0
  164. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/paths/_local_config_walk.py +0 -0
  165. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/paths/_vibe_home.py +0 -0
  166. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/paths/conventions.py +0 -0
  167. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/plan_session.py +0 -0
  168. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/__init__.py +0 -0
  169. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/cli.md +0 -0
  170. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/compact.md +0 -0
  171. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/dangerous_directory.md +0 -0
  172. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/diagnostic.md +0 -0
  173. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/explore.md +0 -0
  174. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/planner.md +0 -0
  175. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/project_context.md +0 -0
  176. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/prompts/tests.md +0 -0
  177. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/proxy_setup.py +0 -0
  178. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/session/session_loader.py +0 -0
  179. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/session/session_logger.py +0 -0
  180. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/session/session_migration.py +0 -0
  181. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/session/state_file.py +0 -0
  182. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/skills/__init__.py +0 -0
  183. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/skills/manager.py +0 -0
  184. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/skills/models.py +0 -0
  185. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/skills/parser.py +0 -0
  186. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/slug.py +0 -0
  187. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/system_prompt.py +0 -0
  188. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/telemetry/__init__.py +0 -0
  189. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/telemetry/send.py +0 -0
  190. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/teleport/errors.py +0 -0
  191. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/teleport/git.py +0 -0
  192. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/teleport/nuage.py +0 -0
  193. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/teleport/teleport.py +0 -0
  194. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/teleport/types.py +0 -0
  195. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/base.py +0 -0
  196. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/ask_user_question.py +0 -0
  197. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/bash.py +0 -0
  198. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
  199. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/grep.py +0 -0
  200. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
  201. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
  202. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/bash.md +0 -0
  203. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/grep.md +0 -0
  204. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
  205. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
  206. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
  207. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/task.md +0 -0
  208. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/todo.md +0 -0
  209. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
  210. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
  211. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
  212. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/read_file.py +0 -0
  213. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/task.py +0 -0
  214. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/todo.py +0 -0
  215. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/webfetch.py +0 -0
  216. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/builtins/write_file.py +0 -0
  217. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/injection_guard.py +0 -0
  218. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/manager.py +0 -0
  219. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/mcp/__init__.py +0 -0
  220. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/mcp/registry.py +0 -0
  221. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/mcp/tools.py +0 -0
  222. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/mcp_sampling.py +0 -0
  223. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/ui.py +0 -0
  224. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/tools/utils.py +0 -0
  225. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/trusted_folders.py +0 -0
  226. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/types.py +0 -0
  227. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/core/utils.py +0 -0
  228. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/onboarding/__init__.py +0 -0
  229. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/onboarding/base.py +0 -0
  230. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/onboarding/onboarding.tcss +0 -0
  231. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/onboarding/screens/__init__.py +0 -0
  232. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/onboarding/screens/api_key.py +0 -0
  233. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/onboarding/screens/welcome.py +0 -0
  234. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
  235. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
  236. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/skills/__init__.py +0 -0
  237. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/skills/create-presentation/SKILL.md +0 -0
  238. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/skills/deep-research/SKILL.md +0 -0
  239. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock/whats_new.md +0 -0
  240. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock-acp.spec +0 -0
  241. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/drydock_terms.md +0 -0
  242. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/flake.lock +0 -0
  243. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/flake.nix +0 -0
  244. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/scripts/README.md +0 -0
  245. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/scripts/bump_version.py +0 -0
  246. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/scripts/deploy_to_github.sh +0 -0
  247. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/scripts/install.sh +0 -0
  248. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/scripts/prepare_release.py +0 -0
  249. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/scripts/publish_to_pypi.sh +0 -0
  250. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/__init__.py +0 -0
  251. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/conftest.py +0 -0
  252. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_acp.py +0 -0
  253. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_agent_thought.py +0 -0
  254. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_bash.py +0 -0
  255. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_compact_session_updates.py +0 -0
  256. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_content.py +0 -0
  257. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_initialize.py +0 -0
  258. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_list_sessions.py +0 -0
  259. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_load_session.py +0 -0
  260. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_multi_session.py +0 -0
  261. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_new_session.py +0 -0
  262. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_proxy_setup_acp.py +0 -0
  263. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_read_file.py +0 -0
  264. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_search_replace.py +0 -0
  265. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_set_config_option.py +0 -0
  266. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_set_mode.py +0 -0
  267. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_set_model.py +0 -0
  268. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_tool_call_session_update.py +0 -0
  269. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_utils.py +0 -0
  270. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/acp/test_write_file.py +0 -0
  271. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_file_indexer.py +0 -0
  272. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_fuzzy.py +0 -0
  273. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
  274. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_path_completer_recursive.py +0 -0
  275. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_path_completion_controller.py +0 -0
  276. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
  277. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_slash_command_controller.py +0 -0
  278. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
  279. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/__init__.py +0 -0
  280. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/data/__init__.py +0 -0
  281. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/data/fireworks.py +0 -0
  282. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/data/mistral.py +0 -0
  283. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/test_anthropic_adapter.py +0 -0
  284. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/test_backend.py +0 -0
  285. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/test_reasoning_adapter.py +0 -0
  286. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
  287. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
  288. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
  289. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
  290. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_bell_notifications.py +0 -0
  291. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_braille_renderer.py +0 -0
  292. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_clipboard.py +0 -0
  293. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_commands.py +0 -0
  294. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_copy_shortcuts.py +0 -0
  295. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_external_editor.py +0 -0
  296. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_no_markup_static.py +0 -0
  297. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_question_app.py +0 -0
  298. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_spinner.py +0 -0
  299. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_switching_mode.py +0 -0
  300. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_ui_clipboard_notifications.py +0 -0
  301. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
  302. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_ui_session_resume.py +0 -0
  303. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/test_ui_skill_dispatch.py +0 -0
  304. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/textual_ui/__init__.py +0 -0
  305. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/cli/textual_ui/test_session_picker.py +0 -0
  306. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/conftest.py +0 -0
  307. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_agents.py +0 -0
  308. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_auth_crypto.py +0 -0
  309. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_auth_github.py +0 -0
  310. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_config_load_dotenv.py +0 -0
  311. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_config_paths.py +0 -0
  312. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_config_resolution.py +0 -0
  313. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_file_logging.py +0 -0
  314. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_plan_session.py +0 -0
  315. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_proxy_setup.py +0 -0
  316. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_slug.py +0 -0
  317. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_telemetry_send.py +0 -0
  318. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_teleport_git.py +0 -0
  319. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_teleport_nuage.py +0 -0
  320. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_teleport_service.py +0 -0
  321. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_trusted_folders.py +0 -0
  322. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/core/test_utils.py +0 -0
  323. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/e2e/common.py +0 -0
  324. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/e2e/conftest.py +0 -0
  325. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/e2e/mock_server.py +0 -0
  326. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/e2e/test_cli_tui_onboarding.py +0 -0
  327. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/e2e/test_cli_tui_streaming.py +0 -0
  328. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
  329. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/mock/__init__.py +0 -0
  330. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/mock/mock_backend_factory.py +0 -0
  331. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/mock/mock_entrypoint.py +0 -0
  332. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/mock/utils.py +0 -0
  333. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/onboarding/test_run_onboarding.py +0 -0
  334. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/onboarding/test_ui_onboarding.py +0 -0
  335. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/session/test_session_loader.py +0 -0
  336. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/session/test_session_logger.py +0 -0
  337. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/session/test_session_migration.py +0 -0
  338. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/skills/conftest.py +0 -0
  339. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/skills/test_manager.py +0 -0
  340. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/skills/test_models.py +0 -0
  341. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/skills/test_parser.py +0 -0
  342. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
  343. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
  344. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
  345. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
  346. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
  347. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
  348. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
  349. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
  350. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
  351. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
  352. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
  353. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
  354. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
  355. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
  356. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
  357. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
  358. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
  359. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
  360. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
  361. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
  362. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
  363. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
  364. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
  365. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
  366. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
  367. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
  368. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
  369. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
  370. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
  371. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
  372. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
  373. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
  374. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
  375. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
  376. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
  377. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
  378. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
  379. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
  380. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
  381. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
  382. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
  383. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
  384. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
  385. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
  386. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
  387. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
  388. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
  389. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
  390. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
  391. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
  392. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
  393. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
  394. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
  395. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
  396. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
  397. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
  398. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
  399. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
  400. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
  401. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
  402. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/base_snapshot_test_app.py +0 -0
  403. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/conftest.py +0 -0
  404. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/snap_compare.py +0 -0
  405. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
  406. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
  407. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
  408. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
  409. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
  410. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
  411. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
  412. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
  413. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
  414. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
  415. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
  416. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
  417. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
  418. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
  419. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/stubs/fake_backend.py +0 -0
  420. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/stubs/fake_client.py +0 -0
  421. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/stubs/fake_tool.py +0 -0
  422. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_agent_auto_compact.py +0 -0
  423. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_agent_backend.py +0 -0
  424. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_agent_observer_streaming.py +0 -0
  425. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_agent_stats.py +0 -0
  426. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_agent_tasks.py +0 -0
  427. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_agent_tool_call.py +0 -0
  428. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_agents.py +0 -0
  429. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_cli_programmatic_preload.py +0 -0
  430. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_drydock_regression.py +0 -0
  431. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_drydock_tasks.py +0 -0
  432. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_history_manager.py +0 -0
  433. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_integration.py +0 -0
  434. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_loop_detection.py +0 -0
  435. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_message_id.py +0 -0
  436. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_message_merging.py +0 -0
  437. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_middleware.py +0 -0
  438. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_real_failures.py +0 -0
  439. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_real_issues.py +0 -0
  440. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_reasoning_content.py +0 -0
  441. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_system_prompt.py +0 -0
  442. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_tagged_text.py +0 -0
  443. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_ui_external_editor.py +0 -0
  444. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_ui_input_history.py +0 -0
  445. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/test_user_issues.py +0 -0
  446. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_ask_user_question.py +0 -0
  447. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_bash.py +0 -0
  448. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_exit_plan_mode.py +0 -0
  449. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_grep.py +0 -0
  450. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_invoke_context.py +0 -0
  451. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_manager_get_tool_config.py +0 -0
  452. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_mcp.py +0 -0
  453. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_mcp_sampling.py +0 -0
  454. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_task.py +0 -0
  455. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_ui_bash_execution.py +0 -0
  456. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_webfetch.py +0 -0
  457. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/tools/test_websearch.py +0 -0
  458. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
  459. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
  460. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/test_do_update.py +0 -0
  461. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
  462. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/test_github_update_gateway.py +0 -0
  463. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
  464. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/test_ui_update_notification.py +0 -0
  465. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/test_update_use_case.py +0 -0
  466. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/tests/update_notifier/test_whats_new.py +0 -0
  467. {drydock_cli-0.7.3 → drydock_cli-0.8.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 0.7.3
3
+ Version: 0.8.0
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
@@ -24,6 +24,7 @@ Classifier: Topic :: Utilities
24
24
  Requires-Python: >=3.12
25
25
  Requires-Dist: agent-client-protocol==0.8.1
26
26
  Requires-Dist: anyio>=4.12.0
27
+ Requires-Dist: beautifulsoup4>=4.12.0
27
28
  Requires-Dist: cachetools>=5.5.0
28
29
  Requires-Dist: cryptography<=46.0.3,>=44.0.0
29
30
  Requires-Dist: gitpython>=3.1.46
@@ -196,7 +196,7 @@ def run_cli(args: argparse.Namespace) -> None:
196
196
  entrypoint_metadata=EntrypointMetadata(
197
197
  agent_entrypoint="cli",
198
198
  agent_version=__version__,
199
- client_name="vibe_cli",
199
+ client_name="drydock_cli",
200
200
  client_version=__version__,
201
201
  ),
202
202
  )
@@ -16,7 +16,7 @@ class ExternalEditor:
16
16
 
17
17
  def edit(self, initial_content: str = "") -> str | None:
18
18
  editor = self.get_editor()
19
- fd, filepath = tempfile.mkstemp(suffix=".md", prefix="vibe_")
19
+ fd, filepath = tempfile.mkstemp(suffix=".md", prefix="drydock_")
20
20
  try:
21
21
  with os.fdopen(fd, "w") as f:
22
22
  f.write(initial_content)
@@ -482,6 +482,7 @@ class AgentLoop:
482
482
  bash_count = 0 # Track consecutive bash calls without an edit
483
483
  search_replace_failures = 0 # Track failed search_replace attempts
484
484
  files_explored: list[str] = [] # Track files read for context state
485
+ files_modified: list[str] = [] # Track files edited for blast radius
485
486
  context_summary_injected = False
486
487
  while not should_break_loop:
487
488
  # Loop protection: prevent infinite tool-call loops
@@ -551,6 +552,14 @@ class AgentLoop:
551
552
  if tc.function.name in ("search_replace", "write_file"):
552
553
  has_made_edit = True
553
554
  bash_count = 0 # Reset on successful edit
555
+ # Track blast radius
556
+ try:
557
+ edit_args = json.loads(tc.function.arguments or "{}")
558
+ edit_path = edit_args.get("file_path", edit_args.get("path", ""))
559
+ if edit_path and edit_path not in files_modified:
560
+ files_modified.append(edit_path)
561
+ except (json.JSONDecodeError, AttributeError):
562
+ pass
554
563
  if tc.function.name == "read_file":
555
564
  try:
556
565
  args = json.loads(tc.function.arguments or "{}")
@@ -569,6 +578,15 @@ class AgentLoop:
569
578
  if "search_replace" in content.lower() and "error" in content.lower():
570
579
  search_replace_failures += 1
571
580
 
581
+ # Blast radius check: warn when touching 5+ files
582
+ if len(files_modified) >= 5 and len(files_modified) % 5 == 0:
583
+ self._inject_system_note(
584
+ f"BLAST RADIUS WARNING: You have modified {len(files_modified)} files. "
585
+ f"Files: {', '.join(files_modified[-5:])}. "
586
+ f"This is a large change. Are you sure all these edits are needed? "
587
+ f"Consider stopping to verify your approach."
588
+ )
589
+
572
590
  # Bash abuse detection: if model keeps using bash instead of
573
591
  # search_replace/read_file, redirect it to the proper tools
574
592
  if not has_made_edit and bash_count >= 10 and bash_count % 5 == 0:
@@ -579,14 +597,26 @@ class AgentLoop:
579
597
  "Call search_replace NOW with your fix."
580
598
  )
581
599
 
582
- # search_replace keeps failing — suggest re-reading the file
583
- if search_replace_failures >= 3 and search_replace_failures % 2 == 1:
584
- self._inject_system_note(
585
- f"Your search_replace has failed {search_replace_failures} times. "
586
- "The text you're searching for doesn't match the file. STOP guessing. "
587
- "Use read_file with offset/limit to see the EXACT current text, "
588
- "then copy it precisely into search_replace old_str."
589
- )
600
+ # 3-Strike Rule: search_replace keeps failing
601
+ if search_replace_failures >= 3:
602
+ if search_replace_failures == 3:
603
+ # Strike 3: STOP and ask user
604
+ self.messages.append(LLMMessage(
605
+ role=Role.user,
606
+ content=(
607
+ f"3-STRIKE RULE: Your search_replace has failed {search_replace_failures} times. "
608
+ "You have exhausted your attempts. STOP trying the same approach. "
609
+ "Either: (1) use read_file to get the EXACT text first, "
610
+ "(2) try a completely different file, or "
611
+ "(3) ask the user for help with /consult."
612
+ )
613
+ ))
614
+ elif search_replace_failures % 3 == 0:
615
+ # Every 3 more failures, escalate
616
+ self.messages.append(LLMMessage(
617
+ role=Role.user,
618
+ content=f"STOP: {search_replace_failures} failed edits. You are stuck. Ask the user for help."
619
+ ))
590
620
 
591
621
  # Context budget warning: after 7 tool turns without an edit,
592
622
  # warn that context is being consumed without progress
@@ -647,7 +677,11 @@ class AgentLoop:
647
677
  should_break_loop = True
648
678
  nudge_text = None
649
679
  if nudge_text:
650
- self._inject_system_note(nudge_text)
680
+ # Inject as user message so the model actually sees it
681
+ # (inject_system_note buries it in old tool results)
682
+ self.messages.append(
683
+ LLMMessage(role=Role.user, content=nudge_text)
684
+ )
651
685
  logger.info("Model gave text without editing — nudging (attempt %d)", text_without_action)
652
686
 
653
687
  # If model has been investigating for too long without making an edit,
@@ -11,7 +11,7 @@ import keyring.errors
11
11
 
12
12
  GITHUB_CLIENT_ID = "Ov23liJ7sk5kFDMEyvDT"
13
13
 
14
- _SERVICE_NAME = "vibe"
14
+ _SERVICE_NAME = "drydock"
15
15
  _KEYRING_USERNAME = "github_token"
16
16
  _DEVICE_CODE_URL = "https://github.com/login/device/code"
17
17
  _TOKEN_URL = "https://github.com/login/oauth/access_token"
@@ -267,7 +267,7 @@ DEFAULT_PROVIDERS = [
267
267
 
268
268
  DEFAULT_MODELS = [
269
269
  ModelConfig(
270
- name="mistral-vibe-cli-latest",
270
+ name="drydock-cli-latest",
271
271
  provider="mistral",
272
272
  alias="devstral-2",
273
273
  input_price=0.4,
@@ -9,7 +9,7 @@ from drydock.core.paths import LOG_DIR, LOG_FILE
9
9
 
10
10
  LOG_DIR.path.mkdir(parents=True, exist_ok=True)
11
11
 
12
- logger = logging.getLogger("vibe")
12
+ logger = logging.getLogger("drydock")
13
13
 
14
14
 
15
15
  class StructuredLogFormatter(logging.Formatter):
@@ -21,7 +21,7 @@ from drydock.core.types import (
21
21
  )
22
22
  from drydock.core.utils import ConversationLimitException
23
23
 
24
- _DEFAULT_CLIENT_METADATA = ClientMetadata(name="vibe_programmatic", version=__version__)
24
+ _DEFAULT_CLIENT_METADATA = ClientMetadata(name="drydock_programmatic", version=__version__)
25
25
 
26
26
 
27
27
  def run_programmatic(
@@ -119,12 +119,15 @@ class SearchReplace(
119
119
  ) -> AsyncGenerator[ToolStreamEvent | SearchReplaceResult, None]:
120
120
  file_path, search_replace_blocks = self._prepare_and_validate_args(args)
121
121
 
122
- # Warn (but don't block) when editing test files
122
+ # BLOCK editing test files the bug is in source code, not tests
123
123
  file_str = str(file_path)
124
124
  if ("/tests/" in file_str or "/test_" in file_str or
125
125
  file_str.endswith("_test.py") or "/testing/" in file_str):
126
- import logging
127
- logging.getLogger(__name__).warning("search_replace targeting test file: %s", 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
+ )
128
131
 
129
132
  # Injection guard: scan replacement content for suspicious patterns
130
133
  from drydock.core.tools.injection_guard import check_content_for_injection
@@ -0,0 +1,133 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import AsyncGenerator
4
+ import os
5
+ import urllib.parse
6
+ from typing import ClassVar, final
7
+
8
+ from pydantic import BaseModel, Field
9
+ from bs4 import BeautifulSoup
10
+
11
+ from drydock.core.tools.base import (
12
+ BaseTool,
13
+ BaseToolConfig,
14
+ BaseToolState,
15
+ InvokeContext,
16
+ ToolError,
17
+ ToolPermission,
18
+ )
19
+ from drydock.core.tools.ui import ToolCallDisplay, ToolResultDisplay, ToolUIData
20
+ from drydock.core.types import ToolStreamEvent
21
+
22
+
23
+ class WebSearchSource(BaseModel):
24
+ title: str
25
+ url: str
26
+
27
+
28
+ class WebSearchArgs(BaseModel):
29
+ query: str = Field(min_length=1)
30
+
31
+
32
+ class WebSearchResult(BaseModel):
33
+ answer: str
34
+ sources: list[WebSearchSource] = Field(default_factory=list)
35
+
36
+
37
+ class WebSearchConfig(BaseToolConfig):
38
+ permission: ToolPermission = ToolPermission.ASK
39
+ timeout: int = Field(default=30, description="HTTP timeout in seconds.")
40
+
41
+
42
+ class WebSearch(
43
+ BaseTool[WebSearchArgs, WebSearchResult, WebSearchConfig, BaseToolState],
44
+ ToolUIData[WebSearchArgs, WebSearchResult],
45
+ ):
46
+ description: ClassVar[str] = "Search the web directly without an API key to find current information."
47
+
48
+ @classmethod
49
+ def is_available(cls) -> bool:
50
+ # Always available! No API key required.
51
+ return True
52
+
53
+ @final
54
+ async def run(
55
+ self, args: WebSearchArgs, ctx: InvokeContext | None = None
56
+ ) -> AsyncGenerator[ToolStreamEvent | WebSearchResult, None]:
57
+
58
+ import httpx
59
+
60
+ # Grab your proxy settings
61
+ proxy_url = os.getenv("HTTPS_PROXY") or os.getenv("https_proxy") or os.getenv("HTTP_PROXY") or os.getenv("http_proxy")
62
+
63
+ headers = {
64
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
65
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
66
+ }
67
+
68
+ try:
69
+ # Respect DRYDOCK_INSECURE flag for SSL bypass
70
+ verify_ssl = os.environ.get("DRYDOCK_INSECURE") != "1"
71
+ async with httpx.AsyncClient(proxy=proxy_url, verify=not verify_ssl if verify_ssl else False, headers=headers) as client:
72
+ response = await client.post(
73
+ "https://html.duckduckgo.com/html/",
74
+ data={"q": args.query},
75
+ timeout=self.config.timeout
76
+ )
77
+ response.raise_for_status()
78
+ except Exception as e:
79
+ raise ToolError(f"Failed to fetch search results: {str(e)}")
80
+
81
+ # Parse the DuckDuckGo HTML results
82
+ soup = BeautifulSoup(response.text, "html.parser")
83
+ results = soup.find_all("div", class_="result")
84
+
85
+ text_parts = []
86
+ sources = []
87
+
88
+ # Extract the top 5 results
89
+ for res in results[:5]:
90
+ title_tag = res.find("a", class_="result__url")
91
+ snippet_tag = res.find("a", class_="result__snippet")
92
+
93
+ if title_tag and snippet_tag:
94
+ title = title_tag.text.strip()
95
+ snippet = snippet_tag.text.strip()
96
+ raw_url = title_tag.get("href", "")
97
+
98
+ # Clean up DuckDuckGo's redirect URLs
99
+ if "uddg=" in raw_url:
100
+ clean_url = urllib.parse.unquote(raw_url.split("uddg=")[1].split("&")[0])
101
+ else:
102
+ clean_url = raw_url
103
+
104
+ sources.append(WebSearchSource(title=title, url=clean_url))
105
+ text_parts.append(f"Source: {title}\nURL: {clean_url}\nInformation: {snippet}\n")
106
+
107
+ if not text_parts:
108
+ answer = "No relevant information found on the web."
109
+ else:
110
+ # We bundle the snippets into a single text block for your local model to read
111
+ answer = "Here is the raw information retrieved from the web:\n\n" + "\n".join(text_parts)
112
+
113
+ yield WebSearchResult(answer=answer, sources=sources)
114
+
115
+ @classmethod
116
+ def get_call_display(cls, event: ToolCallEvent) -> ToolCallDisplay:
117
+ if event.args is None or not isinstance(event.args, WebSearchArgs):
118
+ return ToolCallDisplay(summary="websearch")
119
+ return ToolCallDisplay(summary=f"Searching DuckDuckGo for: '{event.args.query}'")
120
+
121
+ @classmethod
122
+ def get_result_display(cls, event: ToolResultEvent) -> ToolResultDisplay:
123
+ if not isinstance(event.result, WebSearchResult):
124
+ return ToolResultDisplay(
125
+ success=False, message=event.error or event.skip_reason or "No result"
126
+ )
127
+ return ToolResultDisplay(
128
+ success=True, message=f"{len(event.result.sources)} web sources retrieved for the local model."
129
+ )
130
+
131
+ @classmethod
132
+ def get_status_text(cls) -> str:
133
+ return "Scraping the web..."
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: investigate
3
+ description: Systematic debugging with 3-strike rule. Investigate → Analyze → Hypothesize → Fix. Stops after 3 failed hypotheses.
4
+ user-invocable: true
5
+ allowed-tools:
6
+ - bash
7
+ - grep
8
+ - read_file
9
+ - search_replace
10
+ - write_file
11
+ - ask_user_question
12
+ ---
13
+
14
+ # Investigate
15
+
16
+ Systematic debugging workflow. You are a senior debugger.
17
+
18
+ ## Iron Law
19
+
20
+ **Never fix without root cause.** If you don't understand WHY the bug happens, you don't fix it.
21
+
22
+ ## Workflow
23
+
24
+ ### Phase 1: INVESTIGATE
25
+ - Read the error message / bug report carefully
26
+ - Identify the module and function where the bug manifests
27
+ - grep for the relevant code paths
28
+ - Read the specific functions involved
29
+
30
+ ### Phase 2: ANALYZE
31
+ - Trace the data flow from input to the point of failure
32
+ - Identify what value is wrong and where it diverges from expected
33
+ - Check edge cases: null, empty, boundary values
34
+
35
+ ### Phase 3: HYPOTHESIZE
36
+ State your hypothesis clearly:
37
+ ```
38
+ HYPOTHESIS: The bug is caused by [X] in [file:line] because [reason].
39
+ EXPECTED: [what should happen]
40
+ ACTUAL: [what happens instead]
41
+ FIX: [what change to make]
42
+ ```
43
+
44
+ ### Phase 4: IMPLEMENT
45
+ - Make the minimal fix
46
+ - Read back the changed code to verify
47
+ - If the fix doesn't work, go back to Phase 3
48
+
49
+ ## 3-Strike Rule
50
+
51
+ Track your failed hypotheses:
52
+ - Strike 1: "Hypothesis 1 failed because [reason]. Trying different approach."
53
+ - Strike 2: "Hypothesis 2 failed because [reason]. One more attempt."
54
+ - Strike 3: **STOP.** Ask the user: "I've tried 3 approaches and none worked. Here's what I've learned: [summary]. What should I try next?"
55
+
56
+ Do NOT continue past 3 strikes. Ask for help.
57
+
58
+ ## Scope Lock
59
+
60
+ Once you identify the module, **stay in that module**. Do not wander to other parts of the codebase unless the bug clearly crosses module boundaries.
61
+
62
+ ## Blast Radius Check
63
+
64
+ Before applying a fix, count the files you're about to change:
65
+ - 1-2 files: proceed
66
+ - 3-4 files: mention it to the user first
67
+ - 5+ files: **STOP and ask.** "This fix touches {N} files. Should I proceed?"
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: review
3
+ description: Automated code review. Two-pass (critical then informational), scope drift detection, fix-first.
4
+ user-invocable: true
5
+ allowed-tools:
6
+ - bash
7
+ - grep
8
+ - read_file
9
+ - search_replace
10
+ ---
11
+
12
+ # Code Review
13
+
14
+ You are a senior code reviewer. Review the current changes.
15
+
16
+ ## Two-Pass Review
17
+
18
+ ### Pass 1: CRITICAL (must fix before merge)
19
+ - Security vulnerabilities (injection, XSS, auth bypass)
20
+ - Data loss risks (missing transactions, race conditions)
21
+ - Breaking changes to public APIs
22
+ - Missing error handling that could crash
23
+ - Tests missing for new functionality
24
+
25
+ ### Pass 2: INFORMATIONAL (nice to have)
26
+ - Code style and naming
27
+ - Performance suggestions
28
+ - Refactoring opportunities
29
+ - Documentation gaps
30
+
31
+ ## Workflow
32
+
33
+ 1. Run `git diff` to see what changed
34
+ 2. Read each changed file
35
+ 3. For each issue found:
36
+ - **Critical**: Fix it immediately with search_replace
37
+ - **Judgment call**: Ask the user with options
38
+ - **Informational**: Note it but don't block
39
+
40
+ ## Scope Drift Detection
41
+
42
+ If the diff contains changes unrelated to the stated goal:
43
+ - Flag: "These files seem unrelated to the task: [list]"
44
+ - Ask: "Should these be in a separate commit?"
45
+
46
+ ## Fix-First Philosophy
47
+
48
+ - Mechanical issues (typos, missing imports, obvious bugs): fix silently
49
+ - Style issues: fix if trivial, note if subjective
50
+ - Architecture decisions: always ask
51
+
52
+ ## Output Format
53
+
54
+ ```
55
+ ## Review Summary
56
+
57
+ ### Critical (must fix)
58
+ - [ ] [file:line] Issue description
59
+
60
+ ### Informational
61
+ - [file:line] Suggestion
62
+
63
+ ### Scope
64
+ - Files changed: N
65
+ - Lines added: N, removed: N
66
+ - Test coverage: [assessed/not assessed]
67
+ ```
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: ship
3
+ description: Automated shipping pipeline. Test → Review → Commit → Push → PR. Non-interactive.
4
+ user-invocable: true
5
+ allowed-tools:
6
+ - bash
7
+ - grep
8
+ - read_file
9
+ - write_file
10
+ - search_replace
11
+ ---
12
+
13
+ # Ship
14
+
15
+ Automated shipping pipeline. You are a release engineer.
16
+
17
+ ## Verification Gate
18
+
19
+ **Never claim completion without fresh test evidence.**
20
+
21
+ ## Pipeline
22
+
23
+ ### Step 1: Pre-flight checks
24
+ ```bash
25
+ git status
26
+ git diff --stat
27
+ ```
28
+ - If working tree is dirty, ask what to include
29
+ - If on main/master, ask to create a branch first
30
+
31
+ ### Step 2: Run tests
32
+ ```bash
33
+ python3 -m pytest tests/ -q --tb=short 2>&1 | tail -20
34
+ ```
35
+ - If tests fail: **STOP.** Fix the failures first.
36
+ - If no test runner found, note it and continue.
37
+
38
+ ### Step 3: Review diff
39
+ - Run `/review` mentally (check for critical issues)
40
+ - If >5 files changed, confirm with user
41
+
42
+ ### Step 4: Commit
43
+ - Write a clear commit message following conventional commits:
44
+ - `feat:` for new features
45
+ - `fix:` for bug fixes
46
+ - `refactor:` for code changes that aren't fixes or features
47
+ - `docs:` for documentation
48
+ - `test:` for test changes
49
+ - Each commit should be bisectable (tests pass at every commit)
50
+
51
+ ### Step 5: Push and PR
52
+ ```bash
53
+ git push origin HEAD
54
+ ```
55
+ - If `gh` CLI is available, create a PR:
56
+ ```bash
57
+ gh pr create --title "..." --body "..."
58
+ ```
59
+
60
+ ## Rules
61
+
62
+ - Never force push to main/master
63
+ - Never skip tests
64
+ - Never commit secrets, tokens, or credentials
65
+ - Always include what changed and why in the commit message
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "drydock-cli"
3
- version = "0.7.3"
3
+ version = "0.8.0"
4
4
  description = "Drydock — nautical CLI coding agent"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -30,6 +30,7 @@ classifiers = [
30
30
  dependencies = [
31
31
  "agent-client-protocol==0.8.1",
32
32
  "anyio>=4.12.0",
33
+ "beautifulsoup4>=4.12.0",
33
34
  "cachetools>=5.5.0",
34
35
  "cryptography>=44.0.0,<=46.0.3",
35
36
  "gitpython>=3.1.46",
@@ -77,6 +78,9 @@ include = ["drydock/"]
77
78
  [tool.hatch.build.targets.wheel.force-include]
78
79
  "drydock/skills/create-presentation" = "drydock/skills/create-presentation"
79
80
  "drydock/skills/deep-research" = "drydock/skills/deep-research"
81
+ "drydock/skills/investigate" = "drydock/skills/investigate"
82
+ "drydock/skills/review" = "drydock/skills/review"
83
+ "drydock/skills/ship" = "drydock/skills/ship"
80
84
 
81
85
 
82
86
  [project.scripts]
@@ -0,0 +1,84 @@
1
+ #!/bin/bash
2
+ # Backup DryDock project to NAS
3
+ # Cron: 0 3 * * * /data3/drydock/scripts/backup.sh >> /data3/drydock/logs/backup.log 2>&1
4
+
5
+ set -euo pipefail
6
+
7
+ DRYDOCK_SRC="/data3/drydock"
8
+ BENCH_DIR="/data3/swe_bench_runs"
9
+ NAS_MOUNT="/mnt/nas_backups"
10
+ BACKUP_DIR="$NAS_MOUNT/drydock"
11
+ DATE=$(date +%Y%m%d)
12
+ LOGDIR="$DRYDOCK_SRC/logs"
13
+
14
+ mkdir -p "$LOGDIR"
15
+
16
+ log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
17
+
18
+ # Check NAS is mounted
19
+ if ! mountpoint -q "$NAS_MOUNT" 2>/dev/null; then
20
+ log "NAS not mounted. Attempting mount..."
21
+ sudo mount "$NAS_MOUNT" 2>/dev/null || {
22
+ log "ERROR: Cannot mount NAS at $NAS_MOUNT. Skipping backup."
23
+ exit 1
24
+ }
25
+ fi
26
+
27
+ mkdir -p "$BACKUP_DIR"
28
+
29
+ log "Starting backup..."
30
+
31
+ # Backup 1: DryDock source code (excluding __pycache__, .git objects)
32
+ rsync -rlpt --delete --no-group --no-owner \
33
+ --exclude='__pycache__/' \
34
+ --exclude='.pytest_cache/' \
35
+ --exclude='dist/' \
36
+ --exclude='*.egg-info/' \
37
+ --exclude='.git/objects/' \
38
+ --exclude='logs/' \
39
+ "$DRYDOCK_SRC/" "$BACKUP_DIR/source/"
40
+
41
+ log "Source backed up."
42
+
43
+ # Backup 2: SWE-bench results and state (not the repos — too large)
44
+ rsync -rlpt --delete --no-group --no-owner \
45
+ --exclude='repos/' \
46
+ --exclude='tasks/*/repo/' \
47
+ --exclude='__pycache__/' \
48
+ "$BENCH_DIR/continuous_bench_state.json" \
49
+ "$BENCH_DIR/auto_improve_state.json" \
50
+ "$BENCH_DIR/harness.py" \
51
+ "$BENCH_DIR/continuous_bench.sh" \
52
+ "$BENCH_DIR/analyze_batch.py" \
53
+ "$BACKUP_DIR/bench/" 2>/dev/null || true
54
+
55
+ # Backup results directories (small — just JSON)
56
+ rsync -rlpt --no-group --no-owner \
57
+ --include='*/' \
58
+ --include='results.json' \
59
+ --exclude='*' \
60
+ "$BENCH_DIR/results/" "$BACKUP_DIR/bench/results/" 2>/dev/null || true
61
+
62
+ log "Bench state backed up."
63
+
64
+ # Backup 3: Config files
65
+ mkdir -p "$BACKUP_DIR/config/drydock_config" "$BACKUP_DIR/config/drydock_home"
66
+ rsync -rlpt --no-group --no-owner "$HOME/.config/drydock/" "$BACKUP_DIR/config/drydock_config/" 2>/dev/null || true
67
+ rsync -rlpt --no-group --no-owner --exclude='logs/' "$HOME/.drydock/" "$BACKUP_DIR/config/drydock_home/" 2>/dev/null || true
68
+
69
+ log "Config backed up."
70
+
71
+ # Backup 4: Crontab
72
+ crontab -l > "$BACKUP_DIR/crontab_$(hostname).txt" 2>/dev/null || true
73
+
74
+ # Write backup manifest
75
+ cat > "$BACKUP_DIR/MANIFEST.txt" << EOF
76
+ DryDock Backup
77
+ Date: $(date)
78
+ Host: $(hostname)
79
+ Source: $DRYDOCK_SRC
80
+ Bench: $BENCH_DIR
81
+ Version: $(python3 -c "import sys; sys.path.insert(0,'$DRYDOCK_SRC'); from drydock import __version__; print(__version__)" 2>/dev/null || echo "unknown")
82
+ EOF
83
+
84
+ log "Backup complete to $BACKUP_DIR"