drydock-cli 2.7.18__tar.gz → 2.7.20__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 (673) hide show
  1. drydock_cli-2.7.20/.auto_release.lock +1 -0
  2. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/PKG-INFO +1 -1
  3. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/llm/format.py +38 -1
  4. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/read_file.py +23 -11
  5. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/search_replace.py +31 -1
  6. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/pyproject.toml +1 -1
  7. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/stress_babysitter.sh +2 -2
  8. drydock_cli-2.7.20/tests/test_truncated_write_escalation.py +104 -0
  9. drydock_cli-2.7.20/tests/tools/test_read_file_dedup_reembed.py +136 -0
  10. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_search_replace_dir_path.py +23 -0
  11. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/trip_log.md +120 -0
  12. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/uv.lock +1 -1
  13. drydock_cli-2.7.18/.auto_release.lock +0 -1
  14. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.claude/scheduled_tasks.lock +0 -0
  15. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.github/CODEOWNERS +0 -0
  16. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
  17. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  18. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  19. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.github/workflows/build-and-upload.yml +0 -0
  20. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.github/workflows/ci.yml +0 -0
  21. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.github/workflows/issue-labeler.yml +0 -0
  22. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.github/workflows/release.yml +0 -0
  23. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.gitignore +0 -0
  24. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.pre-commit-config.yaml +0 -0
  25. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.python-version +0 -0
  26. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.typos.toml +0 -0
  27. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.vscode/extensions.json +0 -0
  28. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.vscode/launch.json +0 -0
  29. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/.vscode/settings.json +0 -0
  30. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/AGENTS.md +0 -0
  31. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/Admiral.md +0 -0
  32. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/BASELINE_412.md +0 -0
  33. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/CHANGELOG.md +0 -0
  34. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/CLAUDE.md +0 -0
  35. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/CONTRIBUTING.md +0 -0
  36. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/DEPLOYMENT.md +0 -0
  37. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/Drydock_rebrand.md +0 -0
  38. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/LICENSE +0 -0
  39. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/MODEL_SHORTCOMINGS.md +0 -0
  40. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/NOTICE +0 -0
  41. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/OVERNIGHT_PROGRESS.md +0 -0
  42. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/OVERNIGHT_REPORT_2026_04_13.md +0 -0
  43. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/PRD.md +0 -0
  44. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/README.md +0 -0
  45. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/action.yml +0 -0
  46. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/README.md +0 -0
  47. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results1.tsv +0 -0
  48. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results13.tsv +0 -0
  49. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results14.tsv +0 -0
  50. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results15.tsv +0 -0
  51. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results16.tsv +0 -0
  52. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results17.tsv +0 -0
  53. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results18.tsv +0 -0
  54. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results19.tsv +0 -0
  55. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results2.tsv +0 -0
  56. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results20.tsv +0 -0
  57. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results3.tsv +0 -0
  58. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results4.tsv +0 -0
  59. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results5.tsv +0 -0
  60. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results6.tsv +0 -0
  61. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results7.tsv +0 -0
  62. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results8.tsv +0 -0
  63. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results9.tsv +0 -0
  64. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/baseline_history/results_evolved_v1.tsv +0 -0
  65. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/distribution/zed/LICENSE +0 -0
  66. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/distribution/zed/extension.toml +0 -0
  67. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/distribution/zed/icons/mistral_vibe.svg +0 -0
  68. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/docs/README.md +0 -0
  69. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/docs/acp-setup.md +0 -0
  70. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/docs/proxy-setup.md +0 -0
  71. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/__init__.py +0 -0
  72. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/acp/__init__.py +0 -0
  73. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/acp/acp_agent_loop.py +0 -0
  74. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/acp/acp_logger.py +0 -0
  75. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/acp/entrypoint.py +0 -0
  76. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/acp/tools/__init__.py +0 -0
  77. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/acp/tools/base.py +0 -0
  78. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/acp/tools/builtins/bash.py +0 -0
  79. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/acp/tools/builtins/read_file.py +0 -0
  80. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/acp/tools/builtins/search_replace.py +0 -0
  81. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/acp/tools/builtins/todo.py +0 -0
  82. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/acp/tools/builtins/write_file.py +0 -0
  83. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/acp/tools/session_update.py +0 -0
  84. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/acp/utils.py +0 -0
  85. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/__init__.py +0 -0
  86. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/detectors.py +0 -0
  87. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/detectors_proposed.py +0 -0
  88. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/history.py +0 -0
  89. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/interventions.py +0 -0
  90. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/llm_analyzer.py +0 -0
  91. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/metrics.py +0 -0
  92. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/opus_escalator.py +0 -0
  93. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/persistence.py +0 -0
  94. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/policy.py +0 -0
  95. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/proposer.py +0 -0
  96. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/stager.py +0 -0
  97. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/task_classifier.py +0 -0
  98. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/tuning.py +0 -0
  99. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/validator.py +0 -0
  100. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/admiral/worker.py +0 -0
  101. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/__init__.py +0 -0
  102. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/autocompletion/__init__.py +0 -0
  103. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/autocompletion/base.py +0 -0
  104. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/autocompletion/path_completion.py +0 -0
  105. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/autocompletion/slash_command.py +0 -0
  106. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/cli.py +0 -0
  107. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/clipboard.py +0 -0
  108. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/commands.py +0 -0
  109. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/entrypoint.py +0 -0
  110. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/history_manager.py +0 -0
  111. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
  112. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
  113. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
  114. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/terminal_setup.py +0 -0
  115. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/__init__.py +0 -0
  116. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
  117. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/app.py +0 -0
  118. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/app.tcss +0 -0
  119. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/external_editor.py +0 -0
  120. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
  121. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
  122. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
  123. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
  124. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
  125. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
  126. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
  127. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
  128. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
  129. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
  130. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
  131. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
  132. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
  133. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
  134. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
  135. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
  136. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
  137. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
  138. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/checkpoint_picker.py +0 -0
  139. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/compact.py +0 -0
  140. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
  141. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
  142. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
  143. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/loading.py +0 -0
  144. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/messages.py +0 -0
  145. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
  146. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
  147. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
  148. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
  149. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
  150. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
  151. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
  152. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
  153. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
  154. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/tools.py +0 -0
  155. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
  156. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
  157. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/windowing/history.py +0 -0
  158. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
  159. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/textual_ui/windowing/state.py +0 -0
  160. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/update_notifier/__init__.py +0 -0
  161. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
  162. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
  163. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
  164. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
  165. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
  166. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/update_notifier/update.py +0 -0
  167. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/cli/update_notifier/whats_new.py +0 -0
  168. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/__init__.py +0 -0
  169. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/agent_loop.py +0 -0
  170. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/agents/__init__.py +0 -0
  171. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/agents/manager.py +0 -0
  172. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/agents/models.py +0 -0
  173. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/auth/__init__.py +0 -0
  174. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/auth/crypto.py +0 -0
  175. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/auth/github.py +0 -0
  176. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/autocompletion/__init__.py +0 -0
  177. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/autocompletion/completers.py +0 -0
  178. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
  179. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
  180. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
  181. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/autocompletion/file_indexer/store.py +0 -0
  182. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
  183. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/autocompletion/fuzzy.py +0 -0
  184. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/autocompletion/path_prompt.py +0 -0
  185. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
  186. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/build_orchestrator.py +0 -0
  187. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/checkpoint.py +0 -0
  188. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/config/__init__.py +0 -0
  189. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/config/_settings.py +0 -0
  190. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/config/doctor.py +0 -0
  191. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/config/harness_files/__init__.py +0 -0
  192. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/config/harness_files/_harness_manager.py +0 -0
  193. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/config/harness_files/_paths.py +0 -0
  194. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/consultant.py +0 -0
  195. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/drydock_states.py +0 -0
  196. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/hooks.py +0 -0
  197. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/llm/__init__.py +0 -0
  198. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/llm/backend/anthropic.py +0 -0
  199. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/llm/backend/base.py +0 -0
  200. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/llm/backend/factory.py +0 -0
  201. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/llm/backend/generic.py +0 -0
  202. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/llm/backend/mistral.py +0 -0
  203. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
  204. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/llm/backend/vertex.py +0 -0
  205. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/llm/exceptions.py +0 -0
  206. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/llm/message_utils.py +0 -0
  207. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/llm/types.py +0 -0
  208. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/logger.py +0 -0
  209. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/middleware.py +0 -0
  210. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/output_formatters.py +0 -0
  211. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/paths/__init__.py +0 -0
  212. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/paths/_drydock_home.py +0 -0
  213. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/paths/_local_config_walk.py +0 -0
  214. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/paths/conventions.py +0 -0
  215. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/plan_session.py +0 -0
  216. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/plugins.py +0 -0
  217. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/programmatic.py +0 -0
  218. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/prompts/__init__.py +0 -0
  219. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/prompts/builder.md +0 -0
  220. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/prompts/cli.md +0 -0
  221. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/prompts/compact.md +0 -0
  222. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/prompts/dangerous_directory.md +0 -0
  223. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/prompts/diagnostic.md +0 -0
  224. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/prompts/explore.md +0 -0
  225. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/prompts/gemma4.md +0 -0
  226. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/prompts/planner.md +0 -0
  227. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/prompts/project_context.md +0 -0
  228. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/prompts/tests.md +0 -0
  229. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/proxy_setup.py +0 -0
  230. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/session/agent_memory.py +0 -0
  231. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/session/checkpoints.py +0 -0
  232. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/session/session_loader.py +0 -0
  233. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/session/session_logger.py +0 -0
  234. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/session/session_migration.py +0 -0
  235. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/session/state_file.py +0 -0
  236. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/session_checker.py +0 -0
  237. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/skills/__init__.py +0 -0
  238. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/skills/manager.py +0 -0
  239. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/skills/models.py +0 -0
  240. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/skills/parser.py +0 -0
  241. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/slug.py +0 -0
  242. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/system_prompt.py +0 -0
  243. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/telemetry/__init__.py +0 -0
  244. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/telemetry/send.py +0 -0
  245. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/teleport/errors.py +0 -0
  246. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/teleport/git.py +0 -0
  247. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/teleport/nuage.py +0 -0
  248. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/teleport/teleport.py +0 -0
  249. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/teleport/types.py +0 -0
  250. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/base.py +0 -0
  251. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/_task_manager.py +0 -0
  252. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/ask_user_question.py +0 -0
  253. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/bash.py +0 -0
  254. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/cron.py +0 -0
  255. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
  256. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/glob_tool.py +0 -0
  257. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/grep.py +0 -0
  258. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/invoke_skill.py +0 -0
  259. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/lsp.py +0 -0
  260. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/mcp_resources.py +0 -0
  261. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/notebook_edit.py +0 -0
  262. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/powershell.py +0 -0
  263. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
  264. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
  265. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/bash.md +0 -0
  266. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/cron.md +0 -0
  267. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/glob.md +0 -0
  268. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/grep.md +0 -0
  269. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/invoke_skill.md +0 -0
  270. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/lsp.md +0 -0
  271. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/mcp_resources.md +0 -0
  272. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
  273. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/powershell.md +0 -0
  274. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
  275. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
  276. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
  277. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/task.md +0 -0
  278. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
  279. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/todo.md +0 -0
  280. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/tool_search.md +0 -0
  281. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
  282. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
  283. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/worktree.md +0 -0
  284. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
  285. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/task.py +0 -0
  286. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/todo.py +0 -0
  287. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/tool_search.py +0 -0
  288. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/webfetch.py +0 -0
  289. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/websearch.py +0 -0
  290. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/worktree.py +0 -0
  291. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/builtins/write_file.py +0 -0
  292. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/injection_guard.py +0 -0
  293. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/manager.py +0 -0
  294. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/mcp/__init__.py +0 -0
  295. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/mcp/registry.py +0 -0
  296. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/mcp/tools.py +0 -0
  297. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/mcp_sampling.py +0 -0
  298. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/ui.py +0 -0
  299. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/tools/utils.py +0 -0
  300. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/trusted_folders.py +0 -0
  301. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/types.py +0 -0
  302. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/core/utils.py +0 -0
  303. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/setup/onboarding/__init__.py +0 -0
  304. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/setup/onboarding/base.py +0 -0
  305. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/setup/onboarding/onboarding.tcss +0 -0
  306. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/setup/onboarding/screens/__init__.py +0 -0
  307. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/setup/onboarding/screens/api_key.py +0 -0
  308. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/setup/onboarding/screens/choice.py +0 -0
  309. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/setup/onboarding/screens/local_model.py +0 -0
  310. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/setup/onboarding/screens/welcome.py +0 -0
  311. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
  312. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
  313. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/__init__.py +0 -0
  314. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/api-design/SKILL.md +0 -0
  315. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/audit-tests/SKILL.md +0 -0
  316. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/batch/SKILL.md +0 -0
  317. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/commit-code/SKILL.md +0 -0
  318. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/context-summary/SKILL.md +0 -0
  319. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/create-presentation/SKILL.md +0 -0
  320. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/deep-research/SKILL.md +0 -0
  321. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/deploy/SKILL.md +0 -0
  322. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/diff-review/SKILL.md +0 -0
  323. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/doc-gen/SKILL.md +0 -0
  324. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/explain-code/SKILL.md +0 -0
  325. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/explore-code/SKILL.md +0 -0
  326. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/fix-issue/SKILL.md +0 -0
  327. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/git-ops/SKILL.md +0 -0
  328. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/init-project/SKILL.md +0 -0
  329. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/investigate/SKILL.md +0 -0
  330. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/loop/SKILL.md +0 -0
  331. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/migrate/SKILL.md +0 -0
  332. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/perf-analyze/SKILL.md +0 -0
  333. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/plan-impl/SKILL.md +0 -0
  334. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/pr-review/SKILL.md +0 -0
  335. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/refactor/SKILL.md +0 -0
  336. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/regex-help/SKILL.md +0 -0
  337. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/review/SKILL.md +0 -0
  338. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/security-review/SKILL.md +0 -0
  339. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/ship/SKILL.md +0 -0
  340. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/simplify/SKILL.md +0 -0
  341. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/strong-tests/SKILL.md +0 -0
  342. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/skills/test-verify/SKILL.md +0 -0
  343. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock/whats_new.md +0 -0
  344. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock-acp.spec +0 -0
  345. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/drydock_terms.md +0 -0
  346. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/flake.lock +0 -0
  347. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/flake.nix +0 -0
  348. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/nohup.out +0 -0
  349. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/research/README.md +0 -0
  350. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/research/config_base.toml +0 -0
  351. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/research/config_best.toml +0 -0
  352. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/research/domain_spec.md +0 -0
  353. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/research/experimenter.py +0 -0
  354. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/research/kernel.py +0 -0
  355. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/research/mini_prd.md +0 -0
  356. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/research/mini_prompts.txt +0 -0
  357. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/research/proposer.py +0 -0
  358. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/research/results.tsv +0 -0
  359. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/resume.md +0 -0
  360. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/README.md +0 -0
  361. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/admiral_probe.py +0 -0
  362. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/audit_sampler.py +0 -0
  363. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/auto_generate_tests.py +0 -0
  364. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/auto_release.sh +0 -0
  365. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/auto_test_loop.sh +0 -0
  366. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/autonomous_review.sh +0 -0
  367. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/autonomous_review_prompt.md +0 -0
  368. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/backup.sh +0 -0
  369. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/bump_version.py +0 -0
  370. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/comprehensive_loop.py +0 -0
  371. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/deploy_to_github.sh +0 -0
  372. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/discover_cli_tools.sh +0 -0
  373. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/evolve_tests.py +0 -0
  374. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/gen_2000_prompts.py +0 -0
  375. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/install.sh +0 -0
  376. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/llm_balancer.py +0 -0
  377. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/mega_loop.py +0 -0
  378. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/meta_ralph_loop.py +0 -0
  379. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/monitor_swebench.sh +0 -0
  380. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/monitor_test_battery.sh +0 -0
  381. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/notify_release.py +0 -0
  382. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/oss_task_harness.py +0 -0
  383. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/overnight_agents_test.sh +0 -0
  384. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/poll_issues.sh +0 -0
  385. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/port_task.py +0 -0
  386. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/prepare_release.py +0 -0
  387. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/publish_to_pypi.sh +0 -0
  388. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/ralph_loop.py +0 -0
  389. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/research_babysitter.sh +0 -0
  390. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/session_loop_audit.py +0 -0
  391. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/shakedown.py +0 -0
  392. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/shakedown_interactive.py +0 -0
  393. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/shakedown_regression.sh +0 -0
  394. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/shakedown_suite.sh +0 -0
  395. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/shakedown_variance.sh +0 -0
  396. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/stress_prompts_50.txt +0 -0
  397. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/stress_prompts_realuser.txt +0 -0
  398. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/stress_prompts_tool_agent.txt +0 -0
  399. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/stress_prompts_tool_agent_2000.txt +0 -0
  400. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/stress_shakedown.py +0 -0
  401. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/stress_telegram_status.py +0 -0
  402. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/stress_watcher.py +0 -0
  403. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/telegram_bot.py +0 -0
  404. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/test_bank.sh +0 -0
  405. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/test_full.sh +0 -0
  406. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/test_smoke.sh +0 -0
  407. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/test_tui_path.py +0 -0
  408. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/tui_test.py +0 -0
  409. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/scripts/vllm_failover.sh +0 -0
  410. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/test/project/dummy +0 -0
  411. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/__init__.py +0 -0
  412. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/conftest.py +0 -0
  413. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_acp.py +0 -0
  414. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_agent_thought.py +0 -0
  415. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_bash.py +0 -0
  416. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_compact_session_updates.py +0 -0
  417. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_content.py +0 -0
  418. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_initialize.py +0 -0
  419. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_list_sessions.py +0 -0
  420. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_load_session.py +0 -0
  421. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_multi_session.py +0 -0
  422. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_new_session.py +0 -0
  423. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_proxy_setup_acp.py +0 -0
  424. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_read_file.py +0 -0
  425. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_search_replace.py +0 -0
  426. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_set_config_option.py +0 -0
  427. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_set_mode.py +0 -0
  428. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_set_model.py +0 -0
  429. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_tool_call_session_update.py +0 -0
  430. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_utils.py +0 -0
  431. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/acp/test_write_file.py +0 -0
  432. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/autocompletion/test_file_indexer.py +0 -0
  433. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/autocompletion/test_fuzzy.py +0 -0
  434. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
  435. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/autocompletion/test_path_completer_recursive.py +0 -0
  436. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/autocompletion/test_path_completion_controller.py +0 -0
  437. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
  438. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/autocompletion/test_slash_command_controller.py +0 -0
  439. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
  440. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/backend/__init__.py +0 -0
  441. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/backend/data/__init__.py +0 -0
  442. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/backend/data/fireworks.py +0 -0
  443. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/backend/data/mistral.py +0 -0
  444. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/backend/test_anthropic_adapter.py +0 -0
  445. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/backend/test_backend.py +0 -0
  446. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/backend/test_generic_adapter_sanitize.py +0 -0
  447. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/backend/test_reasoning_adapter.py +0 -0
  448. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
  449. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
  450. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
  451. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
  452. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/test_bell_notifications.py +0 -0
  453. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/test_braille_renderer.py +0 -0
  454. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/test_clipboard.py +0 -0
  455. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/test_commands.py +0 -0
  456. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/test_copy_shortcuts.py +0 -0
  457. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/test_external_editor.py +0 -0
  458. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/test_no_markup_static.py +0 -0
  459. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/test_question_app.py +0 -0
  460. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/test_spinner.py +0 -0
  461. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/test_switching_mode.py +0 -0
  462. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/test_ui_clipboard_notifications.py +0 -0
  463. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
  464. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/test_ui_session_resume.py +0 -0
  465. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/test_ui_skill_dispatch.py +0 -0
  466. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/textual_ui/__init__.py +0 -0
  467. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/cli/textual_ui/test_session_picker.py +0 -0
  468. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/conftest.py +0 -0
  469. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_agents.py +0 -0
  470. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_auth_crypto.py +0 -0
  471. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_auth_github.py +0 -0
  472. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_circuit_breaker_readonly_threshold.py +0 -0
  473. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_config_load_dotenv.py +0 -0
  474. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_config_paths.py +0 -0
  475. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_config_resolution.py +0 -0
  476. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_file_logging.py +0 -0
  477. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_plan_session.py +0 -0
  478. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_proxy_setup.py +0 -0
  479. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_slug.py +0 -0
  480. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_telemetry_send.py +0 -0
  481. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_teleport_git.py +0 -0
  482. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_teleport_nuage.py +0 -0
  483. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_teleport_service.py +0 -0
  484. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_trusted_folders.py +0 -0
  485. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/core/test_utils.py +0 -0
  486. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/e2e/common.py +0 -0
  487. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/e2e/conftest.py +0 -0
  488. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/e2e/mock_server.py +0 -0
  489. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/e2e/test_cli_tui_onboarding.py +0 -0
  490. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/e2e/test_cli_tui_streaming.py +0 -0
  491. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
  492. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/fixtures/doc_qa_system_prd.md +0 -0
  493. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/mock/__init__.py +0 -0
  494. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/mock/mock_backend_factory.py +0 -0
  495. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/mock/mock_entrypoint.py +0 -0
  496. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/mock/utils.py +0 -0
  497. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/onboarding/test_run_onboarding.py +0 -0
  498. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/onboarding/test_ui_onboarding.py +0 -0
  499. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/session/test_session_loader.py +0 -0
  500. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/session/test_session_logger.py +0 -0
  501. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/session/test_session_migration.py +0 -0
  502. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/skills/conftest.py +0 -0
  503. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/skills/test_manager.py +0 -0
  504. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/skills/test_models.py +0 -0
  505. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/skills/test_parser.py +0 -0
  506. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
  507. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
  508. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
  509. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
  510. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
  511. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
  512. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
  513. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
  514. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
  515. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
  516. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
  517. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
  518. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
  519. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
  520. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
  521. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
  522. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
  523. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
  524. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
  525. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
  526. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
  527. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
  528. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
  529. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
  530. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
  531. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
  532. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
  533. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
  534. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
  535. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
  536. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
  537. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
  538. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
  539. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
  540. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
  541. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
  542. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
  543. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
  544. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
  545. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
  546. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
  547. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
  548. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
  549. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
  550. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
  551. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
  552. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
  553. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
  554. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
  555. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
  556. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
  557. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
  558. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
  559. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
  560. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
  561. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
  562. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
  563. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
  564. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
  565. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
  566. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/base_snapshot_test_app.py +0 -0
  567. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/conftest.py +0 -0
  568. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/snap_compare.py +0 -0
  569. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
  570. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
  571. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
  572. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
  573. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
  574. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
  575. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
  576. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
  577. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
  578. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
  579. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
  580. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
  581. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
  582. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
  583. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/stubs/fake_backend.py +0 -0
  584. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/stubs/fake_client.py +0 -0
  585. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/stubs/fake_tool.py +0 -0
  586. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_admiral.py +0 -0
  587. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_admiral_phase3.py +0 -0
  588. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_admiral_proposed.py +0 -0
  589. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_admiral_struggle_dedup.py +0 -0
  590. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_agent_auto_compact.py +0 -0
  591. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_agent_backend.py +0 -0
  592. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_agent_observer_streaming.py +0 -0
  593. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_agent_stats.py +0 -0
  594. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_agent_tasks.py +0 -0
  595. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_agent_tool_call.py +0 -0
  596. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_agents.py +0 -0
  597. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_bank_build.py +0 -0
  598. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_bank_debug.py +0 -0
  599. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_bank_multiagent.py +0 -0
  600. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_bank_prd.py +0 -0
  601. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_bank_prd_extended.py +0 -0
  602. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_bank_tools.py +0 -0
  603. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_bank_update.py +0 -0
  604. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_build_projects.py +0 -0
  605. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_checkpoint.py +0 -0
  606. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_cli_programmatic_preload.py +0 -0
  607. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_current_bugs.py +0 -0
  608. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_drydock_regression.py +0 -0
  609. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_drydock_tasks.py +0 -0
  610. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_fake_tool_call_paren_syntax.py +0 -0
  611. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_full_regression.py +0 -0
  612. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_history_manager.py +0 -0
  613. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_integration.py +0 -0
  614. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_issue_fixes.py +0 -0
  615. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_loop_detection.py +0 -0
  616. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_message_id.py +0 -0
  617. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_message_merging.py +0 -0
  618. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_middleware.py +0 -0
  619. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_multi_agent.py +0 -0
  620. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_read_file_not_found_listing.py +0 -0
  621. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_real_failures.py +0 -0
  622. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_real_issues.py +0 -0
  623. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_real_workflow.py +0 -0
  624. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_reasoning_content.py +0 -0
  625. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_smoke.py +0 -0
  626. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_system_prompt.py +0 -0
  627. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_tagged_text.py +0 -0
  628. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_tool_args.py +0 -0
  629. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_truncate_args_valid_json.py +0 -0
  630. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_truncated_arg_path_hint.py +0 -0
  631. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_ui_external_editor.py +0 -0
  632. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_ui_input_history.py +0 -0
  633. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_user_issues.py +0 -0
  634. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_wall_of_text_rescue.py +0 -0
  635. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_workloads.py +0 -0
  636. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/test_write_file_missing_path.py +0 -0
  637. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/testbank_helpers.py +0 -0
  638. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_ask_user_question.py +0 -0
  639. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_bash.py +0 -0
  640. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_exit_plan_mode.py +0 -0
  641. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_grep.py +0 -0
  642. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_invoke_context.py +0 -0
  643. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_manager_gemma_derived_models.py +0 -0
  644. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_manager_get_tool_config.py +0 -0
  645. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_mcp.py +0 -0
  646. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_mcp_sampling.py +0 -0
  647. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_read_file_directory.py +0 -0
  648. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_read_file_limit_truncation.py +0 -0
  649. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_search_replace_append_fallback.py +0 -0
  650. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_search_replace_empty_content.py +0 -0
  651. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_search_replace_hard_stop.py +0 -0
  652. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_search_replace_no_op_loop_breaker.py +0 -0
  653. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_search_replace_refused_loop_breaker.py +0 -0
  654. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_task.py +0 -0
  655. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_ui_bash_execution.py +0 -0
  656. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_webfetch.py +0 -0
  657. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_websearch.py +0 -0
  658. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_write_file_dedup_missing_imports.py +0 -0
  659. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/tools/test_write_file_missing_path_hint.py +0 -0
  660. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
  661. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
  662. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/update_notifier/test_do_update.py +0 -0
  663. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
  664. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/update_notifier/test_github_update_gateway.py +0 -0
  665. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
  666. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/update_notifier/test_ui_update_notification.py +0 -0
  667. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/update_notifier/test_update_use_case.py +0 -0
  668. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/tests/update_notifier/test_whats_new.py +0 -0
  669. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/worked_examples/README.md +0 -0
  670. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/worked_examples/cli_subcommand_dispatch.py +0 -0
  671. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/worked_examples/lookup.json +0 -0
  672. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/worked_examples/sql_parser.py +0 -0
  673. {drydock_cli-2.7.18 → drydock_cli-2.7.20}/worked_examples/tree_walking_interpreter.py +0 -0
