drydock-cli 2.7.17__tar.gz → 2.7.19__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 (672) hide show
  1. drydock_cli-2.7.19/.auto_release.lock +1 -0
  2. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/PKG-INFO +1 -1
  3. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/llm/format.py +50 -5
  4. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/read_file.py +38 -12
  5. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/search_replace.py +40 -0
  6. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/write_file.py +13 -0
  7. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/pyproject.toml +1 -1
  8. drydock_cli-2.7.19/tests/test_write_file_missing_path.py +75 -0
  9. drydock_cli-2.7.19/tests/tools/test_read_file_dedup_reembed.py +136 -0
  10. drydock_cli-2.7.19/tests/tools/test_read_file_limit_truncation.py +76 -0
  11. drydock_cli-2.7.19/tests/tools/test_search_replace_empty_content.py +90 -0
  12. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/trip_log.md +111 -0
  13. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/uv.lock +1 -1
  14. drydock_cli-2.7.17/.auto_release.lock +0 -1
  15. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.claude/scheduled_tasks.lock +0 -0
  16. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.github/CODEOWNERS +0 -0
  17. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
  18. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  19. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  20. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.github/workflows/build-and-upload.yml +0 -0
  21. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.github/workflows/ci.yml +0 -0
  22. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.github/workflows/issue-labeler.yml +0 -0
  23. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.github/workflows/release.yml +0 -0
  24. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.gitignore +0 -0
  25. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.pre-commit-config.yaml +0 -0
  26. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.python-version +0 -0
  27. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.typos.toml +0 -0
  28. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.vscode/extensions.json +0 -0
  29. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.vscode/launch.json +0 -0
  30. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/.vscode/settings.json +0 -0
  31. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/AGENTS.md +0 -0
  32. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/Admiral.md +0 -0
  33. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/BASELINE_412.md +0 -0
  34. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/CHANGELOG.md +0 -0
  35. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/CLAUDE.md +0 -0
  36. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/CONTRIBUTING.md +0 -0
  37. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/DEPLOYMENT.md +0 -0
  38. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/Drydock_rebrand.md +0 -0
  39. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/LICENSE +0 -0
  40. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/MODEL_SHORTCOMINGS.md +0 -0
  41. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/NOTICE +0 -0
  42. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/OVERNIGHT_PROGRESS.md +0 -0
  43. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/OVERNIGHT_REPORT_2026_04_13.md +0 -0
  44. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/PRD.md +0 -0
  45. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/README.md +0 -0
  46. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/action.yml +0 -0
  47. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/README.md +0 -0
  48. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results1.tsv +0 -0
  49. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results13.tsv +0 -0
  50. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results14.tsv +0 -0
  51. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results15.tsv +0 -0
  52. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results16.tsv +0 -0
  53. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results17.tsv +0 -0
  54. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results18.tsv +0 -0
  55. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results19.tsv +0 -0
  56. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results2.tsv +0 -0
  57. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results20.tsv +0 -0
  58. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results3.tsv +0 -0
  59. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results4.tsv +0 -0
  60. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results5.tsv +0 -0
  61. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results6.tsv +0 -0
  62. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results7.tsv +0 -0
  63. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results8.tsv +0 -0
  64. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results9.tsv +0 -0
  65. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/baseline_history/results_evolved_v1.tsv +0 -0
  66. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/distribution/zed/LICENSE +0 -0
  67. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/distribution/zed/extension.toml +0 -0
  68. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/distribution/zed/icons/mistral_vibe.svg +0 -0
  69. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/docs/README.md +0 -0
  70. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/docs/acp-setup.md +0 -0
  71. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/docs/proxy-setup.md +0 -0
  72. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/__init__.py +0 -0
  73. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/acp/__init__.py +0 -0
  74. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/acp/acp_agent_loop.py +0 -0
  75. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/acp/acp_logger.py +0 -0
  76. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/acp/entrypoint.py +0 -0
  77. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/acp/tools/__init__.py +0 -0
  78. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/acp/tools/base.py +0 -0
  79. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/acp/tools/builtins/bash.py +0 -0
  80. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/acp/tools/builtins/read_file.py +0 -0
  81. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/acp/tools/builtins/search_replace.py +0 -0
  82. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/acp/tools/builtins/todo.py +0 -0
  83. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/acp/tools/builtins/write_file.py +0 -0
  84. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/acp/tools/session_update.py +0 -0
  85. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/acp/utils.py +0 -0
  86. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/__init__.py +0 -0
  87. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/detectors.py +0 -0
  88. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/detectors_proposed.py +0 -0
  89. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/history.py +0 -0
  90. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/interventions.py +0 -0
  91. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/llm_analyzer.py +0 -0
  92. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/metrics.py +0 -0
  93. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/opus_escalator.py +0 -0
  94. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/persistence.py +0 -0
  95. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/policy.py +0 -0
  96. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/proposer.py +0 -0
  97. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/stager.py +0 -0
  98. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/task_classifier.py +0 -0
  99. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/tuning.py +0 -0
  100. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/validator.py +0 -0
  101. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/admiral/worker.py +0 -0
  102. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/__init__.py +0 -0
  103. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/autocompletion/__init__.py +0 -0
  104. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/autocompletion/base.py +0 -0
  105. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/autocompletion/path_completion.py +0 -0
  106. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/autocompletion/slash_command.py +0 -0
  107. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/cli.py +0 -0
  108. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/clipboard.py +0 -0
  109. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/commands.py +0 -0
  110. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/entrypoint.py +0 -0
  111. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/history_manager.py +0 -0
  112. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
  113. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
  114. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
  115. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/terminal_setup.py +0 -0
  116. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/__init__.py +0 -0
  117. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
  118. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/app.py +0 -0
  119. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/app.tcss +0 -0
  120. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/external_editor.py +0 -0
  121. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
  122. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
  123. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
  124. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
  125. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
  126. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
  127. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
  128. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
  129. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
  130. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
  131. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
  132. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
  133. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
  134. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
  135. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
  136. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
  137. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
  138. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
  139. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/checkpoint_picker.py +0 -0
  140. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/compact.py +0 -0
  141. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
  142. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
  143. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
  144. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/loading.py +0 -0
  145. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/messages.py +0 -0
  146. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
  147. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
  148. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
  149. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
  150. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
  151. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
  152. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
  153. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
  154. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
  155. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/tools.py +0 -0
  156. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
  157. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
  158. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/windowing/history.py +0 -0
  159. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
  160. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/textual_ui/windowing/state.py +0 -0
  161. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/update_notifier/__init__.py +0 -0
  162. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
  163. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
  164. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
  165. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
  166. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
  167. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/update_notifier/update.py +0 -0
  168. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/cli/update_notifier/whats_new.py +0 -0
  169. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/__init__.py +0 -0
  170. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/agent_loop.py +0 -0
  171. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/agents/__init__.py +0 -0
  172. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/agents/manager.py +0 -0
  173. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/agents/models.py +0 -0
  174. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/auth/__init__.py +0 -0
  175. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/auth/crypto.py +0 -0
  176. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/auth/github.py +0 -0
  177. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/autocompletion/__init__.py +0 -0
  178. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/autocompletion/completers.py +0 -0
  179. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
  180. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
  181. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
  182. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/autocompletion/file_indexer/store.py +0 -0
  183. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
  184. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/autocompletion/fuzzy.py +0 -0
  185. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/autocompletion/path_prompt.py +0 -0
  186. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
  187. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/build_orchestrator.py +0 -0
  188. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/checkpoint.py +0 -0
  189. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/config/__init__.py +0 -0
  190. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/config/_settings.py +0 -0
  191. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/config/doctor.py +0 -0
  192. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/config/harness_files/__init__.py +0 -0
  193. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/config/harness_files/_harness_manager.py +0 -0
  194. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/config/harness_files/_paths.py +0 -0
  195. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/consultant.py +0 -0
  196. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/drydock_states.py +0 -0
  197. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/hooks.py +0 -0
  198. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/llm/__init__.py +0 -0
  199. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/llm/backend/anthropic.py +0 -0
  200. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/llm/backend/base.py +0 -0
  201. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/llm/backend/factory.py +0 -0
  202. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/llm/backend/generic.py +0 -0
  203. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/llm/backend/mistral.py +0 -0
  204. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
  205. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/llm/backend/vertex.py +0 -0
  206. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/llm/exceptions.py +0 -0
  207. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/llm/message_utils.py +0 -0
  208. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/llm/types.py +0 -0
  209. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/logger.py +0 -0
  210. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/middleware.py +0 -0
  211. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/output_formatters.py +0 -0
  212. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/paths/__init__.py +0 -0
  213. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/paths/_drydock_home.py +0 -0
  214. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/paths/_local_config_walk.py +0 -0
  215. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/paths/conventions.py +0 -0
  216. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/plan_session.py +0 -0
  217. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/plugins.py +0 -0
  218. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/programmatic.py +0 -0
  219. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/prompts/__init__.py +0 -0
  220. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/prompts/builder.md +0 -0
  221. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/prompts/cli.md +0 -0
  222. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/prompts/compact.md +0 -0
  223. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/prompts/dangerous_directory.md +0 -0
  224. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/prompts/diagnostic.md +0 -0
  225. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/prompts/explore.md +0 -0
  226. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/prompts/gemma4.md +0 -0
  227. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/prompts/planner.md +0 -0
  228. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/prompts/project_context.md +0 -0
  229. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/prompts/tests.md +0 -0
  230. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/proxy_setup.py +0 -0
  231. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/session/agent_memory.py +0 -0
  232. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/session/checkpoints.py +0 -0
  233. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/session/session_loader.py +0 -0
  234. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/session/session_logger.py +0 -0
  235. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/session/session_migration.py +0 -0
  236. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/session/state_file.py +0 -0
  237. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/session_checker.py +0 -0
  238. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/skills/__init__.py +0 -0
  239. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/skills/manager.py +0 -0
  240. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/skills/models.py +0 -0
  241. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/skills/parser.py +0 -0
  242. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/slug.py +0 -0
  243. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/system_prompt.py +0 -0
  244. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/telemetry/__init__.py +0 -0
  245. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/telemetry/send.py +0 -0
  246. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/teleport/errors.py +0 -0
  247. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/teleport/git.py +0 -0
  248. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/teleport/nuage.py +0 -0
  249. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/teleport/teleport.py +0 -0
  250. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/teleport/types.py +0 -0
  251. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/base.py +0 -0
  252. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/_task_manager.py +0 -0
  253. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/ask_user_question.py +0 -0
  254. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/bash.py +0 -0
  255. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/cron.py +0 -0
  256. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
  257. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/glob_tool.py +0 -0
  258. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/grep.py +0 -0
  259. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/invoke_skill.py +0 -0
  260. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/lsp.py +0 -0
  261. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/mcp_resources.py +0 -0
  262. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/notebook_edit.py +0 -0
  263. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/powershell.py +0 -0
  264. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
  265. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
  266. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/bash.md +0 -0
  267. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/cron.md +0 -0
  268. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/glob.md +0 -0
  269. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/grep.md +0 -0
  270. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/invoke_skill.md +0 -0
  271. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/lsp.md +0 -0
  272. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/mcp_resources.md +0 -0
  273. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
  274. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/powershell.md +0 -0
  275. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
  276. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
  277. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
  278. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/task.md +0 -0
  279. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
  280. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/todo.md +0 -0
  281. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/tool_search.md +0 -0
  282. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
  283. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
  284. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/worktree.md +0 -0
  285. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
  286. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/task.py +0 -0
  287. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/todo.py +0 -0
  288. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/tool_search.py +0 -0
  289. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/webfetch.py +0 -0
  290. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/websearch.py +0 -0
  291. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/builtins/worktree.py +0 -0
  292. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/injection_guard.py +0 -0
  293. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/manager.py +0 -0
  294. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/mcp/__init__.py +0 -0
  295. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/mcp/registry.py +0 -0
  296. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/mcp/tools.py +0 -0
  297. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/mcp_sampling.py +0 -0
  298. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/ui.py +0 -0
  299. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/tools/utils.py +0 -0
  300. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/trusted_folders.py +0 -0
  301. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/types.py +0 -0
  302. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/core/utils.py +0 -0
  303. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/setup/onboarding/__init__.py +0 -0
  304. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/setup/onboarding/base.py +0 -0
  305. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/setup/onboarding/onboarding.tcss +0 -0
  306. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/setup/onboarding/screens/__init__.py +0 -0
  307. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/setup/onboarding/screens/api_key.py +0 -0
  308. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/setup/onboarding/screens/choice.py +0 -0
  309. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/setup/onboarding/screens/local_model.py +0 -0
  310. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/setup/onboarding/screens/welcome.py +0 -0
  311. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
  312. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
  313. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/__init__.py +0 -0
  314. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/api-design/SKILL.md +0 -0
  315. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/audit-tests/SKILL.md +0 -0
  316. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/batch/SKILL.md +0 -0
  317. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/commit-code/SKILL.md +0 -0
  318. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/context-summary/SKILL.md +0 -0
  319. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/create-presentation/SKILL.md +0 -0
  320. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/deep-research/SKILL.md +0 -0
  321. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/deploy/SKILL.md +0 -0
  322. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/diff-review/SKILL.md +0 -0
  323. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/doc-gen/SKILL.md +0 -0
  324. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/explain-code/SKILL.md +0 -0
  325. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/explore-code/SKILL.md +0 -0
  326. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/fix-issue/SKILL.md +0 -0
  327. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/git-ops/SKILL.md +0 -0
  328. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/init-project/SKILL.md +0 -0
  329. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/investigate/SKILL.md +0 -0
  330. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/loop/SKILL.md +0 -0
  331. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/migrate/SKILL.md +0 -0
  332. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/perf-analyze/SKILL.md +0 -0
  333. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/plan-impl/SKILL.md +0 -0
  334. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/pr-review/SKILL.md +0 -0
  335. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/refactor/SKILL.md +0 -0
  336. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/regex-help/SKILL.md +0 -0
  337. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/review/SKILL.md +0 -0
  338. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/security-review/SKILL.md +0 -0
  339. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/ship/SKILL.md +0 -0
  340. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/simplify/SKILL.md +0 -0
  341. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/strong-tests/SKILL.md +0 -0
  342. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/skills/test-verify/SKILL.md +0 -0
  343. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock/whats_new.md +0 -0
  344. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock-acp.spec +0 -0
  345. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/drydock_terms.md +0 -0
  346. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/flake.lock +0 -0
  347. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/flake.nix +0 -0
  348. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/nohup.out +0 -0
  349. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/research/README.md +0 -0
  350. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/research/config_base.toml +0 -0
  351. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/research/config_best.toml +0 -0
  352. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/research/domain_spec.md +0 -0
  353. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/research/experimenter.py +0 -0
  354. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/research/kernel.py +0 -0
  355. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/research/mini_prd.md +0 -0
  356. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/research/mini_prompts.txt +0 -0
  357. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/research/proposer.py +0 -0
  358. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/research/results.tsv +0 -0
  359. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/resume.md +0 -0
  360. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/README.md +0 -0
  361. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/admiral_probe.py +0 -0
  362. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/audit_sampler.py +0 -0
  363. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/auto_generate_tests.py +0 -0
  364. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/auto_release.sh +0 -0
  365. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/auto_test_loop.sh +0 -0
  366. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/autonomous_review.sh +0 -0
  367. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/autonomous_review_prompt.md +0 -0
  368. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/backup.sh +0 -0
  369. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/bump_version.py +0 -0
  370. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/comprehensive_loop.py +0 -0
  371. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/deploy_to_github.sh +0 -0
  372. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/discover_cli_tools.sh +0 -0
  373. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/evolve_tests.py +0 -0
  374. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/gen_2000_prompts.py +0 -0
  375. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/install.sh +0 -0
  376. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/llm_balancer.py +0 -0
  377. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/mega_loop.py +0 -0
  378. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/meta_ralph_loop.py +0 -0
  379. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/monitor_swebench.sh +0 -0
  380. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/monitor_test_battery.sh +0 -0
  381. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/notify_release.py +0 -0
  382. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/oss_task_harness.py +0 -0
  383. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/overnight_agents_test.sh +0 -0
  384. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/poll_issues.sh +0 -0
  385. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/port_task.py +0 -0
  386. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/prepare_release.py +0 -0
  387. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/publish_to_pypi.sh +0 -0
  388. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/ralph_loop.py +0 -0
  389. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/research_babysitter.sh +0 -0
  390. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/session_loop_audit.py +0 -0
  391. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/shakedown.py +0 -0
  392. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/shakedown_interactive.py +0 -0
  393. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/shakedown_regression.sh +0 -0
  394. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/shakedown_suite.sh +0 -0
  395. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/shakedown_variance.sh +0 -0
  396. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/stress_babysitter.sh +0 -0
  397. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/stress_prompts_50.txt +0 -0
  398. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/stress_prompts_realuser.txt +0 -0
  399. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/stress_prompts_tool_agent.txt +0 -0
  400. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/stress_prompts_tool_agent_2000.txt +0 -0
  401. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/stress_shakedown.py +0 -0
  402. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/stress_telegram_status.py +0 -0
  403. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/stress_watcher.py +0 -0
  404. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/telegram_bot.py +0 -0
  405. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/test_bank.sh +0 -0
  406. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/test_full.sh +0 -0
  407. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/test_smoke.sh +0 -0
  408. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/test_tui_path.py +0 -0
  409. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/tui_test.py +0 -0
  410. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/scripts/vllm_failover.sh +0 -0
  411. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/test/project/dummy +0 -0
  412. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/__init__.py +0 -0
  413. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/conftest.py +0 -0
  414. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_acp.py +0 -0
  415. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_agent_thought.py +0 -0
  416. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_bash.py +0 -0
  417. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_compact_session_updates.py +0 -0
  418. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_content.py +0 -0
  419. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_initialize.py +0 -0
  420. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_list_sessions.py +0 -0
  421. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_load_session.py +0 -0
  422. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_multi_session.py +0 -0
  423. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_new_session.py +0 -0
  424. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_proxy_setup_acp.py +0 -0
  425. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_read_file.py +0 -0
  426. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_search_replace.py +0 -0
  427. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_set_config_option.py +0 -0
  428. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_set_mode.py +0 -0
  429. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_set_model.py +0 -0
  430. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_tool_call_session_update.py +0 -0
  431. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_utils.py +0 -0
  432. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/acp/test_write_file.py +0 -0
  433. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/autocompletion/test_file_indexer.py +0 -0
  434. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/autocompletion/test_fuzzy.py +0 -0
  435. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
  436. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/autocompletion/test_path_completer_recursive.py +0 -0
  437. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/autocompletion/test_path_completion_controller.py +0 -0
  438. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
  439. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/autocompletion/test_slash_command_controller.py +0 -0
  440. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
  441. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/backend/__init__.py +0 -0
  442. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/backend/data/__init__.py +0 -0
  443. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/backend/data/fireworks.py +0 -0
  444. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/backend/data/mistral.py +0 -0
  445. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/backend/test_anthropic_adapter.py +0 -0
  446. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/backend/test_backend.py +0 -0
  447. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/backend/test_generic_adapter_sanitize.py +0 -0
  448. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/backend/test_reasoning_adapter.py +0 -0
  449. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
  450. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
  451. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
  452. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
  453. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/test_bell_notifications.py +0 -0
  454. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/test_braille_renderer.py +0 -0
  455. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/test_clipboard.py +0 -0
  456. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/test_commands.py +0 -0
  457. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/test_copy_shortcuts.py +0 -0
  458. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/test_external_editor.py +0 -0
  459. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/test_no_markup_static.py +0 -0
  460. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/test_question_app.py +0 -0
  461. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/test_spinner.py +0 -0
  462. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/test_switching_mode.py +0 -0
  463. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/test_ui_clipboard_notifications.py +0 -0
  464. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
  465. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/test_ui_session_resume.py +0 -0
  466. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/test_ui_skill_dispatch.py +0 -0
  467. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/textual_ui/__init__.py +0 -0
  468. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/cli/textual_ui/test_session_picker.py +0 -0
  469. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/conftest.py +0 -0
  470. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_agents.py +0 -0
  471. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_auth_crypto.py +0 -0
  472. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_auth_github.py +0 -0
  473. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_circuit_breaker_readonly_threshold.py +0 -0
  474. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_config_load_dotenv.py +0 -0
  475. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_config_paths.py +0 -0
  476. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_config_resolution.py +0 -0
  477. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_file_logging.py +0 -0
  478. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_plan_session.py +0 -0
  479. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_proxy_setup.py +0 -0
  480. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_slug.py +0 -0
  481. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_telemetry_send.py +0 -0
  482. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_teleport_git.py +0 -0
  483. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_teleport_nuage.py +0 -0
  484. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_teleport_service.py +0 -0
  485. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_trusted_folders.py +0 -0
  486. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/core/test_utils.py +0 -0
  487. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/e2e/common.py +0 -0
  488. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/e2e/conftest.py +0 -0
  489. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/e2e/mock_server.py +0 -0
  490. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/e2e/test_cli_tui_onboarding.py +0 -0
  491. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/e2e/test_cli_tui_streaming.py +0 -0
  492. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
  493. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/fixtures/doc_qa_system_prd.md +0 -0
  494. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/mock/__init__.py +0 -0
  495. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/mock/mock_backend_factory.py +0 -0
  496. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/mock/mock_entrypoint.py +0 -0
  497. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/mock/utils.py +0 -0
  498. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/onboarding/test_run_onboarding.py +0 -0
  499. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/onboarding/test_ui_onboarding.py +0 -0
  500. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/session/test_session_loader.py +0 -0
  501. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/session/test_session_logger.py +0 -0
  502. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/session/test_session_migration.py +0 -0
  503. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/skills/conftest.py +0 -0
  504. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/skills/test_manager.py +0 -0
  505. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/skills/test_models.py +0 -0
  506. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/skills/test_parser.py +0 -0
  507. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
  508. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
  509. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
  510. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
  511. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
  512. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
  513. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
  514. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
  515. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
  516. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
  517. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
  518. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
  519. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
  520. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
  521. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
  522. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
  523. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
  524. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
  525. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
  526. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
  527. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
  528. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
  529. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
  530. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
  531. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
  532. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
  533. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
  534. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
  535. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
  536. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
  537. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
  538. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
  539. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
  540. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
  541. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
  542. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
  543. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
  544. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
  545. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
  546. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
  547. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
  548. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
  549. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
  550. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
  551. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
  552. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
  553. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
  554. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
  555. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
  556. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
  557. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
  558. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
  559. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
  560. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
  561. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
  562. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
  563. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
  564. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
  565. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
  566. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
  567. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/base_snapshot_test_app.py +0 -0
  568. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/conftest.py +0 -0
  569. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/snap_compare.py +0 -0
  570. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
  571. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
  572. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
  573. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
  574. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
  575. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
  576. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
  577. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
  578. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
  579. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
  580. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
  581. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
  582. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
  583. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
  584. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/stubs/fake_backend.py +0 -0
  585. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/stubs/fake_client.py +0 -0
  586. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/stubs/fake_tool.py +0 -0
  587. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_admiral.py +0 -0
  588. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_admiral_phase3.py +0 -0
  589. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_admiral_proposed.py +0 -0
  590. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_admiral_struggle_dedup.py +0 -0
  591. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_agent_auto_compact.py +0 -0
  592. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_agent_backend.py +0 -0
  593. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_agent_observer_streaming.py +0 -0
  594. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_agent_stats.py +0 -0
  595. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_agent_tasks.py +0 -0
  596. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_agent_tool_call.py +0 -0
  597. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_agents.py +0 -0
  598. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_bank_build.py +0 -0
  599. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_bank_debug.py +0 -0
  600. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_bank_multiagent.py +0 -0
  601. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_bank_prd.py +0 -0
  602. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_bank_prd_extended.py +0 -0
  603. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_bank_tools.py +0 -0
  604. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_bank_update.py +0 -0
  605. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_build_projects.py +0 -0
  606. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_checkpoint.py +0 -0
  607. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_cli_programmatic_preload.py +0 -0
  608. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_current_bugs.py +0 -0
  609. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_drydock_regression.py +0 -0
  610. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_drydock_tasks.py +0 -0
  611. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_fake_tool_call_paren_syntax.py +0 -0
  612. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_full_regression.py +0 -0
  613. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_history_manager.py +0 -0
  614. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_integration.py +0 -0
  615. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_issue_fixes.py +0 -0
  616. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_loop_detection.py +0 -0
  617. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_message_id.py +0 -0
  618. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_message_merging.py +0 -0
  619. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_middleware.py +0 -0
  620. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_multi_agent.py +0 -0
  621. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_read_file_not_found_listing.py +0 -0
  622. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_real_failures.py +0 -0
  623. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_real_issues.py +0 -0
  624. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_real_workflow.py +0 -0
  625. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_reasoning_content.py +0 -0
  626. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_smoke.py +0 -0
  627. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_system_prompt.py +0 -0
  628. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_tagged_text.py +0 -0
  629. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_tool_args.py +0 -0
  630. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_truncate_args_valid_json.py +0 -0
  631. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_truncated_arg_path_hint.py +0 -0
  632. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_ui_external_editor.py +0 -0
  633. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_ui_input_history.py +0 -0
  634. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_user_issues.py +0 -0
  635. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_wall_of_text_rescue.py +0 -0
  636. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/test_workloads.py +0 -0
  637. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/testbank_helpers.py +0 -0
  638. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_ask_user_question.py +0 -0
  639. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_bash.py +0 -0
  640. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_exit_plan_mode.py +0 -0
  641. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_grep.py +0 -0
  642. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_invoke_context.py +0 -0
  643. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_manager_gemma_derived_models.py +0 -0
  644. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_manager_get_tool_config.py +0 -0
  645. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_mcp.py +0 -0
  646. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_mcp_sampling.py +0 -0
  647. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_read_file_directory.py +0 -0
  648. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_search_replace_append_fallback.py +0 -0
  649. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_search_replace_dir_path.py +0 -0
  650. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_search_replace_hard_stop.py +0 -0
  651. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_search_replace_no_op_loop_breaker.py +0 -0
  652. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_search_replace_refused_loop_breaker.py +0 -0
  653. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_task.py +0 -0
  654. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_ui_bash_execution.py +0 -0
  655. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_webfetch.py +0 -0
  656. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_websearch.py +0 -0
  657. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_write_file_dedup_missing_imports.py +0 -0
  658. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/tools/test_write_file_missing_path_hint.py +0 -0
  659. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
  660. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
  661. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/update_notifier/test_do_update.py +0 -0
  662. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
  663. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/update_notifier/test_github_update_gateway.py +0 -0
  664. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
  665. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/update_notifier/test_ui_update_notification.py +0 -0
  666. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/update_notifier/test_update_use_case.py +0 -0
  667. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/tests/update_notifier/test_whats_new.py +0 -0
  668. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/worked_examples/README.md +0 -0
  669. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/worked_examples/cli_subcommand_dispatch.py +0 -0
  670. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/worked_examples/lookup.json +0 -0
  671. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/worked_examples/sql_parser.py +0 -0
  672. {drydock_cli-2.7.17 → drydock_cli-2.7.19}/worked_examples/tree_walking_interpreter.py +0 -0
