drydock-cli 2.6.22__tar.gz → 2.6.25__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 (556) hide show
  1. drydock_cli-2.6.25/.auto_release.lock +1 -0
  2. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.gitignore +1 -0
  3. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/CLAUDE.md +221 -28
  4. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/PKG-INFO +1 -1
  5. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/agent_loop.py +206 -0
  6. drydock_cli-2.6.25/drydock/core/tools/builtins/write_file.py +412 -0
  7. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/pyproject.toml +1 -1
  8. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/auto_release.sh +6 -0
  9. drydock_cli-2.6.25/scripts/run_pain_suite.sh +73 -0
  10. drydock_cli-2.6.25/scripts/user_pain_test.py +589 -0
  11. drydock_cli-2.6.25/tests/fixtures/doc_qa_system_prd.md +86 -0
  12. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_smoke.py +1 -1
  13. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_tool_args.py +1 -1
  14. drydock_cli-2.6.22/.auto_release.lock +0 -1
  15. drydock_cli-2.6.22/drydock/core/tools/builtins/write_file.py +0 -202
  16. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.github/CODEOWNERS +0 -0
  17. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
  18. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  19. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  20. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.github/workflows/build-and-upload.yml +0 -0
  21. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.github/workflows/ci.yml +0 -0
  22. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.github/workflows/issue-labeler.yml +0 -0
  23. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.github/workflows/release.yml +0 -0
  24. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.pre-commit-config.yaml +0 -0
  25. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.python-version +0 -0
  26. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.typos.toml +0 -0
  27. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.vscode/extensions.json +0 -0
  28. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.vscode/launch.json +0 -0
  29. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/.vscode/settings.json +0 -0
  30. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/AGENTS.md +0 -0
  31. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/CHANGELOG.md +0 -0
  32. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/CONTRIBUTING.md +0 -0
  33. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/Drydock_rebrand.md +0 -0
  34. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/LICENSE +0 -0
  35. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/NOTICE +0 -0
  36. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/PRD.md +0 -0
  37. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/README.md +0 -0
  38. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/action.yml +0 -0
  39. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/distribution/zed/LICENSE +0 -0
  40. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/distribution/zed/extension.toml +0 -0
  41. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/distribution/zed/icons/mistral_vibe.svg +0 -0
  42. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/docs/README.md +0 -0
  43. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/docs/acp-setup.md +0 -0
  44. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/docs/proxy-setup.md +0 -0
  45. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/__init__.py +0 -0
  46. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/acp/__init__.py +0 -0
  47. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/acp/acp_agent_loop.py +0 -0
  48. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/acp/acp_logger.py +0 -0
  49. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/acp/entrypoint.py +0 -0
  50. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/acp/tools/__init__.py +0 -0
  51. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/acp/tools/base.py +0 -0
  52. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/acp/tools/builtins/bash.py +0 -0
  53. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/acp/tools/builtins/read_file.py +0 -0
  54. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/acp/tools/builtins/search_replace.py +0 -0
  55. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/acp/tools/builtins/todo.py +0 -0
  56. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/acp/tools/builtins/write_file.py +0 -0
  57. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/acp/tools/session_update.py +0 -0
  58. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/acp/utils.py +0 -0
  59. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/__init__.py +0 -0
  60. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/autocompletion/__init__.py +0 -0
  61. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/autocompletion/base.py +0 -0
  62. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/autocompletion/path_completion.py +0 -0
  63. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/autocompletion/slash_command.py +0 -0
  64. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/cli.py +0 -0
  65. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/clipboard.py +0 -0
  66. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/commands.py +0 -0
  67. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/entrypoint.py +0 -0
  68. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/history_manager.py +0 -0
  69. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
  70. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
  71. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
  72. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/terminal_setup.py +0 -0
  73. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/__init__.py +0 -0
  74. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
  75. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/app.py +0 -0
  76. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/app.tcss +0 -0
  77. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/external_editor.py +0 -0
  78. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
  79. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
  80. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
  81. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
  82. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
  83. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
  84. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
  85. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
  86. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
  87. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
  88. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
  89. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
  90. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
  91. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
  92. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
  93. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
  94. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
  95. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
  96. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/compact.py +0 -0
  97. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
  98. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
  99. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
  100. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/loading.py +0 -0
  101. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/messages.py +0 -0
  102. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
  103. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
  104. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
  105. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
  106. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
  107. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
  108. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
  109. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
  110. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
  111. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/tools.py +0 -0
  112. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
  113. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
  114. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/windowing/history.py +0 -0
  115. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
  116. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/textual_ui/windowing/state.py +0 -0
  117. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/update_notifier/__init__.py +0 -0
  118. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
  119. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
  120. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
  121. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
  122. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
  123. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/update_notifier/update.py +0 -0
  124. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/cli/update_notifier/whats_new.py +0 -0
  125. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/__init__.py +0 -0
  126. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/agents/__init__.py +0 -0
  127. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/agents/manager.py +0 -0
  128. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/agents/models.py +0 -0
  129. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/auth/__init__.py +0 -0
  130. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/auth/crypto.py +0 -0
  131. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/auth/github.py +0 -0
  132. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/autocompletion/__init__.py +0 -0
  133. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/autocompletion/completers.py +0 -0
  134. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
  135. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
  136. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
  137. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/autocompletion/file_indexer/store.py +0 -0
  138. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
  139. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/autocompletion/fuzzy.py +0 -0
  140. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/autocompletion/path_prompt.py +0 -0
  141. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
  142. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/build_orchestrator.py +0 -0
  143. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/config/__init__.py +0 -0
  144. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/config/_settings.py +0 -0
  145. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/config/harness_files/__init__.py +0 -0
  146. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/config/harness_files/_harness_manager.py +0 -0
  147. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/config/harness_files/_paths.py +0 -0
  148. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/consultant.py +0 -0
  149. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/drydock_states.py +0 -0
  150. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/hooks.py +0 -0
  151. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/llm/__init__.py +0 -0
  152. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/llm/backend/anthropic.py +0 -0
  153. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/llm/backend/base.py +0 -0
  154. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/llm/backend/factory.py +0 -0
  155. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/llm/backend/generic.py +0 -0
  156. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/llm/backend/mistral.py +0 -0
  157. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
  158. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/llm/backend/vertex.py +0 -0
  159. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/llm/exceptions.py +0 -0
  160. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/llm/format.py +0 -0
  161. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/llm/message_utils.py +0 -0
  162. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/llm/types.py +0 -0
  163. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/logger.py +0 -0
  164. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/middleware.py +0 -0
  165. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/output_formatters.py +0 -0
  166. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/paths/__init__.py +0 -0
  167. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/paths/_local_config_walk.py +0 -0
  168. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/paths/_vibe_home.py +0 -0
  169. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/paths/conventions.py +0 -0
  170. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/plan_session.py +0 -0
  171. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/plugins.py +0 -0
  172. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/programmatic.py +0 -0
  173. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/prompts/__init__.py +0 -0
  174. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/prompts/builder.md +0 -0
  175. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/prompts/cli.md +0 -0
  176. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/prompts/compact.md +0 -0
  177. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/prompts/dangerous_directory.md +0 -0
  178. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/prompts/diagnostic.md +0 -0
  179. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/prompts/explore.md +0 -0
  180. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/prompts/gemma4.md +0 -0
  181. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/prompts/planner.md +0 -0
  182. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/prompts/project_context.md +0 -0
  183. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/prompts/tests.md +0 -0
  184. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/proxy_setup.py +0 -0
  185. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/session/agent_memory.py +0 -0
  186. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/session/checkpoints.py +0 -0
  187. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/session/session_loader.py +0 -0
  188. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/session/session_logger.py +0 -0
  189. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/session/session_migration.py +0 -0
  190. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/session/state_file.py +0 -0
  191. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/session_checker.py +0 -0
  192. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/skills/__init__.py +0 -0
  193. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/skills/manager.py +0 -0
  194. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/skills/models.py +0 -0
  195. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/skills/parser.py +0 -0
  196. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/slug.py +0 -0
  197. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/system_prompt.py +0 -0
  198. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/telemetry/__init__.py +0 -0
  199. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/telemetry/send.py +0 -0
  200. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/teleport/errors.py +0 -0
  201. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/teleport/git.py +0 -0
  202. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/teleport/nuage.py +0 -0
  203. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/teleport/teleport.py +0 -0
  204. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/teleport/types.py +0 -0
  205. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/base.py +0 -0
  206. /drydock_cli-2.6.22/drydock/core/tools/builtins/task_manager.py → /drydock_cli-2.6.25/drydock/core/tools/builtins/_task_manager.py +0 -0
  207. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/ask_user_question.py +0 -0
  208. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/bash.py +0 -0
  209. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/cron.py +0 -0
  210. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
  211. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/glob_tool.py +0 -0
  212. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/grep.py +0 -0
  213. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/invoke_skill.py +0 -0
  214. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/lsp.py +0 -0
  215. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/mcp_resources.py +0 -0
  216. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/notebook_edit.py +0 -0
  217. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/powershell.py +0 -0
  218. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
  219. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
  220. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/bash.md +0 -0
  221. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/cron.md +0 -0
  222. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/glob.md +0 -0
  223. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/grep.md +0 -0
  224. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/invoke_skill.md +0 -0
  225. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/lsp.md +0 -0
  226. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/mcp_resources.md +0 -0
  227. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
  228. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/powershell.md +0 -0
  229. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
  230. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
  231. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
  232. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/task.md +0 -0
  233. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
  234. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/todo.md +0 -0
  235. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/tool_search.md +0 -0
  236. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
  237. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
  238. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/worktree.md +0 -0
  239. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
  240. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/read_file.py +0 -0
  241. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/search_replace.py +0 -0
  242. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/task.py +0 -0
  243. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/todo.py +0 -0
  244. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/tool_search.py +0 -0
  245. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/webfetch.py +0 -0
  246. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/websearch.py +0 -0
  247. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/builtins/worktree.py +0 -0
  248. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/injection_guard.py +0 -0
  249. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/manager.py +0 -0
  250. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/mcp/__init__.py +0 -0
  251. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/mcp/registry.py +0 -0
  252. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/mcp/tools.py +0 -0
  253. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/mcp_sampling.py +0 -0
  254. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/ui.py +0 -0
  255. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/tools/utils.py +0 -0
  256. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/trusted_folders.py +0 -0
  257. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/types.py +0 -0
  258. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/core/utils.py +0 -0
  259. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/setup/onboarding/__init__.py +0 -0
  260. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/setup/onboarding/base.py +0 -0
  261. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/setup/onboarding/onboarding.tcss +0 -0
  262. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/setup/onboarding/screens/__init__.py +0 -0
  263. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/setup/onboarding/screens/api_key.py +0 -0
  264. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/setup/onboarding/screens/welcome.py +0 -0
  265. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
  266. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
  267. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/__init__.py +0 -0
  268. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/api-design/SKILL.md +0 -0
  269. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/batch/SKILL.md +0 -0
  270. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/commit-code/SKILL.md +0 -0
  271. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/context-summary/SKILL.md +0 -0
  272. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/create-presentation/SKILL.md +0 -0
  273. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/deep-research/SKILL.md +0 -0
  274. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/deploy/SKILL.md +0 -0
  275. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/diff-review/SKILL.md +0 -0
  276. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/doc-gen/SKILL.md +0 -0
  277. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/explain-code/SKILL.md +0 -0
  278. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/explore-code/SKILL.md +0 -0
  279. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/fix-issue/SKILL.md +0 -0
  280. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/git-ops/SKILL.md +0 -0
  281. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/init-project/SKILL.md +0 -0
  282. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/investigate/SKILL.md +0 -0
  283. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/loop/SKILL.md +0 -0
  284. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/migrate/SKILL.md +0 -0
  285. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/perf-analyze/SKILL.md +0 -0
  286. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/plan-impl/SKILL.md +0 -0
  287. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/pr-review/SKILL.md +0 -0
  288. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/refactor/SKILL.md +0 -0
  289. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/regex-help/SKILL.md +0 -0
  290. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/review/SKILL.md +0 -0
  291. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/security-review/SKILL.md +0 -0
  292. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/ship/SKILL.md +0 -0
  293. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/simplify/SKILL.md +0 -0
  294. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/skills/test-verify/SKILL.md +0 -0
  295. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock/whats_new.md +0 -0
  296. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock-acp.spec +0 -0
  297. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/drydock_terms.md +0 -0
  298. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/flake.lock +0 -0
  299. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/flake.nix +0 -0
  300. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/log_analyzer/__init__.py +0 -0
  301. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/log_analyzer/__main__.py +0 -0
  302. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/log_analyzer/analyzer.py +0 -0
  303. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/log_analyzer/cli.py +0 -0
  304. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/README.md +0 -0
  305. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/auto_test_loop.sh +0 -0
  306. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/backup.sh +0 -0
  307. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/bump_version.py +0 -0
  308. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/deploy_to_github.sh +0 -0
  309. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/discover_cli_tools.sh +0 -0
  310. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/install.sh +0 -0
  311. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/llm_balancer.py +0 -0
  312. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/monitor_swebench.sh +0 -0
  313. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/monitor_test_battery.sh +0 -0
  314. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/notify_release.py +0 -0
  315. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/overnight_agents_test.sh +0 -0
  316. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/prepare_release.py +0 -0
  317. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/publish_to_pypi.sh +0 -0
  318. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/telegram_bot.py +0 -0
  319. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/test_bank.sh +0 -0
  320. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/test_full.sh +0 -0
  321. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/test_smoke.sh +0 -0
  322. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/test_tui_path.py +0 -0
  323. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/tui_test.py +0 -0
  324. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/scripts/vllm_failover.sh +0 -0
  325. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/__init__.py +0 -0
  326. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/conftest.py +0 -0
  327. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_acp.py +0 -0
  328. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_agent_thought.py +0 -0
  329. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_bash.py +0 -0
  330. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_compact_session_updates.py +0 -0
  331. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_content.py +0 -0
  332. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_initialize.py +0 -0
  333. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_list_sessions.py +0 -0
  334. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_load_session.py +0 -0
  335. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_multi_session.py +0 -0
  336. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_new_session.py +0 -0
  337. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_proxy_setup_acp.py +0 -0
  338. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_read_file.py +0 -0
  339. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_search_replace.py +0 -0
  340. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_set_config_option.py +0 -0
  341. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_set_mode.py +0 -0
  342. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_set_model.py +0 -0
  343. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_tool_call_session_update.py +0 -0
  344. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_utils.py +0 -0
  345. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/acp/test_write_file.py +0 -0
  346. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/autocompletion/test_file_indexer.py +0 -0
  347. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/autocompletion/test_fuzzy.py +0 -0
  348. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
  349. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/autocompletion/test_path_completer_recursive.py +0 -0
  350. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/autocompletion/test_path_completion_controller.py +0 -0
  351. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
  352. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/autocompletion/test_slash_command_controller.py +0 -0
  353. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
  354. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/backend/__init__.py +0 -0
  355. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/backend/data/__init__.py +0 -0
  356. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/backend/data/fireworks.py +0 -0
  357. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/backend/data/mistral.py +0 -0
  358. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/backend/test_anthropic_adapter.py +0 -0
  359. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/backend/test_backend.py +0 -0
  360. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/backend/test_reasoning_adapter.py +0 -0
  361. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
  362. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
  363. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
  364. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
  365. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/test_bell_notifications.py +0 -0
  366. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/test_braille_renderer.py +0 -0
  367. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/test_clipboard.py +0 -0
  368. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/test_commands.py +0 -0
  369. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/test_copy_shortcuts.py +0 -0
  370. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/test_external_editor.py +0 -0
  371. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/test_no_markup_static.py +0 -0
  372. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/test_question_app.py +0 -0
  373. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/test_spinner.py +0 -0
  374. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/test_switching_mode.py +0 -0
  375. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/test_ui_clipboard_notifications.py +0 -0
  376. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
  377. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/test_ui_session_resume.py +0 -0
  378. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/test_ui_skill_dispatch.py +0 -0
  379. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/textual_ui/__init__.py +0 -0
  380. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/cli/textual_ui/test_session_picker.py +0 -0
  381. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/conftest.py +0 -0
  382. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_agents.py +0 -0
  383. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_auth_crypto.py +0 -0
  384. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_auth_github.py +0 -0
  385. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_config_load_dotenv.py +0 -0
  386. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_config_paths.py +0 -0
  387. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_config_resolution.py +0 -0
  388. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_file_logging.py +0 -0
  389. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_plan_session.py +0 -0
  390. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_proxy_setup.py +0 -0
  391. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_slug.py +0 -0
  392. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_telemetry_send.py +0 -0
  393. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_teleport_git.py +0 -0
  394. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_teleport_nuage.py +0 -0
  395. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_teleport_service.py +0 -0
  396. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_trusted_folders.py +0 -0
  397. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/core/test_utils.py +0 -0
  398. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/e2e/common.py +0 -0
  399. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/e2e/conftest.py +0 -0
  400. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/e2e/mock_server.py +0 -0
  401. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/e2e/test_cli_tui_onboarding.py +0 -0
  402. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/e2e/test_cli_tui_streaming.py +0 -0
  403. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
  404. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/mock/__init__.py +0 -0
  405. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/mock/mock_backend_factory.py +0 -0
  406. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/mock/mock_entrypoint.py +0 -0
  407. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/mock/utils.py +0 -0
  408. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/onboarding/test_run_onboarding.py +0 -0
  409. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/onboarding/test_ui_onboarding.py +0 -0
  410. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/session/test_session_loader.py +0 -0
  411. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/session/test_session_logger.py +0 -0
  412. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/session/test_session_migration.py +0 -0
  413. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/skills/conftest.py +0 -0
  414. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/skills/test_manager.py +0 -0
  415. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/skills/test_models.py +0 -0
  416. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/skills/test_parser.py +0 -0
  417. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
  418. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
  419. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
  420. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
  421. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
  422. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
  423. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
  424. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
  425. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
  426. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
  427. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
  428. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
  429. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
  430. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
  431. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
  432. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
  433. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
  434. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
  435. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
  436. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
  437. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
  438. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
  439. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
  440. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
  441. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
  442. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
  443. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
  444. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
  445. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
  446. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
  447. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
  448. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
  449. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
  450. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
  451. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
  452. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
  453. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
  454. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
  455. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
  456. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
  457. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
  458. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
  459. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
  460. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
  461. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
  462. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
  463. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
  464. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
  465. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
  466. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
  467. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
  468. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
  469. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
  470. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
  471. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
  472. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
  473. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
  474. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
  475. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
  476. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
  477. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/base_snapshot_test_app.py +0 -0
  478. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/conftest.py +0 -0
  479. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/snap_compare.py +0 -0
  480. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
  481. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
  482. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
  483. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
  484. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
  485. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
  486. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
  487. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
  488. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
  489. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
  490. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
  491. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
  492. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
  493. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
  494. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/stubs/fake_backend.py +0 -0
  495. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/stubs/fake_client.py +0 -0
  496. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/stubs/fake_tool.py +0 -0
  497. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_agent_auto_compact.py +0 -0
  498. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_agent_backend.py +0 -0
  499. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_agent_observer_streaming.py +0 -0
  500. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_agent_stats.py +0 -0
  501. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_agent_tasks.py +0 -0
  502. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_agent_tool_call.py +0 -0
  503. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_agents.py +0 -0
  504. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_bank_build.py +0 -0
  505. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_bank_debug.py +0 -0
  506. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_bank_multiagent.py +0 -0
  507. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_bank_prd.py +0 -0
  508. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_bank_prd_extended.py +0 -0
  509. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_bank_tools.py +0 -0
  510. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_bank_update.py +0 -0
  511. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_build_projects.py +0 -0
  512. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_cli_programmatic_preload.py +0 -0
  513. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_current_bugs.py +0 -0
  514. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_drydock_regression.py +0 -0
  515. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_drydock_tasks.py +0 -0
  516. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_full_regression.py +0 -0
  517. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_history_manager.py +0 -0
  518. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_integration.py +0 -0
  519. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_loop_detection.py +0 -0
  520. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_message_id.py +0 -0
  521. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_message_merging.py +0 -0
  522. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_middleware.py +0 -0
  523. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_multi_agent.py +0 -0
  524. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_real_failures.py +0 -0
  525. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_real_issues.py +0 -0
  526. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_real_workflow.py +0 -0
  527. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_reasoning_content.py +0 -0
  528. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_system_prompt.py +0 -0
  529. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_tagged_text.py +0 -0
  530. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_ui_external_editor.py +0 -0
  531. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_ui_input_history.py +0 -0
  532. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_user_issues.py +0 -0
  533. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/test_workloads.py +0 -0
  534. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/testbank_helpers.py +0 -0
  535. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/tools/test_ask_user_question.py +0 -0
  536. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/tools/test_bash.py +0 -0
  537. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/tools/test_exit_plan_mode.py +0 -0
  538. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/tools/test_grep.py +0 -0
  539. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/tools/test_invoke_context.py +0 -0
  540. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/tools/test_manager_get_tool_config.py +0 -0
  541. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/tools/test_mcp.py +0 -0
  542. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/tools/test_mcp_sampling.py +0 -0
  543. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/tools/test_task.py +0 -0
  544. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/tools/test_ui_bash_execution.py +0 -0
  545. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/tools/test_webfetch.py +0 -0
  546. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/tools/test_websearch.py +0 -0
  547. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
  548. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
  549. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/update_notifier/test_do_update.py +0 -0
  550. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
  551. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/update_notifier/test_github_update_gateway.py +0 -0
  552. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
  553. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/update_notifier/test_ui_update_notification.py +0 -0
  554. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/update_notifier/test_update_use_case.py +0 -0
  555. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/tests/update_notifier/test_whats_new.py +0 -0
  556. {drydock_cli-2.6.22 → drydock_cli-2.6.25}/uv.lock +0 -0