@@ -0,0 +1 @@
1
+ 404218
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 2.7.18
3
+ Version: 2.7.20
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
@@ -169,6 +169,11 @@ class ResolvedMessage(BaseModel):
169
169
 
170
170
 
171
171
  class APIToolFormatHandler:
172
+ def __init__(self) -> None:
173
+ # Track per-path truncated-history write_file retries so we can
174
+ # escalate on 2nd+ identical failures (model ignores advisory-only msgs).
175
+ self._truncated_hit_count: dict[str, int] = {}
176
+
172
177
  @property
173
178
  def name(self) -> str:
174
179
  return "api"
@@ -379,6 +384,12 @@ class APIToolFormatHandler:
379
384
  path_hint = (parsed_call.raw_args.get("path")
380
385
  or parsed_call.raw_args.get("file_path")
381
386
  or "")
387
+ # Track retry count per path to escalate on 2nd+ offense.
388
+ hit_key = path_hint or "<unknown>"
389
+ hit_count = self._truncated_hit_count.get(hit_key, 0) + 1
390
+ self._truncated_hit_count[hit_key] = hit_count
391
+ escalate = hit_count >= 2
392
+
382
393
  # Auto-embed the current file content so the model can
383
394
  # rewrite immediately without an extra read_file round-trip.