@@ -0,0 +1 @@
1
+ 361748
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 2.7.17
3
+ Version: 2.7.19
4
4
  Summary: Local-first CLI coding agent — tested with Gemma 4 26B via vLLM
5
5
  Project-URL: Homepage, https://github.com/fbobe321/drydock
6
6
  Project-URL: Repository, https://github.com/fbobe321/drydock
@@ -412,7 +412,7 @@ class APIToolFormatHandler:
412
412
  tool_name=parsed_call.tool_name,
413
413
  call_id=parsed_call.call_id,
414
414
  error=(
415
- f"{parsed_call.tool_name}: your call used a "
415
+ f"your call used a "
416
416
  f"truncated history entry as a template (it contained "
417
417
  f"'_truncated'/'_original_bytes' instead of real "
418
418
  f"arguments).{file_embed} Provide the full required arguments."
@@ -438,11 +438,56 @@ class APIToolFormatHandler:
438
438
  and "path" in error_str
439
439
  and "Field required" in error_str
440
440
  ):
441
+ # Try to infer path from the first comment line of content.
442
+ # Gemma 4 frequently calls write_file(content="...") without path.
443
+ content_val = parsed_call.raw_args.get("content", "")
444
+ inferred_path: str | None = None
445
+ if content_val:
446
+ for _line in content_val.splitlines()[:5]:
447
+ _line = _line.strip()
448
+ _m = _re.match(
449
+ r'^#\s+([\w./+-]+\.(?:py|js|ts|json|yaml|yml|toml|md|txt|sh|cfg|ini))\s*$',
450
+ _line,
451
+ )
452
+ if _m:
453
+ inferred_path = _m.group(1)
454
+ break
455
+ if inferred_path:
456
+ try:
457
+ _new_args = dict(parsed_call.raw_args)
458
+ _new_args["path"] = inferred_path
459
+ validated_args = args_model.model_validate(_new_args)
460
+ resolved_calls.append(
461
+ ResolvedToolCall(
462
+ tool_name=parsed_call.tool_name,
463
+ tool_class=tool_class,
464
+ validated_args=validated_args,
465
+ call_id=parsed_call.call_id,
466
+ )
467
+ )
468
+ continue
469
+ except ValidationError:
470
+ pass
471
+ # List project .py files as hints so the model can pick the right one
472
+ _candidates: list[str] = []
473
+ try:
474
+ _candidates = [
475
+ str(p.relative_to(Path.cwd()))
476
+ for p in sorted(Path.cwd().rglob("*.py"))
477
+ if "__pycache__" not in str(p) and ".git" not in str(p)
478
+ ][:12]
479
+ except Exception:
480
+ pass
481
+ _hint = (
482
+ f"Project .py files: {', '.join(_candidates)}"
483
+ if _candidates
484
+ else "Use read_file or glob to list available files."
485
+ )
441
486
  error_msg = (
442
- "write_file: missing required `path` parameter. "
443
- "You must pass BOTH `path` AND `content` as separate arguments. "
444
- 'Fix: write_file(path="your/file.py", content="..."). '
445
- "Do NOT omit `path`."
487
+ "missing required `path` parameter. "
488
+ "You must pass BOTH `path` AND `content` as separate arguments: "
489
+ 'write_file(path="pkg/file.py", content="..."). '
490
+ f"Do NOT omit `path`. {_hint}"
446
491
  )