@@ -0,0 +1 @@
1
+ 199791
@@ -201,3 +201,4 @@ tests/playground/*
201
201
  .
202
202
  logs/
203
203
  test_bank_results/
204
+ .pause_auto_release
@@ -4,17 +4,22 @@
4
4
 
5
5
  Drydock is a local CLI coding agent (fork of mistral-vibe, Apache 2.0).
6
6
  - **Repo:** https://github.com/fbobe321/drydock
7
- - **PyPI:** https://pypi.org/project/drydock-cli/ (v2.5.0)
8
- - **Goal:** Reliable TUI coding agent with local LLMs. PRD-driven project building + SWE-bench bug fixing.
7
+ - **PyPI:** https://pypi.org/project/drydock-cli/ (v2.6.23 — v2.6.24 built but unreleased)
8
+ - **Goal:** Reliable TUI coding agent with local LLMs. PRD-driven project building.
9
9
  - **Hardware:** 2x RTX 4060 Ti 16GB, Gemma 4 26B MoE (A4B) via vLLM Docker at localhost:8000
10
10
  - **Server:** remus (Ubuntu 22.04, user: bobef)
11
11
  - **Active model:** Gemma 4 26B-A4B-it-AWQ-4bit (only 4B active params, ~70 tok/s)
12
- - **TUI build tests:** 303/320 pass --help (94%) BUT --help IS MEANINGLESS
13
- - **TUI real functional tests:** 35/63 pass (56%) — the honest number
14
- - **SWE-bench:** 70% file match (v3 baseline)
12
+ - **The honest test:** `scripts/user_pain_test.py` user-pain harnesspass means real
13
+ user-perceptible behaviour, not tool-call counts. See `scripts/run_pain_suite.sh`
14
+ for the 10-project core set.
15
+ - **OLD harnesses you should NOT trust:** `scripts/tui_test.py` and
16
+ `core_tests_real.sh` count tool calls and `--help` and miss the things users
17
+ actually experience (loops the model ignores, hallucinated tool names that
18
+ hang the session, models that declare done with broken code, 2-minute
19
+ generation pauses). They produce passing scores while real usage fails.
15
20
  - **Priority:** TUI experience first. Fix drydock bugs, don't simplify PRDs.
16
21
  - **370 PRDs** at /data3/drydock_test_projects/ — the benchmark suite
17
- - **Current version:** v2.5.6 (PyPI + GitHub + user's env)
22
+ - **Current version:** v2.6.23 on PyPI / v2.6.24 built locally (unreleased)
18
23
 
19
24
  ## Build & Test
20
25
 
@@ -256,37 +261,217 @@ v3 is a from-scratch rewrite using nano-claude-code as foundation. 4 core files,
256
261
  - ✅ Docker-based model serving (vLLM + Gemma 4)
257
262
  - ✅ Multi-backend SWE-bench harness (v2/devstral + v3/gemma4)
258
263
  - ✅ Thinking token filtering (Gemma 4 `<|channel>` leak)
264
+ - ✅ **User-pain harness** (`scripts/user_pain_test.py`) — drives real TUI
265
+ via pexpect, watches live session log, types `STOP` interrupts,
266
+ judges on user-perceptible criteria
267
+ - ✅ **Multi-PRD pain suite** (`scripts/run_pain_suite.sh`) — 10 core
268
+ projects through the user-pain harness
269
+ - ✅ **`_check_main_module_entry`** in write_file.py — catches
270
+ `__main__.py` files that import `main` but never call it (the codec
271
+ silent-exit bug)
272
+ - ✅ **`_check_missing_sibling_imports`** in write_file.py — catches
273
+ `from .cli import CLI` when `cli.py` doesn't exist on disk yet (the
274
+ minivc unimportable-package bug)
275
+ - ✅ **Escalating dedup message** in write_file.py — 2nd+ identical-content
276
+ write to a path returns the actual current directory listing plus
277
+ concrete next-action suggestions, instead of abstract "move to next file"
278
+ - ✅ **Loop-detection wiring** in agent_loop.py — `_check_tool_call_repetition()`
279
+ was defined but never called; now fires from `_handle_tool_response()`
280
+ and injects an advisory nudge via `_inject_system_note()`, rate-limited
281
+ every 3 turns
282
+ - ✅ **`_truncate_old_tool_results`** in agent_loop.py — proactive
283
+ shrinkage of stale tool results before each LLM call; keeps the last
284
+ 6 in full, truncates older ones > 800 bytes to head + footer + size
285
+ marker; idempotent
286
+ - ✅ **`_task_manager.py` rename** — TaskCreate/Update/List were
287
+ duplicates of the `todo` tool that confused Gemma 4 into hanging.
288
+ Underscore prefix excludes them from tool discovery
289
+ - ✅ **Trust dialog auto-dismissal** in user_pain_test.py
290
+ - ✅ **Pause flags** for both `auto_release.sh` and `watchdog.sh` so
291
+ manual debugging doesn't get its work overwritten
259
292
 
260
293
  **Legal note:** All patterns are standard design concepts implemented from scratch. No proprietary code copied.
261
294
 
262
295
  ## Key Learnings
263
296
 
264
- 1. **Test the TUI, not headless.** Headless passes mask real bugs. TUI has different code paths (streaming, approval, render_path_prompt). ALL testing through TUI via pexpect.
265
- 2. **Use PRDs for testing.** Concrete PRDs with expected files and `--help` give clear pass/fail. 100-project suite proved TUI works (98%).
266
- 3. **Scaffold per model.** Weaker models need more guardrails (non-streaming, fewer tools, simpler prompts). As models improve, remove scaffolding. The code should get simpler over time.
267
- 4. **Streaming breaks Gemma 4 tool calls.** Streaming accumulates JSON chunk-by-chunk → empty args. Non-streaming gets complete response → works perfectly. Root cause of weeks of TUI failures.
268
- 5. **Fewer tools = better for local models.** Gemma 4 wasted 64 turns on task_create/task_update. Disabling non-essential tools eliminated the loop.
269
- 6. **Simple prompts win.** The 125-line cli.md with phases/delegation confused Gemma 4. The 20-line gemma4.md ("ACT IMMEDIATELY") works.
270
- 7. AGENTS.md essential for devstral (loops without it), not needed for Gemma 4
271
- 8. Circuit breaker was net negative — removed entirely
272
- 9. Loop detection should guide, never stop (retrospection > hardcoded nudges)
273
- 10. Clean rewrites beat incremental fixes v3 (~750 lines) outperforms v2 (~5000+ lines) on SWE-bench
274
- 11. Model choice matters more than agent complexity — Gemma 4 MoE gives 3-4x speed
275
- 12. Docker-based model serving (vLLM) is reliable easier restarts, GPU management
276
- 13. Auto-read on failed edit automatically show the model the real file content
277
- 14. Temperature bump on loopsforce model to explore different paths
278
- 15. Failed-approach accumulator prevent re-trying strategies after pruning/compaction
279
- 16. PRD complexity must match model capability too many files/features causes timeout
297
+ ### Most-recent (debugging the user's worst session, April 2026)
298
+
299
+ 1. **Test-harness counts are not user pain.** `tui_test.py` and
300
+ `core_tests_real.sh` reported 80% pass while real users saw drydock
301
+ loop, hang, and produce broken code. The harnesses were structurally
302
+ incapable of catching what users experience because they measure
303
+ tool-call counts and `--help` exit codes, not progress. Build pass
304
+ criteria around user-perceptible state instead. See `user_pain_test.py`.
305
+ 2. **Gemma 4 ignores advisory nudges.** The model received the dedup
306
+ message ("File already has this exact content. Move to the NEXT file."),
307
+ the loop-detection system note, the missing-import warning, AND a
308
+ user-typed `STOP` interrupt its own thinking tokens ACKNOWLEDGED
309
+ the loop ("The user is pointing out that I am in a loop... I should
310
+ move to the next file")and kept writing the same file 10 times
311
+ anyway. The advisory-only rule is correct in principle, but Gemma 4
312
+ cannot reliably respond to it. Hard blocks on pure no-op duplicates
313
+ may eventually be necessary.
314
+ 3. **The auto_release.sh cron silently reverts site-packages every 6 hours.**
315
+ It runs at 0/6/12/18, builds a wheel from `/data3/drydock`, uploads to
316
+ PyPI, and `pip install --force-reinstall`s into the user's env. Direct
317
+ edits to `site-packages/drydock/...` disappear at the next cron tick.
318
+ Pause via `touch /data3/drydock/.pause_auto_release`.
319
+ 4. **`/data3/drydock` is in `sys.path`, but site-packages comes first.**
320
+ `import drydock; print(drydock.__file__)` lies depending on cwd. From
321
+ `/data3/drydock` it reports the source tree (cwd is `""` at index 0).
322
+ From any project cwd it reports site-packages. **Always validate
323
+ imports from a neutral cwd.**
324
+ 5. **PRDs get contaminated across sessions.** The model edits `PRD.md`
325
+ during a session (adds "✅ Completed" status tables, chat-style
326
+ filler text). The next test run sees a "completed" PRD and either
327
+ declares done immediately or hallucinates fix actions. Snapshot
328
+ `PRD.master.md` before each run; the harness restores it automatically.
329
+ 6. **Hallucinated tool names hang the session.** The model called
330
+ `ralph_repo_index({"directory": "."})` — a tool that doesn't exist.
331
+ `_build_tool_call_events()` had `if tool_class is None: continue` which
332
+ silently dropped the call. Drydock waited forever for a tool result
333
+ that never came. `resolve_tool_calls()` correctly emits a `FailedToolCall`
334
+ downstream — both code paths exist; verify which one the model is hitting.
335
+ 7. **The "Trust this folder?" dialog blocks all input.** Drydock pops a
336
+ blocking modal the first time it opens an unfamiliar directory. The
337
+ harness used to type the user prompt blindly into it; the dialog ate
338
+ the keystrokes and drydock waited forever. The fix: detect the dialog
339
+ in pexpect output, send Left+Enter to answer Yes. The harness now does
340
+ this. The CLI should never strand users on a modal dialog.
341
+ 8. **Context-bloat eats first-turn latency.** Drydock includes the system
342
+ prompt + 24 tool definitions + AGENTS.md auto-injection + user message
343
+ on every turn. With Gemma 4 `thinking="high"` the first response can
344
+ take 60–130 seconds even on a small project, because the model is
345
+ generating ~1000 thinking tokens at ~70 tok/s. `auto_compact_threshold`
346
+ defaults to 200K (higher than Gemma 4's 131K max context) so it never
347
+ fires. Lower it per-model, and rely on `_truncate_old_tool_results()`
348
+ to shrink stale `read_file` outputs proactively.
349
+ 9. **`task_manager.py` (TaskCreate/Update/List) confused Gemma 4** — the
350
+ model mixed it up with the existing `todo` tool, called `task_update`
351
+ on a `todo` ID, hung waiting on the response. Renamed to
352
+ `_task_manager.py` so the auto-discovery loop in `tools/manager.py`
353
+ skips it (it skips files starting with `_`). The classes are still
354
+ importable for tests via the new module name.
355
+ 10. **Variance is the rule, not the exception.** Same code, same prompt,
356
+ same model: codec passed in run 1 of the suite and triggered all 3
357
+ pain criteria in run 2. Always state both numbers honestly. Don't
358
+ cherry-pick the run that worked.
359
+
360
+ ### Older but still relevant
361
+
362
+ 11. **Test the TUI, not headless.** Headless passes mask real bugs. TUI
363
+ has different code paths (streaming, approval, render_path_prompt).
364
+ ALL testing through TUI via pexpect.
365
+ 12. **Use PRDs for testing.** Concrete PRDs with expected files give
366
+ clear pass/fail. The 370-PRD suite is at /data3/drydock_test_projects/.
367
+ 13. **Scaffold per model.** Weaker models need more guardrails
368
+ (non-streaming, fewer tools, simpler prompts). As models improve,
369
+ remove scaffolding.
370
+ 14. **Streaming breaks Gemma 4 tool calls.** Non-streaming gets the
371
+ complete response so JSON args are valid. Set `enable_streaming=False`
372
+ when model is Gemma 4.
373
+ 15. **Fewer tools = better for local models.** 24 builtins is already a
374
+ lot for Gemma 4. The auto-injected list of 39 user-installed CLI
375
+ tools makes it worse.
376
+ 16. **Simple prompts win.** The 125-line `cli.md` with phases/delegation
377
+ confused Gemma 4. The 20-line `gemma4.md` ("ACT IMMEDIATELY") works.
378
+ 17. **AGENTS.md essential for devstral, not needed for Gemma 4.**
379
+ 18. **Circuit breaker was net negative — removed entirely.**
380
+ 19. **Loop detection should guide, never stop.** Per the user's rule.
381
+ See learning #2 for the limit of this rule.
382
+ 20. **Auto-read on failed edit, temperature bump on loops, failed-approach
383
+ accumulator** — additive context techniques that help.
280
384
 
281
385
  ## Testing
282
386
 
283
- ### TUI Test Harness
284
- - **Script:** `scripts/tui_test.py` — pexpect-based, drives the REAL TUI binary
285
- - **Real test runner:** `run_real_tests.sh` functional testing, not just --help
286
- - **Results:** `real_test_results.txt` honest pass/fail with functional verification
287
- - **370 PRDs** at `/data3/drydock_test_projects/` covering CLI tools, integration, edge cases, best practices
387
+ ### Use `scripts/user_pain_test.py` — anything else lies
388
+
389
+ The `user_pain_test.py` harness is the only test infrastructure that catches what
390
+ real users experience. Older harnesses (`tui_test.py`, `core_tests_real.sh`,
391
+ `run_real_tests.sh`) measure tool counts and `--help` exit codes; they pass
392
+ while real users see loops and hangs.
393
+
394
+ **How it works:**
395
+ - Drives the real `drydock` TUI via pexpect (no headless mode)
396
+ - Sends a vague user-style prompt ("review the PRD and build the package")
397
+ - Polls the live `~/.vibe/logs/session/session_<id>/messages.jsonl` in parallel
398
+ - Watches for write loops, search_replace cascades, hallucinated-tool hangs
399
+ - Types simulated `STOP` interrupts when loops are detected, then tracks
400
+ whether the model OBEYS them
401
+ - Distinguishes three end-states:
402
+ - **Active turn** (any new message in the last 120s) → keep going
403
+ - **Done** (last assistant has text content with no tool call) → grace 30s, then PASS
404
+ - **Dead silence** (no new messages of any kind for 120s) → FAIL
405
+ - Resets the cwd between runs (restores `PRD.md` from `PRD.master.md` if present,
406
+ wipes the package dir and stale data dirs)
407
+ - Auto-handles the "Trust this folder?" dialog drydock pops on new directories
408
+
409
+ **Pass criteria (ALL must hold):**
410
+ 1. NO write loops (≥3 identical-content writes to a path)
411
+ 2. NO ignored user `STOP` interrupts
412
+ 3. NO search_replace failure cascade (≥3 in a row)
413
+ 4. `python3 -m <pkg> --help` actually works
414
+ 5. Session under `MAX_SESSION_SECONDS` (default 600)
415
+
416
+ **Run a single project:**
288
417
 
289
- ### Test Levels
418
+ ```bash
419
+ PYTHONUNBUFFERED=1 python3 -u scripts/user_pain_test.py \
420
+ --cwd /data3/test_drydock \
421
+ --prompt "review the PRD and get started" \
422
+ --pkg doc_qa_system
423
+ ```
424
+
425
+ **Run the 10-project core suite:**
426
+
427
+ ```bash
428
+ bash scripts/run_pain_suite.sh
429
+ ```
430
+
431
+ **Real-world results from the harness (after recent fixes):**
432
+ - 4/4 on the small suite (roman_converter, prime_tool, todo_list, codec)
433
+ with real functional verification: codec round-trips work, todo_list
434
+ workflow works, prime check works.
435
+ - Variance is real — codec passed in one suite run and FAILED with a
436
+ 3-criteria loop in the next. Same code, same prompt. Document this when
437
+ reporting.
438
+
439
+ ### Fixture: `tests/fixtures/doc_qa_system_prd.md`
440
+
441
+ The PRD that originally exposed the user's worst session (10 identical
442
+ `__init__.py` writes, hallucinated `ralph_repo_index` tool, contaminated
443
+ PRD across sessions, 13-min runtime) is checked in. Use it as the canary
444
+ case for any harness work.
445
+
446
+ ### Two cron pause flags you should know about
447
+
448
+ Both crons silently overwrite work mid-debug. Pause them when iterating:
449
+
450
+ ```bash
451
+ touch /data3/drydock_test_projects/.pause_watchdog # stops watchdog.sh
452
+ touch /data3/drydock/.pause_auto_release # stops auto_release.sh
453
+ ```
454
+
455
+ `auto_release.sh` runs at 0/6/12/18, builds a wheel from `/data3/drydock`,
456
+ uploads to PyPI, and `pip install --force-reinstall`s it into the user's env.
457
+ That overwrites any direct site-packages edits. **If your fix doesn't
458
+ survive the next cron run, it's because you only edited `/data3/drydock` —
459
+ auto_release rebuilds from there but ALSO replaces site-packages.** Commit
460
+ your fix to source AND verify it landed via `git log --oneline -5` before
461
+ expecting persistence.
462
+
463
+ ### Why direct site-packages edits keep disappearing
464
+
465
+ `/home/bobef/miniforge3/envs/drydock/lib/python3.14/site-packages` comes
466
+ before `/data3/drydock` in `sys.path` from a project cwd, even though the
467
+ `_drydock.pth` file adds `/data3/drydock`. So a sanity check from
468
+ `/data3/drydock` (`import drydock; print(drydock.__file__)`) lies — it
469
+ reports `/data3/drydock/drydock/__init__.py` because cwd-`""` is at index 0.
470
+ From `/data3/drydock_test_projects/X` it reports the site-packages path.
471
+ **Always test imports from a neutral cwd**, OR commit to source AND let
472
+ auto_release rebuild.
473
+
474
+ ### Test Levels (kept for reference, but the user-pain harness covers all of them)
290
475
  1. **Build test (--help):** package runs — MEANINGLESS alone
291
476
  2. **Functional test:** PRD test cases verified with correct output — THE REAL TEST
292
477
  3. **Acceptance test:** specific expected outputs verified
@@ -298,6 +483,14 @@ v3 is a from-scratch rewrite using nano-claude-code as foundation. 4 core files,
298
483
  - Safety mechanisms must be ADVISORY not BLOCKING
299
484
  - NEVER add circuit breakers that prevent legitimate work
300
485
  - The model should be able to answer questions without being forced to edit files
486
+ - **NEVER trust an old harness's pass result.** If `tui_test.py` or
487
+ `core_tests_real.sh` says PASS, run the same project through
488
+ `user_pain_test.py` to confirm. The old harnesses count `--help` and
489
+ silently miss the things users hate.
490
+ - **Always reset PRDs between runs.** The model edits PRD.md (adds
491
+ "✅ Completed" status tables, chat-style filler) and contaminates
492
+ subsequent test runs. The harness restores from `PRD.master.md`
493
+ automatically if present.
301
494
 
302
495
  ## When Compacting
303
496
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 2.6.22
3
+ Version: 2.6.25
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
@@ -1079,6 +1079,33 @@ class AgentLoop:
1079
1079
  f"Do NOT run another bash command until you have fixed the code."
1080
1080
  )
1081
1081
 
1082
+ # RECOVERY: hard-blocked duplicate write_file. When write_file raises
1083
+ # "BLOCKED: ... has been called N times with IDENTICAL content", the
1084
+ # model has a history full of identical no-op writes. Prune those from
1085
+ # message history so the model's next turn sees a cleaner context and
1086
+ # is less likely to re-trigger the same loop.
1087
+ #
1088
+ # Pruning is safe here because the duplicates are by definition no-ops
1089
+ # against the file on disk — deleting the history preserves actual
1090
+ # state. We keep the most recent write attempt (which is the one that
1091
+ # just got blocked) so the model sees the error.
1092
+ if (
1093
+ tool_call.tool_name == "write_file"
1094
+ and "BLOCKED:" in str(exc)
1095
+ and "IDENTICAL content" in str(exc)
1096
+ ):
1097
+ try:
1098
+ target_path = ""
1099
+ try:
1100
+ wf_args = json.loads(tool_call.raw_arguments or "{}")
1101
+ target_path = wf_args.get("path", "")
1102
+ except (json.JSONDecodeError, AttributeError):
1103
+ pass
1104
+ if target_path:
1105
+ self._prune_duplicate_writes(target_path)
1106
+ except Exception as prune_exc:
1107
+ logger.debug("Prune after block failed: %s", prune_exc)
1108
+
1082
1109
  yield ToolResultEvent(
1083
1110
  tool_name=tool_call.tool_name,
1084
1111
  tool_class=tool_call.tool_class,
@@ -1125,6 +1152,18 @@ class AgentLoop:
1125
1152
  )
1126
1153
  )
1127
1154
 
1155
+ # Advisory loop detection: inject nudge when the model keeps repeating
1156
+ # the same call. Never blocks, never stops — just steers the model toward
1157
+ # a different approach. Catches the 28-identical-bash-calls failure mode.
1158
+ try:
1159
+ repetition = self._check_tool_call_repetition()
1160
+ if repetition:
1161
+ nudge = self._build_repetition_nudge(repetition, tool_call)
1162
+ if nudge:
1163
+ self._inject_system_note(nudge)
1164
+ except Exception as e:
1165
+ logger.debug("Loop detection check failed: %s", e)
1166
+
1128
1167
  self.telemetry_client.send_tool_call_finished(
1129
1168
  tool_call=tool_call,
1130
1169
  agent_profile_name=self.agent_profile.name,
@@ -1133,6 +1172,169 @@ class AgentLoop:
1133
1172
  result=result,
1134
1173
  )
1135
1174
 
1175
+ def _build_repetition_nudge(
1176
+ self, signal: str, tool_call: ResolvedToolCall
1177
+ ) -> str | None:
1178
+ """Build an advisory nudge for the model when a loop is detected.
1179
+
1180
+ Returns None if the tool call was already nudged recently (prevents
1181
+ spamming the model with the same message on every turn).
1182
+ """
1183
+ # Rate-limit: don't nudge more than once every 3 turns for the same tool
1184
+ last_nudge_turn = getattr(self, "_last_nudge_turn", -10)
1185
+ current_turn = len(self.messages)
1186
+ if current_turn - last_nudge_turn < 3:
1187
+ return None
1188
+ self._last_nudge_turn = current_turn
1189
+
1190
+ tool_name = tool_call.tool_name
1191
+ if signal == "FORCE_STOP":
1192
+ return (
1193
+ f"You have called `{tool_name}` with the SAME arguments 8+ times "
1194
+ f"and gotten the same result each time. This is a dead end. "
1195
+ f"You MUST change your approach:\n"
1196
+ f"- For bash: if output is empty, read the source files to find the bug — "
1197
+ f" don't just re-run the command\n"
1198
+ f"- For write_file/search_replace: if the file already has your content, "
1199
+ f" move on to the NEXT file\n"
1200
+ f"- If stuck, inspect the actual file contents with read_file before editing"
1201
+ )
1202
+ if signal.startswith("WARNING|"):
1203
+ stuck_tool = signal.split("|", 1)[1] or tool_name
1204
+ if stuck_tool == "bash":
1205
+ return (
1206
+ f"You have run very similar `bash` commands several times in a row. "
1207
+ f"If the output is empty or unchanged, the command is not the problem — "
1208
+ f"the CODE is. Use read_file to inspect the source, then write_file or "
1209
+ f"search_replace to fix the bug. Do not re-run the same command again."
1210
+ )
1211
+ if stuck_tool in ("write_file", "search_replace"):
1212
+ return (
1213
+ f"You have written the same file multiple times in a row. "
1214
+ f"Move to the NEXT file in your plan. If no next file, run the code "
1215
+ f"with bash to verify it works."
1216
+ )
1217
+ return (
1218
+ f"You have called `{stuck_tool}` several times in a row with similar "
1219
+ f"arguments. Try a different tool or a different approach."
1220
+ )
1221
+ return None
1222
+
1223
+ def _prune_duplicate_writes(self, target_path: str) -> None:
1224
+ """Remove assistant-write_file / tool-result pairs for a looping path.
1225
+
1226
+ Called after the hard-block fires on a write_file call. By that point
1227
+ the message history contains 3+ identical no-op write attempts to
1228
+ `target_path`, which bloats context and keeps nudging the model back
1229
+ toward the same action. Pruning them out gives the next turn a
1230
+ cleaner view.
1231
+
1232
+ We keep:
1233
+ - the system prompt + first user message (they anchor the task)
1234
+ - the MOST RECENT write_file+result pair for this path (the one
1235
+ that just triggered the block — its error message is what the
1236
+ model needs to see)
1237
+ - everything unrelated to target_path
1238
+
1239
+ We drop:
1240
+ - older write_file(path=target_path) assistant messages
1241
+ - their matching tool result messages
1242
+
1243
+ This only prunes write_file calls where the path matches exactly and
1244
+ where the write_file is the ONLY tool call in that assistant message
1245
+ (to avoid removing unrelated calls in a multi-tool turn).
1246
+ """
1247
+ if len(self.messages) < 4:
1248
+ return
1249
+
1250
+ # Find indices of all write_file assistant messages targeting this path
1251
+ target_indices: list[int] = []
1252
+ for i, msg in enumerate(self.messages):
1253
+ if msg.role != Role.assistant:
1254
+ continue
1255
+ tcs = msg.tool_calls or []
1256
+ if len(tcs) != 1:
1257
+ continue
1258
+ fn = tcs[0].function
1259
+ if not fn or fn.name != "write_file":
1260
+ continue
1261
+ try:
1262
+ args = json.loads(fn.arguments or "{}")
1263
+ except (json.JSONDecodeError, AttributeError):
1264
+ continue
1265
+ if args.get("path", "") == target_path:
1266
+ target_indices.append(i)
1267
+
1268
+ if len(target_indices) < 2:
1269
+ return
1270
+
1271
+ # Keep the MOST RECENT one; prune the rest (and their tool result)
1272
+ to_drop: set[int] = set()
1273
+ for idx in target_indices[:-1]:
1274
+ to_drop.add(idx)
1275
+ # The matching tool result is the next tool message
1276
+ for j in range(idx + 1, min(idx + 3, len(self.messages))):
1277
+ if self.messages[j].role == Role.tool:
1278
+ to_drop.add(j)
1279
+ break
1280
+
1281
+ if not to_drop:
1282
+ return
1283
+
1284
+ kept = [m for i, m in enumerate(self.messages) if i not in to_drop]
1285
+ logger.info(
1286
+ "Pruning %d message(s) from write loop on %s (history now %d → %d)",
1287
+ len(to_drop), target_path, len(self.messages), len(kept),
1288
+ )
1289
+ self.messages.reset(kept)
1290
+
1291
+ def _truncate_old_tool_results(self) -> None:
1292
+ """Shrink old verbose tool results before they bloat context.
1293
+
1294
+ For local models like Gemma 4 the per-turn cost grows quadratically
1295
+ with context size, so a session with 30+ messages and a few large
1296
+ read_file results becomes unusable. This method:
1297
+
1298
+ - Keeps the system prompt and the FIRST user message verbatim
1299
+ (instructions that should not be lost).
1300
+ - Keeps the last KEEP_RECENT tool results in full.
1301
+ - Truncates any older tool result whose content exceeds the
1302
+ per-result soft cap to a head + footer + size marker.
1303
+
1304
+ Runs every turn but is a no-op when nothing exceeds the caps.
1305
+ Truncation is in-place and idempotent.
1306
+ """
1307
+ KEEP_RECENT = 6 # last N tool messages stay full
1308
+ SOFT_CAP_BYTES = 800 # tool result longer than this gets shrunk
1309
+ HEAD_BYTES = 400 # bytes kept from the head
1310
+ TAIL_BYTES = 100 # bytes kept from the tail
1311
+
1312
+ if len(self.messages) < KEEP_RECENT + 4:
1313
+ return
1314
+
1315
+ # Index of every tool message
1316
+ tool_idxs = [
1317
+ i for i, m in enumerate(self.messages) if m.role == Role.tool
1318
+ ]
1319
+ if len(tool_idxs) <= KEEP_RECENT:
1320
+ return
1321
+
1322
+ # Truncate everything except the last KEEP_RECENT
1323
+ for idx in tool_idxs[:-KEEP_RECENT]:
1324
+ msg = self.messages[idx]
1325
+ content = str(msg.content or "")
1326
+ if len(content) <= SOFT_CAP_BYTES:
1327
+ continue
1328
+ # Idempotent guard — already truncated by us
1329
+ if "[…truncated " in content and "bytes…]" in content:
1330
+ continue
1331
+ head = content[:HEAD_BYTES]
1332
+ tail = content[-TAIL_BYTES:]
1333
+ removed = len(content) - HEAD_BYTES - TAIL_BYTES
1334
+ msg.content = (
1335
+ f"{head}\n[…truncated {removed} bytes…]\n{tail}"
1336
+ )
1337
+
1136
1338
  def _sanitize_message_ordering(self) -> None:
1137
1339
  """Fix any role ordering violations before sending to vLLM/Mistral.
1138
1340
 
@@ -1142,6 +1344,10 @@ class AgentLoop:
1142
1344
 
1143
1345
  This runs as a safety net before every LLM call.
1144
1346
  """
1347
+ # Proactive context shrinkage runs first so the LLM call sees the
1348
+ # smaller payload.
1349
+ self._truncate_old_tool_results()
1350
+
1145
1351
  if not self.messages:
1146
1352
  return
1147
1353