384
395
  file_embed = ""
@@ -407,6 +418,31 @@ class APIToolFormatHandler:
407
418
  pass
408
419
  if not file_embed and path_hint:
409
420
  file_embed = f" Re-read `{path_hint}` with read_file first."
421
+
422
+ if escalate:
423
+ # Model is stuck in a truncated-template retry loop.
424
+ # Show project files and give a concrete directive.
425
+ try:
426
+ py_files = sorted(
427
+ str(p2.relative_to(Path.cwd()))
428
+ for p2 in Path.cwd().rglob("*.py")
429
+ if "__pycache__" not in str(p2) and ".git" not in str(p2)
430
+ )[:20]
431
+ dir_listing = "\n".join(f" {f}" for f in py_files)
432
+ except Exception:
433
+ dir_listing = " (could not list files)"
434
+ escalation_suffix = (
435
+ f"\n\n[REPEATED FAILURE #{hit_count}: your write_file call "
436
+ f"keeps using a stale truncated template for '{path_hint}'. "
437
+ f"You MUST type fresh content — do NOT copy from history. "
438
+ f"Current .py files in project:\n{dir_listing}\n"
439
+ f"Use read_file on the target file, then call write_file "
440
+ f"with fully typed content, OR use search_replace to make "
441
+ f"targeted edits without rewriting the whole file.]"
442
+ )
443
+ else:
444
+ escalation_suffix = ""
445
+
410
446
  failed_calls.append(
411
447
  FailedToolCall(
412
448
  tool_name=parsed_call.tool_name,
@@ -415,7 +451,8 @@ class APIToolFormatHandler:
415
451
  f"your call used a "
416
452
  f"truncated history entry as a template (it contained "
417
453
  f"'_truncated'/'_original_bytes' instead of real "
418
- f"arguments).{file_embed} Provide the full required arguments."
454
+ f"arguments).{file_embed} Provide the full required "
455
+ f"arguments.{escalation_suffix}"
419
456
  ),
420
457
  )