447
492
  else:
448
493
  error_msg = f"Invalid arguments: {e}"
@@ -45,7 +45,7 @@ class ReadFileResult(BaseModel):
45
45
  content: str
46
46
  lines_read: int
47
47
  was_truncated: bool = Field(
48
- description="True if the reading was stopped due to the max_read_bytes limit."
48
+ description="True if the reading was stopped due to the line limit or max_read_bytes limit."
49
49
  )
50
50
 
51
51
 
@@ -111,25 +111,48 @@ class ReadFile(
111
111
  and prior.get("offset") == args.offset
112
112
  and prior.get("limit") == args.limit
113
113
  ):
114
+ # Re-embed the cached content so the model has it even if the
115
+ # earlier tool_result was truncated by _truncate_old_tool_results.
116
+ # Pointing at a stale/truncated prior result causes re-read loops.
117
+ cached_content = prior.get("content", "")
118
+ prior_lines = prior.get("lines_read", 0)
119
+ dedup_count = prior.get("dedup_count", 0)
120
+ if dedup_count == 0:
121
+ header = "[Unchanged since last read — content re-embedded]\n"
122
+ else:
123
+ header = (
124
+ f"[REPEATED READ #{dedup_count + 1}: file has not changed across your last "
125
+ f"{dedup_count + 1} reads with these exact arguments. "
126
+ f"Reading again will produce this same result. "
127
+ f"To make progress: write or edit a file, use offset= to read a different section, "
128
+ f"or move on to the next task.]\n"
129
+ )
130
+ if read_state is not None:
131
+ read_state[path_key] = {**prior, "dedup_count": dedup_count + 1}
114
132
  yield ReadFileResult(
115
133
  path=path_key,
116
- content=(
117
- "<system-reminder>\n"
118
- f"File unchanged since your earlier read this session "
119
- f"({file_path.name}, mtime unchanged, same offset/limit). "
120
- "Use the content from the earlier Read tool_result — "
121
- "do NOT re-read. If you need to take action, call "
122
- "search_replace or write_file on what you already have.\n"
123
- "</system-reminder>"
124
- ),
125
- lines_read=0,
126
- was_truncated=True,
134
+ content=f"{header}{cached_content}",
135
+ lines_read=prior_lines,
136
+ was_truncated=prior.get("was_truncated", False),
127
137
  )