421
458
  )
@@ -111,19 +111,29 @@ 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
 
@@ -151,6 +161,8 @@ class ReadFile(
151
161
  "timestamp": current_mtime,
152
162
  "offset": args.offset,
153
163
  "limit": args.limit,
164
+ "lines_read": len(read_result.lines),
165
+ "was_truncated": read_result.was_truncated,
154
166
  }
155
167
 
156
168
  yield ReadFileResult(
@@ -175,17 +175,46 @@ class SearchReplace(
175
175
  # Model passed a directory instead of a file path.
176
176
  # Return a result (not raise) so the model corrects the call
177
177
  # rather than retrying the same directory path in a loop.
178
+ # Track consecutive calls to escalate guidance on 2nd+ offense.
178
179
  dir_path_str = args.file_path.strip()
179
180
  dir_path = Path(dir_path_str).expanduser()
180
181
  if not dir_path.is_absolute():
181
182
  dir_path = Path.cwd() / dir_path
182
183
  dir_path = dir_path.resolve()
183
184
  if dir_path.is_dir():
185
+ dir_state = self.state.__dict__.setdefault("_sr_dir_history", {})
186
+ dir_key = str(dir_path)
187
+ dir_entry = dir_state.get(dir_key, {"count": 0})
188
+ dir_entry["count"] += 1
189
+ dir_state[dir_key] = dir_entry
190
+ dir_count = dir_entry["count"]
184
191
  try:
185
192
  files = sorted(p.name for p in dir_path.iterdir() if p.is_file())
186
193
  except OSError:
187
194
  files = []
188
195
  files_list = "\n".join(f" {f}" for f in files[:20]) or " (empty directory)"
196
+ if dir_count >= 2:
197
+ # Escalate: model retried the same directory path — add project listing
198
+ try:
199
+ py_files = sorted(
200
+ str(p.relative_to(Path.cwd()))
201
+ for p in Path.cwd().rglob("*.py")
202
+ if "__pycache__" not in str(p) and ".git" not in str(p)
203
+ )[:20]
204
+ project_listing = (
205
+ f"\n[REPEATED ERROR #{dir_count}: you have called search_replace on "
206
+ f"this directory {dir_count} times. You MUST specify a filename. "
207
+ f"Project .py files:\n"
208
+ + "\n".join(f" {f}" for f in py_files)
209
+ + "\nUse the exact path from this list.]"
210
+ )
211
+ except Exception:
212
+ project_listing = (
213
+ f"\n[REPEATED ERROR #{dir_count}: stop passing the directory. "
214
+ "Use a full file path like 'tool_agent/cli.py'.]"
215
+ )
216
+ else:
217
+ project_listing = ""
189
218
  yield SearchReplaceResult(
190
219
  file=str(dir_path),
191
220
  blocks_applied=0,
@@ -195,7 +224,8 @@ class SearchReplace(
195
224
  f"search_replace requires a path to a specific file.\n"
196
225
  f"Files in that directory:\n{files_list}\n"
197
226
  f"Specify the full path including the filename, e.g. "
198
- f"'{dir_path}/<filename.py>'"
227
+ f"'{dir_path}/{files[0] if files else '<filename.py>'}'"
228
+ + project_listing
199
229
  ),
200
230
  )
201
231
  return
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "drydock-cli"
3
- version = "2.7.18"
3
+ version = "2.7.20"
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"
@@ -28,8 +28,8 @@ PID_FILE=/tmp/stress_pid.txt
28
28
  # /tmp/stress_2000_*.log. Avoids the stale-log bug where babysitter reported
29
29
  # COMPLETE for hours while the real harness kept processing (2026-04-25).
30
30
  # Falls back to the prior hardcoded path if no match exists yet.
31
- STRESS_LOG=$(ls -t /tmp/stress_2000_*.log 2>/dev/null | head -1)
32
- STRESS_LOG=${STRESS_LOG:-/tmp/stress_2000_v10_restart_1777237201.log}
31
+ STRESS_LOG=/tmp/stress_2000_v10_restart_1777453487.log
32
+ STRESS_LOG=/tmp/stress_2000_v10_restart_1777453487.log
33
33
  NOTIFY=/data3/drydock/scripts/notify_release.py
34
34
  PY_CONDA=/home/bobef/miniconda3/bin/python3
35
35
  PY_DRYDOCK=/home/bobef/miniforge3/envs/drydock/bin/python3
@@ -0,0 +1,104 @@
1
+ """Regression test: truncated write_file retry loop escalation.
2
+
3
+ When Gemma 4 calls write_file with _truncated args (copied from a pruned history
4
+ entry), drydock returns a FailedToolCall. The model often retries identically
5
+ instead of correcting the call, creating an 8-10 turn loop (observed in stress run
6
+ 2026-04-29, ~8 fires of retry_after_error:write_file:truncated history in 7 min).
7
+
8
+ Fix: APIToolFormatHandler tracks per-path truncated-arg hit count. On the 2nd+
9
+ identical failure for the same path, the error message is escalated with a project
10
+ file listing and a concrete directive to type fresh content or use search_replace.
11
+ """
12
+ from __future__ import annotations
13
+
14
+ from unittest.mock import MagicMock
15
+
16
+ from drydock.core.llm.format import APIToolFormatHandler, ParsedMessage, ParsedToolCall
17
+ from drydock.core.tools.builtins.write_file import WriteFile
18
+
19
+
20
+ def _make_tm():
21
+ tm = MagicMock()
22
+ tm.available_tools = {"write_file": WriteFile}
23
+ return tm
24
+
25
+
26
+ def _truncated_call(path: str, call_id: str = "tc1") -> ParsedMessage:
27
+ return ParsedMessage(
28
+ tool_calls=[
29
+ ParsedToolCall(
30
+ tool_name="write_file",
31
+ call_id=call_id,
32
+ raw_args={
33
+ "_truncated": True,
34
+ "_original_bytes": 4096,
35
+ "file_path": path,
36
+ },
37
+ )
38
+ ]
39
+ )
40
+
41
+
42
+ class TestTruncatedWriteEscalation:
43
+ def test_first_hit_no_escalation(self, tmp_path):
44
+ """First truncated-arg failure returns normal advisory, no escalation block."""
45
+ target = tmp_path / "cli.py"
46
+ target.write_text("print('hello')\n")
47
+ handler = APIToolFormatHandler()
48
+ result = handler.resolve_tool_calls(_truncated_call(str(target)), _make_tm())
49
+ err = result.failed_calls[0].error
50
+ assert "REPEATED FAILURE" not in err
51
+ assert "truncated" in err.lower()
52
+
53
+ def test_second_hit_escalates(self, tmp_path):
54
+ """Second truncated-arg failure for the same path triggers escalation block."""
55
+ target = tmp_path / "cli.py"
56
+ target.write_text("print('hello')\n")
57
+ handler = APIToolFormatHandler()
58
+ # First call
59
+ handler.resolve_tool_calls(_truncated_call(str(target), "tc1"), _make_tm())
60
+ # Second call — should escalate
61
+ result = handler.resolve_tool_calls(_truncated_call(str(target), "tc2"), _make_tm())
62
+ err = result.failed_calls[0].error
63
+ assert "REPEATED FAILURE #2" in err
64
+ assert "stale truncated template" in err
65
+ assert "search_replace" in err
66
+
67
+ def test_third_hit_increments_count(self, tmp_path):
68
+ """Third hit shows #3 in the escalation message."""
69
+ target = tmp_path / "utils.py"
70
+ target.write_text("x = 1\n")
71
+ handler = APIToolFormatHandler()
72
+ for i in range(3):
73
+ result = handler.resolve_tool_calls(
74
+ _truncated_call(str(target), f"tc{i}"), _make_tm()
75
+ )
76
+ err = result.failed_calls[0].error
77
+ assert "REPEATED FAILURE #3" in err
78
+
79
+ def test_different_paths_tracked_separately(self, tmp_path):
80
+ """Two different paths each have their own hit counter."""
81
+ a = tmp_path / "a.py"
82
+ b = tmp_path / "b.py"
83
+ a.write_text("pass\n")
84
+ b.write_text("pass\n")
85
+ handler = APIToolFormatHandler()
86
+ # Hit path a twice → escalate
87
+ handler.resolve_tool_calls(_truncated_call(str(a), "tc1"), _make_tm())
88
+ result_a = handler.resolve_tool_calls(_truncated_call(str(a), "tc2"), _make_tm())
89
+ assert "REPEATED FAILURE #2" in result_a.failed_calls[0].error
90
+ # Hit path b once → no escalation
91
+ result_b = handler.resolve_tool_calls(_truncated_call(str(b), "tc3"), _make_tm())
92
+ assert "REPEATED FAILURE" not in result_b.failed_calls[0].error
93
+
94
+ def test_fresh_handler_resets_count(self, tmp_path):
95
+ """A new APIToolFormatHandler instance starts with a clean counter."""
96
+ target = tmp_path / "main.py"
97
+ target.write_text("pass\n")
98
+ handler1 = APIToolFormatHandler()
99
+ handler1.resolve_tool_calls(_truncated_call(str(target), "tc1"), _make_tm())
100
+ handler1.resolve_tool_calls(_truncated_call(str(target), "tc2"), _make_tm())
101
+ # Fresh handler for a new session — no accumulated state
102
+ handler2 = APIToolFormatHandler()
103
+ result = handler2.resolve_tool_calls(_truncated_call(str(target), "tc3"), _make_tm())
104
+ assert "REPEATED FAILURE" not in result.failed_calls[0].error
@@ -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
@@ -89,3 +89,26 @@ async def test_directory_path_repeated_call_still_returns_result(tool, ctx, tmp_
89
89
  assert isinstance(result, SearchReplaceResult)
90
90
  assert result.blocks_applied == 0
91
91
  assert "PATH ERROR" in result.content
92
+
93
+
94
+ @pytest.mark.asyncio
95
+ async def test_directory_path_escalates_on_second_call(tool, ctx, tmp_path):
96
+ """Second call with the same directory path includes REPEATED ERROR escalation."""
97
+ (tmp_path / "cli.py").write_text("x = 1\n")
98
+ args = SearchReplaceArgs(
99
+ file_path=str(tmp_path),
100
+ content="<<<<<<< SEARCH\nold\n=======\nnew\n>>>>>>> REPLACE",
101
+ )
102
+ # First call — no escalation
103
+ results1 = await _collect(tool.run(args, ctx))
104
+ assert "REPEATED ERROR" not in results1[-1].content
105
+
106
+ # Second call — escalation fires
107
+ results2 = await _collect(tool.run(args, ctx))
108
+ assert "REPEATED ERROR" in results2[-1].content
109
+ assert "#2" in results2[-1].content
110
+
111
+ # Third call — escalation still present with updated count
112
+ results3 = await _collect(tool.run(args, ctx))
113
+ assert "REPEATED ERROR" in results3[-1].content
114
+ assert "#3" in results3[-1].content
@@ -3,6 +3,38 @@
3
3
  Autonomous Claude Code review ticks while the user is away. Each tick appended
4
4
  chronologically. Cron-driven every 30 min from `/data3/drydock/scripts/autonomous_review.sh`.
5
5
 
6
+ ## 2026-04-29 08:34 UTC tick
7
+ - Stress: 229/1658 (PID 270529, new run started ~Apr 29 03:26 UTC; progressing)
8
+ - Write rate: 19% (last 100 prompts) — early in sequence; previous run was at 73% at prompts 1550-1650, not a fair comparison; new run at prompt 225 already has 52 writes vs 0 in prev run at same point, so actually running better
9
+ - Admiral last 30 min: struggle:66-76 (model made 76 reads without writing; ended on its own); loop:bash --help x1; retry_after_error:search_replace directory path x1; empty_after_tool:read_file x1 — all known model-behavior patterns
10
+ - vLLM 400s: 0
11
+ - GH issues: 0 open
12
+ - Action this tick: no fix committed; b2f26aa (search_replace dir-path escalation) is unshipped pending next auto_release at ~12:00 UTC; skip rate 24% is higher than prev run's 7% at same point but this is variance from model being in 76-read struggle sessions, not a drydock bug
13
+
14
+ ## 2026-04-29 08:01 UTC tick
15
+ - Stress: 207/1658 (PID 270529, new run from babysitter restart; progressing normally)
16
+ - Write rate: 15% (expected — prompts 200-207 are analysis queries: function_count, class_count, test_file_count, etc., no file writes expected)
17
+ - Admiral last 30 min: struggle events firing at 70+ consecutive non-write tool calls; empty_after_tool:read_file x4 (all handled by stall retry); one empty_after_tool:web_search — all normal model-behavior noise
18
+ - vLLM 400s: 0
19
+ - GH issues: 0 open
20
+ - Action this tick: No fix committed. All systems healthy. Commit b2f26aa (search_replace: escalate directory-path error on 2nd+ repeated call) is staged ahead of v2.7.19 tag, will auto-release as v2.7.20 at 12:00 UTC.
21
+
22
+ ## 2026-04-29 06:10 UTC tick
23
+ - Stress: 141/1658 (PID 270529, new run started by babysitter; prior run PID 3713698 dead)
24
+ - Write rate: 38% (significant regression from 74% sustained — SKIP rate 44% vs 13% baseline in prior run)
25
+ - Admiral last 30 min: loop:bash, loop:search_replace, loop:read_file, struggle:search_replace all firing — normal model-behavior noise
26
+ - vLLM 400s: 0
27
+ - GH issues: 0 open
28
+ - Action this tick: No fix committed. Investigated SKIP regression: 62/141 prompts skipped with "TUI did not accept after 3 retries". SKIPs began at prompt 10 in the very first session. Pattern suggests TUI is busy processing previous turn output when harness sends next prompt; watcher times out after 3×120s without seeing new user message in session log. v2.7.18 read_file escalation changes (2nd+ identical dedup escalates with full context) may be causing model to stay in extended tool-call loops after each turn "completes", keeping the session non-quiet. No actionable drydock source fix identified within budget — flagged for user to investigate on return (2026-05-01).
29
+
30
+ ## 2026-04-29 04:35 UTC tick
31
+ - Stress: 128/1658 (new run restarted by babysitter; prior run PID 3713698 dead at 680/1658)
32
+ - Write rate: 39% (was 74% sustained — SKIP rate elevated at ~30% vs 8% baseline)
33
+ - Admiral last 30 min: active — loop:read_file(tool_agent/cli.py, limit=100) firing repeatedly; struggle:search_replace counts reaching 30-36 per prompt
34
+ - vLLM 400s: 0
35
+ - GH issues: 0 open
36
+ - Action this tick: triggered manual auto_release to ship v2.7.18 early (tagged, PyPI upload confirmed). The 4 unreleased commits (read_file pagination hint, search_replace empty-content soft advisory, write_file dir-path detection, write_file path inference) directly address the read_file loop pattern visible in admiral logs: model reads cli.py with limit=100, gets no truncation hint, retries identically 3+ times, then struggles with search_replace on text it couldn't see. v2.7.18 adds the pagination hint that breaks this cycle. Stress run is live at 128/1658 and will pick up v2.7.18 at next session reset.
37
+
6
38
  **Pause loop:** `touch /data3/drydock/.pause_autonomous_loop`
7
39
  **Resume loop:** `rm /data3/drydock/.pause_autonomous_loop`
8
40
  **Live log:** `/data3/drydock/logs/autonomous_review.log` (full Claude output + errors)
@@ -466,3 +498,91 @@ restarted, cron self-match bug fixed in this same session).
466
498
  - GH issues: 0 open
467
499
  - Services: llm_balancer PID 24354 on :8001 healthy, vLLM gemma4 up, balancer curl verified
468
500
  - Action this tick: committed fix (11f1752) — search_replace empty-content ToolError converted to soft advisory SearchReplaceResult; tracks consecutive empty-content calls per file and escalates with project file listing on 2nd+ offense; 3 regression tests added; auto-ships as v2.7.18 at next 06:00 UTC cron tick
501
+
502
+ ## 2026-04-29 05:10 UTC tick
503
+ - Stress: 132/1658 (new run, PID 270529, log /tmp/stress_2000_1777408317.log, 8.5h elapsed)
504
+ - Write rate: 40% (last 65 prompts)
505
+ - SKIP rate: 55/132 (42%) — TUI queuing stress prompts while busy; harness detection mismatch, not a drydock bug
506
+ - Admiral last 30 min: loop:read_file (cli.py, limit=100) ~6 fires, struggle:search_replace ~10 fires, empty_after_tool 2 fires
507
+ - vLLM 400s: 0
508
+ - GH issues: 0 open
509
+ - Action this tick: committed fix(read_file): re-embed cached content on dedup — when _truncate_old_tool_results pruned the earlier tool_result, the dedup stub pointed at absent content causing re-read loops; now embeds cached content directly. 3 regression tests added. Will ship at next 0/6/12/18 UTC auto-release tick.
510
+
511
+ ## 2026-04-29 05:50 UTC tick
512
+ - Stress: 137/1658 (PID 270529 alive, new run restarted from 0 since previous tick; babysitter keeps it alive)
513
+ - Write rate: 32% (last 50 completed prompts; low due to high SKIP rate and lightweight utility prompts)
514
+ - SKIP rate: 66/137 = 48% (elevated; concentrated in timezone/date-util prompts where TUI is busy with prior session)
515
+ - Admiral last 30 min: 25 fires — loop:read_file::cli.py(limit=100) dominant (30+ occurrences across session), struggle:search_replace, empty_after_tool all known patterns
516
+ - vLLM 400s: 0
517
+ - GH issues: 0 open
518
+ - Services: llm_balancer PID 24354 on :8001 healthy, vLLM gemma4 container up, stress harness PID 270529 running
519
+ - Action this tick: committed fix(read_file) ff5217d — escalating REPEATED READ #N advisory on 2nd+ identical dedup read; 1 new regression test (4 total in test file pass); auto-ships at next 0/6/12/18 UTC tick
520
+
521
+ ## 2026-04-29 06:40 UTC tick
522
+ - Stress: 146/1658 (PID 270529 alive; new run restarted from 0 by babysitter; old run 3713698 gone)
523
+ - Write rate: 26/67 = 38% (last 100 completed prompts)
524
+ - SKIP rate: 45/141 = 32% — TUI busy; FORCE-RESETs unsticking; known pattern
525
+ - Admiral last 30 min: struggle:search_replace (27-46 calls, single long session at 06:05-06:07 UTC); loop:read_file::cli.py(limit=100) and loop:search_replace at 06:28-06:31 UTC; empty_after_tool:read_file 1 fire
526
+ - vLLM 400s: 0
527
+ - GH issues: 0 open
528
+ - Services: llm_balancer PID 24354 on :8001 healthy, vLLM gemma4 up, stress harness PID 270529 running
529
+ - Action this tick: triggered manual auto_release (v2.7.19) to ship read_file dedup fixes (ff5217d, 3fc4e4b) committed earlier this session but missed by midnight cron; PyPI upload OK; installed wheel directly into user's env; all prior fixes (search_replace HARD-STOP loop-breaker, dedup re-embed, escalating dedup advisory) now live
530
+
531
+ ## 2026-04-29 07:03 UTC tick
532
+ - Stress: 149/1658 (PID 270529 alive, new run; babysitter restarted from 0 at ~00:30 UTC)
533
+ - Write rate: 38% overall (26/67 completed prompts), 32% last 50; lightweight utility prompts at start of run
534
+ - SKIP rate: ~45% (TUI busy; FORCE-RESETs happening; known harness/TUI timing mismatch)
535
+ - Admiral last 30 min: struggle:search_replace (35-call streak), loop:read_file::cli.py, loop:search_replace (identical blocks), retry_after_error:search_replace (directory path)
536
+ - vLLM 400s: 0
537
+ - GH issues: 0 open
538
+ - Services: llm_balancer PID 24354 on :8001 healthy, vLLM gemma4 up, stress PID 270529 running
539
+ - Action this tick: committed fix(search_replace) b2f26aa — escalate directory-path error on 2nd+ repeat; model was getting same PATH ERROR advisory each time and retrying indefinitely; now get REPEATED ERROR #N + full project .py listing on 2nd+ offense; 4 regression tests (all pass); auto-ships at next 0/6/12/18 UTC auto-release tick
540
+
541
+ ## 2026-04-29 07:33 UTC tick
542
+ - Stress: 680/1658 (41%; PID 270529 alive, 11h elapsed)
543
+ - Write rate: 32% last 100 prompts (down from 74% peak); prompt section now at "API: WebSocket/SSE/JSON-RPC/gRPC" + tool-existence queries — model explores codebase but writes 0 files for most; expected given prompt difficulty
544
+ - SKIP rate: 80 total SKIPs; prompts 677-679 SKIPped consecutively after 21-msg/7-write WebSocket session; harness FORCE-RESET unstuck it; prompt 680 currently in progress
545
+ - Admiral last 30 min: struggle:40-70 tool calls without writes (multiple interventions 07:23-07:30 UTC); model reading extensively for API-type prompts; admiral correctly firing; no new admiral pattern
546
+ - vLLM 400s: 0
547
+ - GH issues: 0 open
548
+ - Services: llm_balancer PID 24354 on :8001 healthy (confirmed curl), vLLM gemma4 up, stress PID 270529 running, admiral_probe PID 4075121 on :8878
549
+ - Unshipped: b2f26aa (search_replace dir-path escalation) will ship at next auto-release ~11:00 UTC
550
+ - Action this tick: no action — system healthy; write rate dip is prompt-section artifact (API/question prompts), not a drydock regression; no new bugs found
551
+
552
+ ## 2026-04-29 09:15 UTC tick
553
+ - Stress: 232/1658 (PID 270529 was stuck for 5+ hours; killed and restarted as PID 387049 resuming from step 175)
554
+ - Write rate: 19% last 100 prompts (expected — prompts 1-232 are single-word CLI invocations, not write tasks)
555
+ - SKIP rate: 24% (55 skips at idx=232; consistent with early-run pattern, normalizes over time)
556
+ - Admiral last 30 min: loop:bash::--help, retry_after_error:bash, loop:read_file::cli.py(limit=100), retry_after_error:search_replace (directory path repeats); all normal patterns
557
+ - vLLM 400s: 0
558
+ - GH issues: 0 open
559
+ - Services: llm_balancer healthy on :8001, vLLM gemma4 healthy (Running: 0 reqs), stress harness PID 387049 resuming from step 175
560
+ - Action this tick: killed stuck harness PID 270529 (TUI child 270531 was stuck in "Observing..." for 5h with no model response; vLLM healthy so likely pexpect stream deadlock); restarted via babysitter which resumed from checkpoint 173 at step 175; harness now progressing again
561
+
562
+ ## 2026-04-29 09:33 UTC tick
563
+ - Stress: 215/1658 (PID 387049 alive, 29 min elapsed, 260MB RSS; prior run COMPLETED 1658/1658 on 2026-04-28 20:00 UTC; babysitter restarted fresh run at 09:04 UTC after PID 270527 died at idx=233)
564
+ - Write rate: 5% last 39 prompts (analysis-prompt section 196-215: lines_of_code, tabs_vs_spaces, indent_consistency_check etc. — all expected 0 writes; model actively writing files again from prompt 212 onward: ethereum_price.py, ip_geolocation.py, phone_to_country.py confirmed in session log)
565
+ - Admiral last 30 min: 0 fires since 09:04 restart; prior session had loop:bash::--help, loop:read_file::cli.py, retry_after_error:search_replace (directory path) — all known patterns
566
+ - vLLM 400s: 0
567
+ - GH issues: 0 open
568
+ - Services: llm_balancer healthy on :8001, vLLM gemma4 running, admiral_probe up; stress babysitter STRESS_LOG has cosmetic duplicate line (both set to current log, harmless)
569
+ - Unshipped: b2f26aa (search_replace escalate directory-path error on 2nd+ call) ships at ~11:00 UTC as v2.7.20
570
+ - Action this tick: no action — system healthy; prior stress run completed full 1658-prompt sweep; new run progressing normally; no new bugs found
571
+
572
+ ## 2026-04-29 10:03 UTC tick
573
+ - Stress: 230/1658 (PID 387049 alive, started 09:04 UTC, resumed from step 174; prior full run at 680/1658 was from old log /tmp/stress_2000_1777119799.log — current active log is /tmp/stress_2000_v10_restart_1777453487.log)
574
+ - Write rate: 28% (15/52 prompts with writes in current run; low-write section 174-230 includes analysis/sentiment/keyword prompts with minimal file creation)
575
+ - vLLM 400s: 0 (89% prefix cache hit rate, GPU healthy)
576
+ - GH issues: 0 open
577
+ - Services: llm_balancer PID 24354 on :8001 healthy, vLLM gemma4 up, admiral_probe up; babysitter STRESS_LOG correctly pointed at active log
578
+ - Unshipped: b2f26aa (search_replace escalate dir-path error on 2nd+ call) ships at 12:00 UTC as v2.7.20
579
+ - Admiral patterns last 2h: retry_after_error:write_file (truncated-history recovery) x2 — investigated; model correctly recovered by resubmitting with real args, write succeeded; no new drydock bug; empty_after_tool:search_replace x1, retry_after_error:bash, retry_after_error:search_replace — all known patterns
580
+ - Action this tick: no fix committed — all services healthy, no new bugs found; previous stress log confusion resolved (was reading old Apr 26 log instead of current babysitter log)
581
+
582
+ ## 2026-04-29 10:35 UTC tick
583
+ - Stress: 235/1658 (PID 387049 alive, 1h25m elapsed, resuming from step 174; current prompts are qr_encode/decode/barcode_encode section, mostly TIMEOUT with writes)
584
+ - Write rate: 33% last 56 prompts (19/56 with writes; analysis/QR section skews low)
585
+ - vLLM 400s: 0
586
+ - GH issues: 0 open
587
+ - Services: llm_balancer healthy, vLLM gemma4 up, stress harness alive
588
+ - Action this tick: committed fix 3695f6b — escalate truncated-history write_file retry on 2nd+ offense. Pattern observed: 8 consecutive retry_after_error:write_file:truncated_history fires in 7 min (10:05-10:12 UTC), model ignoring the existing advisory. APIToolFormatHandler now tracks per-path hit count; 2nd+ failure gets "REPEATED FAILURE #N" with project file listing and concrete search_replace alternative, matching the escalation pattern in search_replace.py. 5 regression tests pass. Ships as v2.7.21 at next auto-release (~12:00 UTC).
@@ -326,7 +326,7 @@ wheels = [
326
326
 
327
327
  [[package]]
328
328
  name = "drydock-cli"
329
- version = "2.7.17"
329
+ version = "2.7.19"
330
330
  source = { editable = "." }
331
331
  dependencies = [
332
332
  { name = "agent-client-protocol" },
@@ -1 +0,0 @@
1
- 341821
File without changes