128
138
  return
129
139
 
130
140
  read_result = await self._read_file(args, file_path)
131
141
  content = "".join(read_result.lines)
132
142
 
143
+ # When stopped by the line limit (not byte limit), append a hint so
144
+ # the model knows to paginate with offset= instead of re-reading.
145
+ if (
146
+ read_result.was_truncated
147
+ and args.limit is not None
148
+ and len(read_result.lines) == args.limit
149
+ ):
150
+ next_offset = args.offset + args.limit
151
+ content += (
152
+ f"\n[lines {args.offset + 1}–{next_offset} shown; "
153
+ f"use offset={next_offset} to read more]"
154
+ )
155
+
133
156
  # Record read state so Write/Edit can enforce Read-before-Write
134
157
  # and so future re-reads can dedup against this one.
135
158
  if read_state is not None:
@@ -138,6 +161,8 @@ class ReadFile(
138
161
  "timestamp": current_mtime,
139
162
  "offset": args.offset,
140
163
  "limit": args.limit,
164
+ "lines_read": len(read_result.lines),
165
+ "was_truncated": read_result.was_truncated,
141
166
  }
142
167
 
143
168
  yield ReadFileResult(
@@ -195,6 +220,7 @@ class ReadFile(
195
220
  continue
196
221
 
197
222
  if args.limit is not None and len(lines_to_return) >= args.limit:
223
+ was_truncated = True
198
224
  break
199
225
 
200
226
  line_bytes = len(line.encode("utf-8"))
@@ -131,6 +131,46 @@ class SearchReplace(
131
131
  file_path, search_replace_blocks = self._prepare_and_validate_args(args)
132
132
  except ToolError as e:
133
133
  err_msg = str(e)
134
+ if err_msg.startswith("Empty content provided.") or err_msg.startswith("File path is required."):
135
+ # Model sent search_replace with missing content or file_path.
136
+ # Convert to a soft result so the model corrects — a ToolError
137
+ # causes panic-retry loops (feedback: never raise ToolError for
138
+ # loop detection). Track count to escalate on repeat offenses.
139
+ empty_state = self.state.__dict__.setdefault("_sr_empty_history", {})
140
+ key = args.file_path.strip() or "<no-path>"
141
+ entry = empty_state.get(key, {"count": 0})
142
+ entry["count"] += 1
143
+ empty_state[key] = entry
144
+ count = entry["count"]
145
+ escalate = count >= 2
146
+ extra = ""
147
+ if escalate:
148
+ # Show project files so model can recover context
149
+ try:
150
+ py_files = sorted(
151
+ str(p.relative_to(Path.cwd()))
152
+ for p in Path.cwd().rglob("*.py")
153
+ if "__pycache__" not in str(p) and ".git" not in str(p)
154
+ )[:20]
155
+ extra = (
156
+ f"\n[This is the #{count} empty search_replace on '{key}'. "
157
+ f"Stop retrying. Current .py files in project:\n"
158
+ + "\n".join(f" {f}" for f in py_files)
159
+ + "\nUse write_file to create a file, or read_file to "
160
+ f"see file contents before editing.]"
161
+ )
162
+ except Exception:
163
+ extra = (
164
+ f"\n[This is the #{count} empty search_replace on '{key}'. "
165
+ "Stop retrying. Use write_file or read the file first.]"
166
+ )
167
+ yield SearchReplaceResult(
168
+ file=key,
169
+ blocks_applied=0,
170
+ lines_changed=0,
171
+ content=err_msg + extra,
172
+ )
173
+ return
134
174
  if err_msg.startswith("Path is not a file:"):
135
175
  # Model passed a directory instead of a file path.
136
176
  # Return a result (not raise) so the model corrects the call
@@ -735,6 +735,19 @@ class WriteFile(
735
735
  file_path = Path.cwd() / file_path
736
736
  file_path = file_path.resolve()
737
737
 
738
+ if file_path.is_dir():
739
+ try:
740
+ children = sorted(p.name for p in file_path.iterdir())[:20]
741
+ listing = ", ".join(children) if children else "(empty)"
742
+ except OSError:
743
+ listing = "(unreadable)"
744
+ raise ToolError(
745
+ f"'{file_path}' is a directory, not a file. "
746
+ f"Specify the exact file path inside it.\n"
747
+ f"Files in that directory: {listing}\n"
748
+ f"Example: {file_path}/{children[0] if children else 'yourfile.py'}"
749
+ )
750
+
738
751
  file_existed = file_path.exists()
739
752
 
740
753
  if file_existed and not args.overwrite:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "drydock-cli"
3
- version = "2.7.17"
3
+ version = "2.7.19"
4
4
  description = "Local-first CLI coding agent — tested with Gemma 4 26B via vLLM"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -0,0 +1,75 @@
1
+ """Regression test: write_file missing-path loop fix.
2
+
3
+ Stress run 2026-04-28 showed Gemma 4 calling write_file(content="...")
4
+ without a path. format.py returned "write_file: missing required `path`..."
5
+ and agent_loop.py wrapped it as "<tool_error>write_file: write_file: ..."
6
+ producing a confusing double-prefix. Also, the error message placeholder
7
+ "your/file.py" gave the model no real hint.
8
+
9
+ Fixes in format.py:
10
+ 1. Remove tool-name prefix from error msg (agent_loop adds it already).
11
+ 2. When content first line is "# filename.py", infer path and succeed.
12
+ 3. When path can't be inferred, include project .py file listing in error.
13
+ """
14
+ from __future__ import annotations
15
+
16
+ from unittest.mock import MagicMock
17
+
18
+ import pytest
19
+
20
+ from drydock.core.llm.format import APIToolFormatHandler, ParsedMessage, ParsedToolCall
21
+
22
+
23
+ def _make_tool_manager():
24
+ tm = MagicMock()
25
+ from drydock.core.tools.builtins.write_file import WriteFile
26
+ tm.available_tools = {"write_file": WriteFile}
27
+ return tm
28
+
29
+
30
+ class TestWriteFileMissingPath:
31
+ def _resolve(self, raw_args: dict) -> object:
32
+ handler = APIToolFormatHandler()
33
+ parsed = ParsedMessage(
34
+ tool_calls=[
35
+ ParsedToolCall(
36
+ tool_name="write_file",
37
+ call_id="tc1",
38
+ raw_args=raw_args,
39
+ )
40
+ ],
41
+ text_content="",
42
+ )
43
+ return handler.resolve_tool_calls(parsed, _make_tool_manager())
44
+
45
+ def test_missing_path_no_double_prefix(self):
46
+ """Error for missing path must NOT start with 'write_file:'."""
47
+ result = self._resolve({"content": "import os\nprint('hello')\n"})
48
+ assert result.failed_calls
49
+ err = result.failed_calls[0].error
50
+ # agent_loop.py will add "write_file: " prefix — the error itself must not
51
+ assert not err.startswith("write_file:"), f"Double prefix found: {err!r}"
52
+
53
+ def test_missing_path_error_has_useful_hint(self):
54
+ """Error should mention path parameter and how to fix it."""
55
+ result = self._resolve({"content": "import os\nprint('hello')\n"})
56
+ err = result.failed_calls[0].error
57
+ assert "path" in err.lower()
58
+ # Must not contain the useless placeholder "your/file.py"
59
+ assert "your/file.py" not in err
60
+
61
+ def test_path_inferred_from_comment(self, tmp_path, monkeypatch):
62
+ """When first line is '# mymodule.py', path is inferred and write succeeds."""
63
+ monkeypatch.chdir(tmp_path)
64
+ content = "# mymodule.py\nimport os\n\ndef hello():\n pass\n"
65
+ result = self._resolve({"content": content})
66
+ # Should resolve (no failed call), path inferred as mymodule.py
67
+ assert not result.failed_calls, f"Expected no failure, got: {result.failed_calls[0].error!r}"
68
+ assert result.tool_calls
69
+ assert result.tool_calls[0].validated_args.path == "mymodule.py"
70
+
71
+ def test_path_not_inferred_from_plain_import(self):
72
+ """Content starting with bare import (no comment) must produce a failed call."""
73
+ result = self._resolve({"content": "import abc\nimport os\nimport datetime\n"})
74
+ assert result.failed_calls
75
+ assert not result.tool_calls
@@ -0,0 +1,136 @@
1
+ """Regression test: read_file dedup re-embeds cached content instead of pointing
2
+ at a possibly-truncated prior tool_result.
3
+
4
+ The model (Gemma 4) looped re-reading cli.py with limit=100 because:
5
+ 1. First read: stored in read_state, returned truncated content.
6
+ 2. _truncate_old_tool_results pruned that tool_result from message history.
7
+ 3. Second read (same offset/limit/mtime): dedup fired with "use earlier result."
8
+ 4. Model couldn't find the earlier result (truncated) and re-read again → loop.
9
+
10
+ Fix: when dedup fires, embed the cached content directly in the response
11
+ rather than pointing at the prior (possibly absent) tool_result.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import pytest
16
+ from pathlib import Path
17
+ from unittest.mock import MagicMock
18
+
19
+ from drydock.core.tools.base import BaseToolState
20
+ from drydock.core.tools.builtins.read_file import ReadFile, ReadFileArgs, ReadFileResult, ReadFileToolConfig
21
+
22
+
23
+ async def _run_result(tool, args, ctx) -> ReadFileResult:
24
+ async for event in tool.run(args, ctx):
25
+ if isinstance(event, ReadFileResult):
26
+ return event
27
+ raise AssertionError("no ReadFileResult yielded")
28
+
29
+
30
+ @pytest.mark.asyncio
31
+ async def test_dedup_reembeds_cached_content(tmp_path):
32
+ """Second identical read returns cached content, not a pointer stub."""
33
+ f = tmp_path / "cli.py"
34
+ f.write_text("def main():\n pass\n")
35
+
36
+ tool = ReadFile(ReadFileToolConfig(), BaseToolState())
37
+ read_state: dict = {}
38
+ ctx = MagicMock()
39
+ ctx.read_file_state = read_state
40
+
41
+ args = ReadFileArgs(path=str(f), offset=0, limit=100)
42
+
43
+ # First read populates the cache.
44
+ result1 = await _run_result(tool, args, ctx)
45
+ assert "def main" in result1.content
46
+
47
+ # Second read with same args/mtime must return real content, not a pointer.
48
+ result2 = await _run_result(tool, args, ctx)
49
+ assert "def main" in result2.content, "dedup must re-embed content, not point at prior result"
50
+ assert "re-embedded" in result2.content
51
+
52
+
53
+ @pytest.mark.asyncio
54
+ async def test_dedup_does_not_fire_after_file_changes(tmp_path):
55
+ """Dedup must not fire if the file has been modified on disk."""
56
+ f = tmp_path / "cli.py"
57
+ f.write_text("version = 1\n")
58
+
59
+ tool = ReadFile(ReadFileToolConfig(), BaseToolState())
60
+ read_state: dict = {}
61
+ ctx = MagicMock()
62
+ ctx.read_file_state = read_state
63
+
64
+ args = ReadFileArgs(path=str(f), offset=0, limit=100)
65
+
66
+ result1 = await _run_result(tool, args, ctx)
67
+ assert "version = 1" in result1.content
68
+
69
+ # Modify the file (mtime changes).
70
+ import time; time.sleep(0.01)
71
+ f.write_text("version = 2\n")
72
+
73
+ result2 = await _run_result(tool, args, ctx)
74
+ assert "version = 2" in result2.content, "should read updated file, not cached content"
75
+ assert "re-embedded" not in result2.content
76
+
77
+
78
+ @pytest.mark.asyncio
79
+ async def test_dedup_escalates_on_repeated_reads(tmp_path):
80
+ """Third and later identical reads get an escalating REPEATED READ advisory."""
81
+ f = tmp_path / "cli.py"
82
+ f.write_text("def main():\n pass\n")
83
+
84
+ tool = ReadFile(ReadFileToolConfig(), BaseToolState())
85
+ read_state: dict = {}
86
+ ctx = MagicMock()
87
+ ctx.read_file_state = read_state
88
+
89
+ args = ReadFileArgs(path=str(f), offset=0, limit=100)
90
+
91
+ # First read: no dedup.
92
+ r1 = await _run_result(tool, args, ctx)
93
+ assert "re-embedded" not in r1.content
94
+ assert "REPEATED READ" not in r1.content
95
+
96
+ # Second read: first dedup hit — gentle re-embed message.
97
+ r2 = await _run_result(tool, args, ctx)
98
+ assert "re-embedded" in r2.content
99
+ assert "REPEATED READ" not in r2.content
100
+ assert read_state[str(f)]["dedup_count"] == 1
101
+
102
+ # Third read: second dedup hit — escalated advisory.
103
+ r3 = await _run_result(tool, args, ctx)
104
+ assert "REPEATED READ #2" in r3.content
105
+ assert "def main" in r3.content
106
+ assert read_state[str(f)]["dedup_count"] == 2
107
+
108
+ # Fourth read: third dedup hit — counter increments.
109
+ r4 = await _run_result(tool, args, ctx)
110
+ assert "REPEATED READ #3" in r4.content
111
+ assert read_state[str(f)]["dedup_count"] == 3
112
+
113
+
114
+ @pytest.mark.asyncio
115
+ async def test_dedup_stores_lines_read_and_was_truncated(tmp_path):
116
+ """read_state must record lines_read and was_truncated for correct dedup re-embedding."""
117
+ f = tmp_path / "big.py"
118
+ f.write_text("\n".join(f"line{i}" for i in range(1, 201))) # 200 lines
119
+
120
+ tool = ReadFile(ReadFileToolConfig(), BaseToolState())
121
+ read_state: dict = {}
122
+ ctx = MagicMock()
123
+ ctx.read_file_state = read_state
124
+
125
+ args = ReadFileArgs(path=str(f), offset=0, limit=50)
126
+ await _run_result(tool, args, ctx)
127
+
128
+ path_key = str(f)
129
+ assert "lines_read" in read_state[path_key]
130
+ assert read_state[path_key]["lines_read"] == 50
131
+ assert read_state[path_key]["was_truncated"] is True
132
+
133
+ # Second read: dedup fires, re-embeds with correct metadata.
134
+ result2 = await _run_result(tool, args, ctx)
135
+ assert result2.lines_read == 50
136
+ assert result2.was_truncated is True
@@ -0,0 +1,76 @@
1
+ """Regression test: read_file with limit= sets was_truncated and appends pagination hint.
2
+
3
+ The model (Gemma 4) called read_file with limit=100 on large files, received
4
+ was_truncated=False and no hint, and then re-read the same file 10+ times
5
+ confused about why it was seeing partial content. Fix: set was_truncated=True
6
+ when the line limit stops reading, and append an "offset=N to read more" hint
7
+ so the model knows to paginate rather than re-read.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import pytest
12
+ from pathlib import Path
13
+ from unittest.mock import MagicMock
14
+
15
+ from drydock.core.tools.base import BaseToolState
16
+ from drydock.core.tools.builtins.read_file import ReadFile, ReadFileArgs, ReadFileResult, ReadFileToolConfig
17
+
18
+
19
+ async def _run_result(tool, args, ctx) -> ReadFileResult:
20
+ async for event in tool.run(args, ctx):
21
+ if isinstance(event, ReadFileResult):
22
+ return event
23
+ raise AssertionError("no ReadFileResult yielded")
24
+
25
+
26
+ @pytest.mark.asyncio
27
+ async def test_limit_sets_was_truncated_and_adds_hint(tmp_path):
28
+ """was_truncated=True and pagination hint appended when limit stops the read."""
29
+ f = tmp_path / "big.py"
30
+ f.write_text("\n".join(f"line{i}" for i in range(1, 201))) # 200 lines
31
+
32
+ tool = ReadFile(ReadFileToolConfig(), BaseToolState())
33
+ args = ReadFileArgs(path=str(f), offset=0, limit=100)
34
+ ctx = MagicMock()
35
+ ctx.read_file_state = {}
36
+
37
+ result = await _run_result(tool, args, ctx)
38
+
39
+ assert result.was_truncated is True
40
+ assert result.lines_read == 100
41
+ assert "offset=100" in result.content
42
+ assert "read more" in result.content
43
+
44
+
45
+ @pytest.mark.asyncio
46
+ async def test_no_truncation_when_file_fits_in_limit(tmp_path):
47
+ """was_truncated=False when file has fewer lines than the limit."""
48
+ f = tmp_path / "small.py"
49
+ f.write_text("\n".join(f"line{i}" for i in range(1, 11))) # 10 lines
50
+
51
+ tool = ReadFile(ReadFileToolConfig(), BaseToolState())
52
+ args = ReadFileArgs(path=str(f), offset=0, limit=100)
53
+ ctx = MagicMock()
54
+ ctx.read_file_state = {}
55
+
56
+ result = await _run_result(tool, args, ctx)
57
+
58
+ assert result.was_truncated is False
59
+ assert "offset=" not in result.content
60
+
61
+
62
+ @pytest.mark.asyncio
63
+ async def test_offset_pagination_hint_uses_correct_next_offset(tmp_path):
64
+ """Hint shows the correct next offset when reading a middle chunk."""
65
+ f = tmp_path / "file.py"
66
+ f.write_text("\n".join(f"line{i}" for i in range(1, 301))) # 300 lines
67
+
68
+ tool = ReadFile(ReadFileToolConfig(), BaseToolState())
69
+ args = ReadFileArgs(path=str(f), offset=50, limit=100)
70
+ ctx = MagicMock()
71
+ ctx.read_file_state = {}
72
+
73
+ result = await _run_result(tool, args, ctx)
74
+
75
+ assert result.was_truncated is True
76
+ assert "offset=150" in result.content # 50 + 100
@@ -0,0 +1,90 @@
1
+ """Regression test: search_replace empty-content raises ToolError → retry loop.
2
+
3
+ Stress run 2026-04-28 showed Gemma 4 calling search_replace with empty
4
+ content (content="") 20+ times consecutively. The ToolError path caused
5
+ panic-retry loops (feedback: never raise ToolError for loop detection).
6
+
7
+ Fix: detect empty content/file_path in the ToolError handler in run()
8
+ and yield a soft SearchReplaceResult instead of re-raising. Track count
9
+ per call-target so the 2nd+ offense escalates with project file listing.
10
+ """
11
+ from __future__ import annotations
12
+
13
+ import asyncio
14
+ from pathlib import Path
15
+
16
+ import pytest
17
+
18
+ from drydock.core.tools.base import BaseToolState, InvokeContext
19
+ from drydock.core.tools.builtins.search_replace import (
20
+ SearchReplace,
21
+ SearchReplaceArgs,
22
+ SearchReplaceConfig,
23
+ SearchReplaceResult,
24
+ )
25
+
26
+
27
+ def _make_tool() -> SearchReplace:
28
+ config = SearchReplaceConfig()
29
+ state = BaseToolState()
30
+ return SearchReplace(config=config, state=state)
31
+
32
+
33
+ async def _run(tool: SearchReplace, args: SearchReplaceArgs, tmp_path: Path) -> SearchReplaceResult:
34
+ ctx = InvokeContext(tool_call_id="test-1", read_file_state={})
35
+ results = []
36
+ async for item in tool.run(args, ctx):
37
+ if isinstance(item, SearchReplaceResult):
38
+ results.append(item)
39
+ assert results, "Expected at least one SearchReplaceResult"
40
+ return results[-1]
41
+
42
+
43
+ @pytest.mark.asyncio
44
+ async def test_empty_content_returns_result_not_raises(tmp_path: Path) -> None:
45
+ """Empty content must yield a result, never raise ToolError."""
46
+ tool = _make_tool()
47
+ result = await _run(
48
+ tool,
49
+ SearchReplaceArgs(file_path="foo.py", content=""),
50
+ tmp_path,
51
+ )
52
+ assert isinstance(result, SearchReplaceResult)
53
+ assert result.blocks_applied == 0
54
+ assert "Empty content" in result.content
55
+
56
+
57
+ @pytest.mark.asyncio
58
+ async def test_empty_content_escalates_on_repeat(tmp_path: Path) -> None:
59
+ """2nd consecutive empty-content call adds project file listing."""
60
+ tool = _make_tool()
61
+ # First call
62
+ result1 = await _run(
63
+ tool,
64
+ SearchReplaceArgs(file_path="foo.py", content=""),
65
+ tmp_path,
66
+ )
67
+ assert "Empty content" in result1.content
68
+ assert "#2" not in result1.content # no escalation yet
69
+
70
+ # Second call — same key, should escalate
71
+ result2 = await _run(
72
+ tool,
73
+ SearchReplaceArgs(file_path="foo.py", content=""),
74
+ tmp_path,
75
+ )
76
+ assert "#2" in result2.content
77
+ assert "Stop retrying" in result2.content
78
+
79
+
80
+ @pytest.mark.asyncio
81
+ async def test_missing_file_path_returns_result_not_raises(tmp_path: Path) -> None:
82
+ """Missing file_path (can't infer) must also yield a result, not raise."""
83
+ tool = _make_tool()
84
+ result = await _run(
85
+ tool,
86
+ SearchReplaceArgs(file_path="", content=""),
87
+ tmp_path,
88
+ )
89
+ assert isinstance(result, SearchReplaceResult)
90
+ assert result.blocks_applied == 0