drydock-cli 2.6.82__tar.gz → 2.6.83__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 (595) hide show
  1. drydock_cli-2.6.83/.auto_release.lock +1 -0
  2. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/PKG-INFO +1 -1
  3. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/entrypoint.py +17 -0
  4. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/agent_loop.py +7 -0
  5. drydock_cli-2.6.83/drydock/core/config/doctor.py +222 -0
  6. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/base.py +5 -0
  7. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/bash.py +66 -5
  8. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/read_file.py +45 -52
  9. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/search_replace.py +61 -0
  10. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/write_file.py +117 -10
  11. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/pyproject.toml +1 -1
  12. drydock_cli-2.6.82/.auto_release.lock +0 -1
  13. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.claude/scheduled_tasks.lock +0 -0
  14. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/CODEOWNERS +0 -0
  15. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
  16. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  17. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  18. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/workflows/build-and-upload.yml +0 -0
  19. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/workflows/ci.yml +0 -0
  20. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/workflows/issue-labeler.yml +0 -0
  21. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/workflows/release.yml +0 -0
  22. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.gitignore +0 -0
  23. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.pre-commit-config.yaml +0 -0
  24. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.python-version +0 -0
  25. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.typos.toml +0 -0
  26. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.vscode/extensions.json +0 -0
  27. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.vscode/launch.json +0 -0
  28. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.vscode/settings.json +0 -0
  29. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/AGENTS.md +0 -0
  30. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/BASELINE_412.md +0 -0
  31. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/CHANGELOG.md +0 -0
  32. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/CLAUDE.md +0 -0
  33. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/CONTRIBUTING.md +0 -0
  34. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/Drydock_rebrand.md +0 -0
  35. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/LICENSE +0 -0
  36. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/MODEL_SHORTCOMINGS.md +0 -0
  37. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/NOTICE +0 -0
  38. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/OVERNIGHT_REPORT_2026_04_13.md +0 -0
  39. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/PRD.md +0 -0
  40. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/README.md +0 -0
  41. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/action.yml +0 -0
  42. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/README.md +0 -0
  43. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results1.tsv +0 -0
  44. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results13.tsv +0 -0
  45. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results14.tsv +0 -0
  46. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results15.tsv +0 -0
  47. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results16.tsv +0 -0
  48. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results17.tsv +0 -0
  49. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results18.tsv +0 -0
  50. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results19.tsv +0 -0
  51. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results2.tsv +0 -0
  52. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results20.tsv +0 -0
  53. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results3.tsv +0 -0
  54. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results4.tsv +0 -0
  55. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results5.tsv +0 -0
  56. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results6.tsv +0 -0
  57. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results7.tsv +0 -0
  58. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results8.tsv +0 -0
  59. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results9.tsv +0 -0
  60. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results_evolved_v1.tsv +0 -0
  61. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/distribution/zed/LICENSE +0 -0
  62. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/distribution/zed/extension.toml +0 -0
  63. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/distribution/zed/icons/mistral_vibe.svg +0 -0
  64. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/docs/README.md +0 -0
  65. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/docs/acp-setup.md +0 -0
  66. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/docs/proxy-setup.md +0 -0
  67. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/__init__.py +0 -0
  68. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/__init__.py +0 -0
  69. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/acp_agent_loop.py +0 -0
  70. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/acp_logger.py +0 -0
  71. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/entrypoint.py +0 -0
  72. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/__init__.py +0 -0
  73. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/base.py +0 -0
  74. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/bash.py +0 -0
  75. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/read_file.py +0 -0
  76. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/search_replace.py +0 -0
  77. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/todo.py +0 -0
  78. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/write_file.py +0 -0
  79. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/session_update.py +0 -0
  80. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/utils.py +0 -0
  81. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/__init__.py +0 -0
  82. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/autocompletion/__init__.py +0 -0
  83. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/autocompletion/base.py +0 -0
  84. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/autocompletion/path_completion.py +0 -0
  85. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/autocompletion/slash_command.py +0 -0
  86. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/cli.py +0 -0
  87. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/clipboard.py +0 -0
  88. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/commands.py +0 -0
  89. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/history_manager.py +0 -0
  90. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
  91. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
  92. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
  93. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/terminal_setup.py +0 -0
  94. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/__init__.py +0 -0
  95. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
  96. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/app.py +0 -0
  97. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/app.tcss +0 -0
  98. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/external_editor.py +0 -0
  99. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
  100. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
  101. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
  102. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
  103. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
  104. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
  105. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
  106. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
  107. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
  108. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
  109. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
  110. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
  111. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
  112. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
  113. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
  114. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
  115. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
  116. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
  117. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/compact.py +0 -0
  118. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
  119. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
  120. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
  121. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/loading.py +0 -0
  122. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/messages.py +0 -0
  123. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
  124. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
  125. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
  126. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
  127. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
  128. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
  129. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
  130. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
  131. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
  132. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/tools.py +0 -0
  133. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
  134. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
  135. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/windowing/history.py +0 -0
  136. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
  137. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/windowing/state.py +0 -0
  138. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/__init__.py +0 -0
  139. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
  140. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
  141. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
  142. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
  143. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
  144. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/update.py +0 -0
  145. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/whats_new.py +0 -0
  146. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/__init__.py +0 -0
  147. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/agents/__init__.py +0 -0
  148. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/agents/manager.py +0 -0
  149. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/agents/models.py +0 -0
  150. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/auth/__init__.py +0 -0
  151. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/auth/crypto.py +0 -0
  152. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/auth/github.py +0 -0
  153. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/__init__.py +0 -0
  154. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/completers.py +0 -0
  155. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
  156. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
  157. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
  158. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/store.py +0 -0
  159. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
  160. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/fuzzy.py +0 -0
  161. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/path_prompt.py +0 -0
  162. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
  163. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/build_orchestrator.py +0 -0
  164. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/config/__init__.py +0 -0
  165. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/config/_settings.py +0 -0
  166. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/config/harness_files/__init__.py +0 -0
  167. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/config/harness_files/_harness_manager.py +0 -0
  168. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/config/harness_files/_paths.py +0 -0
  169. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/consultant.py +0 -0
  170. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/drydock_states.py +0 -0
  171. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/hooks.py +0 -0
  172. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/__init__.py +0 -0
  173. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/backend/anthropic.py +0 -0
  174. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/backend/base.py +0 -0
  175. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/backend/factory.py +0 -0
  176. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/backend/generic.py +0 -0
  177. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/backend/mistral.py +0 -0
  178. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
  179. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/backend/vertex.py +0 -0
  180. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/exceptions.py +0 -0
  181. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/format.py +0 -0
  182. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/message_utils.py +0 -0
  183. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/types.py +0 -0
  184. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/logger.py +0 -0
  185. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/middleware.py +0 -0
  186. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/output_formatters.py +0 -0
  187. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/paths/__init__.py +0 -0
  188. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/paths/_local_config_walk.py +0 -0
  189. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/paths/_vibe_home.py +0 -0
  190. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/paths/conventions.py +0 -0
  191. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/plan_session.py +0 -0
  192. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/plugins.py +0 -0
  193. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/programmatic.py +0 -0
  194. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/__init__.py +0 -0
  195. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/builder.md +0 -0
  196. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/cli.md +0 -0
  197. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/compact.md +0 -0
  198. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/dangerous_directory.md +0 -0
  199. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/diagnostic.md +0 -0
  200. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/explore.md +0 -0
  201. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/gemma4.md +0 -0
  202. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/planner.md +0 -0
  203. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/project_context.md +0 -0
  204. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/tests.md +0 -0
  205. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/proxy_setup.py +0 -0
  206. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/session/agent_memory.py +0 -0
  207. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/session/checkpoints.py +0 -0
  208. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/session/session_loader.py +0 -0
  209. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/session/session_logger.py +0 -0
  210. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/session/session_migration.py +0 -0
  211. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/session/state_file.py +0 -0
  212. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/session_checker.py +0 -0
  213. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/skills/__init__.py +0 -0
  214. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/skills/manager.py +0 -0
  215. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/skills/models.py +0 -0
  216. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/skills/parser.py +0 -0
  217. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/slug.py +0 -0
  218. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/system_prompt.py +0 -0
  219. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/telemetry/__init__.py +0 -0
  220. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/telemetry/send.py +0 -0
  221. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/teleport/errors.py +0 -0
  222. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/teleport/git.py +0 -0
  223. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/teleport/nuage.py +0 -0
  224. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/teleport/teleport.py +0 -0
  225. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/teleport/types.py +0 -0
  226. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/_task_manager.py +0 -0
  227. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/ask_user_question.py +0 -0
  228. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/cron.py +0 -0
  229. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
  230. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/glob_tool.py +0 -0
  231. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/grep.py +0 -0
  232. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/invoke_skill.py +0 -0
  233. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/lsp.py +0 -0
  234. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/mcp_resources.py +0 -0
  235. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/notebook_edit.py +0 -0
  236. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/powershell.py +0 -0
  237. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
  238. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
  239. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/bash.md +0 -0
  240. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/cron.md +0 -0
  241. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/glob.md +0 -0
  242. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/grep.md +0 -0
  243. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/invoke_skill.md +0 -0
  244. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/lsp.md +0 -0
  245. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/mcp_resources.md +0 -0
  246. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
  247. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/powershell.md +0 -0
  248. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
  249. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
  250. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
  251. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/task.md +0 -0
  252. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
  253. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/todo.md +0 -0
  254. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/tool_search.md +0 -0
  255. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
  256. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
  257. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/worktree.md +0 -0
  258. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
  259. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/task.py +0 -0
  260. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/todo.py +0 -0
  261. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/tool_search.py +0 -0
  262. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/webfetch.py +0 -0
  263. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/websearch.py +0 -0
  264. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/worktree.py +0 -0
  265. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/injection_guard.py +0 -0
  266. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/manager.py +0 -0
  267. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/mcp/__init__.py +0 -0
  268. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/mcp/registry.py +0 -0
  269. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/mcp/tools.py +0 -0
  270. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/mcp_sampling.py +0 -0
  271. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/ui.py +0 -0
  272. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/utils.py +0 -0
  273. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/trusted_folders.py +0 -0
  274. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/types.py +0 -0
  275. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/utils.py +0 -0
  276. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/onboarding/__init__.py +0 -0
  277. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/onboarding/base.py +0 -0
  278. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/onboarding/onboarding.tcss +0 -0
  279. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/onboarding/screens/__init__.py +0 -0
  280. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/onboarding/screens/api_key.py +0 -0
  281. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/onboarding/screens/welcome.py +0 -0
  282. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
  283. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
  284. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/__init__.py +0 -0
  285. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/api-design/SKILL.md +0 -0
  286. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/audit-tests/SKILL.md +0 -0
  287. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/batch/SKILL.md +0 -0
  288. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/commit-code/SKILL.md +0 -0
  289. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/context-summary/SKILL.md +0 -0
  290. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/create-presentation/SKILL.md +0 -0
  291. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/deep-research/SKILL.md +0 -0
  292. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/deploy/SKILL.md +0 -0
  293. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/diff-review/SKILL.md +0 -0
  294. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/doc-gen/SKILL.md +0 -0
  295. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/explain-code/SKILL.md +0 -0
  296. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/explore-code/SKILL.md +0 -0
  297. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/fix-issue/SKILL.md +0 -0
  298. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/git-ops/SKILL.md +0 -0
  299. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/init-project/SKILL.md +0 -0
  300. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/investigate/SKILL.md +0 -0
  301. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/loop/SKILL.md +0 -0
  302. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/migrate/SKILL.md +0 -0
  303. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/perf-analyze/SKILL.md +0 -0
  304. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/plan-impl/SKILL.md +0 -0
  305. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/pr-review/SKILL.md +0 -0
  306. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/refactor/SKILL.md +0 -0
  307. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/regex-help/SKILL.md +0 -0
  308. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/review/SKILL.md +0 -0
  309. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/security-review/SKILL.md +0 -0
  310. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/ship/SKILL.md +0 -0
  311. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/simplify/SKILL.md +0 -0
  312. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/strong-tests/SKILL.md +0 -0
  313. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/test-verify/SKILL.md +0 -0
  314. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/whats_new.md +0 -0
  315. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock-acp.spec +0 -0
  316. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock_terms.md +0 -0
  317. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/flake.lock +0 -0
  318. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/flake.nix +0 -0
  319. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/README.md +0 -0
  320. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/audit_sampler.py +0 -0
  321. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/auto_generate_tests.py +0 -0
  322. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/auto_release.sh +0 -0
  323. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/auto_test_loop.sh +0 -0
  324. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/backup.sh +0 -0
  325. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/bump_version.py +0 -0
  326. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/comprehensive_loop.py +0 -0
  327. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/deploy_to_github.sh +0 -0
  328. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/discover_cli_tools.sh +0 -0
  329. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/evolve_tests.py +0 -0
  330. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/install.sh +0 -0
  331. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/llm_balancer.py +0 -0
  332. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/mega_loop.py +0 -0
  333. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/meta_ralph_loop.py +0 -0
  334. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/monitor_swebench.sh +0 -0
  335. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/monitor_test_battery.sh +0 -0
  336. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/notify_release.py +0 -0
  337. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/oss_task_harness.py +0 -0
  338. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/overnight_agents_test.sh +0 -0
  339. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/port_task.py +0 -0
  340. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/prepare_release.py +0 -0
  341. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/publish_to_pypi.sh +0 -0
  342. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/ralph_loop.py +0 -0
  343. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/session_loop_audit.py +0 -0
  344. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/shakedown.py +0 -0
  345. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/shakedown_interactive.py +0 -0
  346. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/shakedown_regression.sh +0 -0
  347. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/shakedown_suite.sh +0 -0
  348. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/shakedown_variance.sh +0 -0
  349. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/telegram_bot.py +0 -0
  350. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/test_bank.sh +0 -0
  351. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/test_full.sh +0 -0
  352. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/test_smoke.sh +0 -0
  353. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/test_tui_path.py +0 -0
  354. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/tui_test.py +0 -0
  355. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/vllm_failover.sh +0 -0
  356. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/__init__.py +0 -0
  357. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/conftest.py +0 -0
  358. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_acp.py +0 -0
  359. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_agent_thought.py +0 -0
  360. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_bash.py +0 -0
  361. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_compact_session_updates.py +0 -0
  362. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_content.py +0 -0
  363. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_initialize.py +0 -0
  364. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_list_sessions.py +0 -0
  365. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_load_session.py +0 -0
  366. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_multi_session.py +0 -0
  367. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_new_session.py +0 -0
  368. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_proxy_setup_acp.py +0 -0
  369. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_read_file.py +0 -0
  370. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_search_replace.py +0 -0
  371. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_set_config_option.py +0 -0
  372. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_set_mode.py +0 -0
  373. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_set_model.py +0 -0
  374. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_tool_call_session_update.py +0 -0
  375. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_utils.py +0 -0
  376. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_write_file.py +0 -0
  377. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_file_indexer.py +0 -0
  378. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_fuzzy.py +0 -0
  379. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
  380. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_path_completer_recursive.py +0 -0
  381. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_path_completion_controller.py +0 -0
  382. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
  383. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_slash_command_controller.py +0 -0
  384. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
  385. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/__init__.py +0 -0
  386. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/data/__init__.py +0 -0
  387. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/data/fireworks.py +0 -0
  388. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/data/mistral.py +0 -0
  389. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/test_anthropic_adapter.py +0 -0
  390. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/test_backend.py +0 -0
  391. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/test_reasoning_adapter.py +0 -0
  392. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
  393. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
  394. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
  395. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
  396. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_bell_notifications.py +0 -0
  397. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_braille_renderer.py +0 -0
  398. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_clipboard.py +0 -0
  399. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_commands.py +0 -0
  400. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_copy_shortcuts.py +0 -0
  401. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_external_editor.py +0 -0
  402. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_no_markup_static.py +0 -0
  403. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_question_app.py +0 -0
  404. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_spinner.py +0 -0
  405. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_switching_mode.py +0 -0
  406. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_ui_clipboard_notifications.py +0 -0
  407. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
  408. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_ui_session_resume.py +0 -0
  409. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_ui_skill_dispatch.py +0 -0
  410. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/textual_ui/__init__.py +0 -0
  411. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/textual_ui/test_session_picker.py +0 -0
  412. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/conftest.py +0 -0
  413. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_agents.py +0 -0
  414. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_auth_crypto.py +0 -0
  415. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_auth_github.py +0 -0
  416. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_config_load_dotenv.py +0 -0
  417. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_config_paths.py +0 -0
  418. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_config_resolution.py +0 -0
  419. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_file_logging.py +0 -0
  420. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_plan_session.py +0 -0
  421. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_proxy_setup.py +0 -0
  422. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_slug.py +0 -0
  423. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_telemetry_send.py +0 -0
  424. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_teleport_git.py +0 -0
  425. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_teleport_nuage.py +0 -0
  426. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_teleport_service.py +0 -0
  427. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_trusted_folders.py +0 -0
  428. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_utils.py +0 -0
  429. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/e2e/common.py +0 -0
  430. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/e2e/conftest.py +0 -0
  431. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/e2e/mock_server.py +0 -0
  432. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/e2e/test_cli_tui_onboarding.py +0 -0
  433. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/e2e/test_cli_tui_streaming.py +0 -0
  434. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
  435. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/fixtures/doc_qa_system_prd.md +0 -0
  436. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/mock/__init__.py +0 -0
  437. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/mock/mock_backend_factory.py +0 -0
  438. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/mock/mock_entrypoint.py +0 -0
  439. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/mock/utils.py +0 -0
  440. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/onboarding/test_run_onboarding.py +0 -0
  441. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/onboarding/test_ui_onboarding.py +0 -0
  442. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/session/test_session_loader.py +0 -0
  443. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/session/test_session_logger.py +0 -0
  444. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/session/test_session_migration.py +0 -0
  445. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/skills/conftest.py +0 -0
  446. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/skills/test_manager.py +0 -0
  447. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/skills/test_models.py +0 -0
  448. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/skills/test_parser.py +0 -0
  449. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
  450. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
  451. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
  452. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
  453. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
  454. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
  455. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
  456. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
  457. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
  458. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
  459. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
  460. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
  461. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
  462. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
  463. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
  464. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
  465. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
  466. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
  467. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
  468. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
  469. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
  470. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
  471. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
  472. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
  473. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
  474. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
  475. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
  476. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
  477. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
  478. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
  479. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
  480. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
  481. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
  482. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
  483. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
  484. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
  485. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
  486. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
  487. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
  488. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
  489. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
  490. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
  491. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
  492. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
  493. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
  494. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
  495. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
  496. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
  497. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
  498. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
  499. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
  500. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
  501. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
  502. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
  503. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
  504. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
  505. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
  506. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
  507. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
  508. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
  509. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/base_snapshot_test_app.py +0 -0
  510. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/conftest.py +0 -0
  511. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/snap_compare.py +0 -0
  512. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
  513. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
  514. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
  515. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
  516. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
  517. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
  518. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
  519. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
  520. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
  521. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
  522. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
  523. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
  524. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
  525. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
  526. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/stubs/fake_backend.py +0 -0
  527. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/stubs/fake_client.py +0 -0
  528. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/stubs/fake_tool.py +0 -0
  529. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_agent_auto_compact.py +0 -0
  530. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_agent_backend.py +0 -0
  531. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_agent_observer_streaming.py +0 -0
  532. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_agent_stats.py +0 -0
  533. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_agent_tasks.py +0 -0
  534. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_agent_tool_call.py +0 -0
  535. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_agents.py +0 -0
  536. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_bank_build.py +0 -0
  537. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_bank_debug.py +0 -0
  538. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_bank_multiagent.py +0 -0
  539. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_bank_prd.py +0 -0
  540. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_bank_prd_extended.py +0 -0
  541. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_bank_tools.py +0 -0
  542. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_bank_update.py +0 -0
  543. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_build_projects.py +0 -0
  544. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_cli_programmatic_preload.py +0 -0
  545. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_current_bugs.py +0 -0
  546. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_drydock_regression.py +0 -0
  547. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_drydock_tasks.py +0 -0
  548. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_full_regression.py +0 -0
  549. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_history_manager.py +0 -0
  550. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_integration.py +0 -0
  551. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_loop_detection.py +0 -0
  552. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_message_id.py +0 -0
  553. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_message_merging.py +0 -0
  554. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_middleware.py +0 -0
  555. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_multi_agent.py +0 -0
  556. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_real_failures.py +0 -0
  557. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_real_issues.py +0 -0
  558. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_real_workflow.py +0 -0
  559. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_reasoning_content.py +0 -0
  560. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_smoke.py +0 -0
  561. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_system_prompt.py +0 -0
  562. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_tagged_text.py +0 -0
  563. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_tool_args.py +0 -0
  564. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_ui_external_editor.py +0 -0
  565. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_ui_input_history.py +0 -0
  566. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_user_issues.py +0 -0
  567. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_workloads.py +0 -0
  568. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/testbank_helpers.py +0 -0
  569. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_ask_user_question.py +0 -0
  570. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_bash.py +0 -0
  571. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_exit_plan_mode.py +0 -0
  572. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_grep.py +0 -0
  573. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_invoke_context.py +0 -0
  574. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_manager_get_tool_config.py +0 -0
  575. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_mcp.py +0 -0
  576. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_mcp_sampling.py +0 -0
  577. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_task.py +0 -0
  578. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_ui_bash_execution.py +0 -0
  579. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_webfetch.py +0 -0
  580. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_websearch.py +0 -0
  581. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
  582. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
  583. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/test_do_update.py +0 -0
  584. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
  585. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/test_github_update_gateway.py +0 -0
  586. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
  587. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/test_ui_update_notification.py +0 -0
  588. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/test_update_use_case.py +0 -0
  589. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/test_whats_new.py +0 -0
  590. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/uv.lock +0 -0
  591. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/worked_examples/README.md +0 -0
  592. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/worked_examples/cli_subcommand_dispatch.py +0 -0
  593. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/worked_examples/lookup.json +0 -0
  594. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/worked_examples/sql_parser.py +0 -0
  595. {drydock_cli-2.6.82 → drydock_cli-2.6.83}/worked_examples/tree_walking_interpreter.py +0 -0
@@ -0,0 +1 @@
1
+ 1426724
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 2.6.82
3
+ Version: 2.6.83
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
@@ -82,6 +82,17 @@ def parse_arguments() -> argparse.Namespace:
82
82
  "or custom from ~/.drydock/agents/NAME.toml)",
83
83
  )
84
84
  parser.add_argument("--setup", action="store_true", help="Setup API key and exit")
85
+ parser.add_argument(
86
+ "--doctor",
87
+ action="store_true",
88
+ help="Check ~/.drydock/config.toml for drift vs. package defaults and exit",
89
+ )
90
+ parser.add_argument(
91
+ "--fix",
92
+ action="store_true",
93
+ help="With --doctor: rewrite ~/.drydock/config.toml to union missing "
94
+ "defaults (writes .bak backup first). No effect without --doctor.",
95
+ )
85
96
  parser.add_argument(
86
97
  "--workdir",
87
98
  type=Path,
@@ -175,6 +186,12 @@ def check_and_resolve_trusted_folder() -> None:
175
186
  def main() -> None:
176
187
  args = parse_arguments()
177
188
 
189
+ if getattr(args, "doctor", False):
190
+ from drydock.core.config.harness_files import init_harness_files_manager
191
+ from drydock.core.config.doctor import run_doctor
192
+ init_harness_files_manager("user", "project")
193
+ sys.exit(run_doctor(apply=bool(getattr(args, "fix", False))))
194
+
178
195
  if args.workdir:
179
196
  workdir = args.workdir.expanduser().resolve()
180
197
  if not workdir.is_dir():
@@ -195,6 +195,12 @@ class AgentLoop:
195
195
  self._empty_responses: int = 0
196
196
  self._successful_test_runs: int = 0
197
197
 
198
+ # Shared read-file state — used by write_file / search_replace to
199
+ # enforce Read-before-Write (per Claude Code's tool contract) and
200
+ # by read_file to dedup unchanged-mtime re-reads. Keyed by resolved
201
+ # absolute path; value is {"content", "timestamp", "offset", "limit"}.
202
+ self._read_file_state: dict[str, dict] = {}
203
+
198
204
  system_prompt = get_universal_system_prompt(
199
205
  self.tool_manager, self.config, self.skill_manager, self.agent_manager
200
206
  )
@@ -970,6 +976,7 @@ class AgentLoop:
970
976
  sampling_callback=self._sampling_handler,
971
977
  plan_file_path=self._plan_session.plan_file_path,
972
978
  switch_agent_callback=self.switch_agent,
979
+ read_file_state=self._read_file_state,
973
980
  ),
974
981
  **tool_call.args_dict,
975
982
  ):
@@ -0,0 +1,222 @@
1
+ """Config drift diagnostics (Option C — `drydock doctor`).
2
+
3
+ Reads the user's ~/.drydock/config.toml, compares each field against the
4
+ pydantic default, and reports drift. Designed to complement the auto-merge
5
+ behavior in Option A: even though list fields union with defaults at
6
+ load time, the user's config.toml FILE still shows the old values —
7
+ the merge is runtime-only. `drydock doctor --fix` rewrites the TOML with
8
+ the merged values so the file matches what's actually loaded.
9
+
10
+ Separately reports scalar drift (e.g., auto_compact_threshold=200000 when
11
+ the sensible value for the active model is lower). Those are advisory —
12
+ doctor prints them but won't change them without --fix.
13
+ """
14
+ from __future__ import annotations
15
+
16
+ from dataclasses import dataclass
17
+ from pathlib import Path
18
+ from typing import Any
19
+
20
+ try:
21
+ import tomllib
22
+ except ImportError: # pragma: no cover
23
+ import tomli as tomllib # type: ignore
24
+
25
+ try:
26
+ import tomli_w
27
+ except ImportError: # pragma: no cover
28
+ tomli_w = None # type: ignore
29
+
30
+
31
+ # Fields known to be mergeable (user value unioned with package default).
32
+ # When drift is detected on these, `--fix` unions them.
33
+ MERGEABLE_LIST_FIELDS: dict[str, str] = {
34
+ # "section.field": "human_label"
35
+ "bash.allowlist": "bash allowlist (auto-approved commands)",
36
+ "bash.denylist": "bash denylist (blocked commands)",
37
+ "bash.denylist_standalone": "bash denylist_standalone",
38
+ }
39
+
40
+
41
+ @dataclass
42
+ class DriftReport:
43
+ field: str
44
+ user_value: Any
45
+ default_value: Any
46
+ kind: str # "list_merge" | "missing_in_user" | "scalar_stale"
47
+ fix_description: str
48
+
49
+ def to_row(self) -> tuple[str, str, str, str]:
50
+ u = str(self.user_value)
51
+ d = str(self.default_value)
52
+ if len(u) > 40:
53
+ u = u[:37] + "..."
54
+ if len(d) > 40:
55
+ d = d[:37] + "..."
56
+ return (self.field, u, d, self.kind)
57
+
58
+
59
+ def _get_tool_section(toml_data: dict, section: str) -> dict | None:
60
+ """Walk `tools.bash` → toml_data.get('tools', {}).get('bash', {})."""
61
+ cur: Any = toml_data
62
+ for part in section.split("."):
63
+ if not isinstance(cur, dict):
64
+ return None
65
+ cur = cur.get(part)
66
+ if cur is None:
67
+ return None
68
+ return cur if isinstance(cur, dict) else None
69
+
70
+
71
+ def _get_default_list(field_path: str) -> list[str]:
72
+ """Resolve the package-default factory for a dotted field path."""
73
+ section, field = field_path.rsplit(".", 1)
74
+ if section == "bash":
75
+ from drydock.core.tools.builtins.bash import (
76
+ _get_default_allowlist,
77
+ _get_default_denylist,
78
+ _get_default_denylist_standalone,
79
+ )
80
+ factories = {
81
+ "allowlist": _get_default_allowlist,
82
+ "denylist": _get_default_denylist,
83
+ "denylist_standalone": _get_default_denylist_standalone,
84
+ }
85
+ fn = factories.get(field)
86
+ return list(fn()) if fn else []
87
+ return []
88
+
89
+
90
+ def analyze_config(config_path: Path) -> tuple[dict, list[DriftReport]]:
91
+ """Load the user's config.toml and compare each mergeable field against
92
+ its package default. Returns (raw_toml_data, drift_reports)."""
93
+ if not config_path.exists():
94
+ return {}, []
95
+ with config_path.open("rb") as f:
96
+ data = tomllib.load(f)
97
+
98
+ reports: list[DriftReport] = []
99
+
100
+ # Mergeable list fields — check for defaults missing from user config.
101
+ for field_path, _label in MERGEABLE_LIST_FIELDS.items():
102
+ section, field = field_path.rsplit(".", 1)
103
+ # Drydock TOML structure: [tools.bash] allowlist = [...]
104
+ user_section = _get_tool_section(data, f"tools.{section}")
105
+ user_value = user_section.get(field) if user_section else None
106
+ defaults = _get_default_list(field_path)
107
+ if user_value is None:
108
+ # User has no entry — pydantic uses full defaults. No drift.
109
+ continue
110
+ if not isinstance(user_value, list):
111
+ continue
112
+ if "__override__" in user_value:
113
+ continue # explicit opt-out, respect it
114
+ missing = [d for d in defaults if d not in user_value]
115
+ if missing:
116
+ reports.append(DriftReport(
117
+ field=f"tools.{field_path}",
118
+ user_value=f"{len(user_value)} entries",
119
+ default_value=f"{len(defaults)} in package",
120
+ kind="list_merge",
121
+ fix_description=(
122
+ f"Add {len(missing)} missing default(s): "
123
+ + ", ".join(missing[:5])
124
+ + (f" … (+{len(missing) - 5} more)" if len(missing) > 5 else "")
125
+ ),
126
+ ))
127
+
128
+ return data, reports
129
+
130
+
131
+ def print_drift_report(reports: list[DriftReport]) -> None:
132
+ """Print a table of drift findings."""
133
+ from rich.console import Console
134
+ from rich.table import Table
135
+ console = Console()
136
+ if not reports:
137
+ console.print("[green]No config drift detected.[/green]")
138
+ console.print(
139
+ "Your ~/.drydock/config.toml is in sync with the package defaults."
140
+ )
141
+ return
142
+ table = Table(title="Config drift vs. package defaults", show_lines=True)
143
+ table.add_column("Field")
144
+ table.add_column("User", overflow="fold")
145
+ table.add_column("Package default", overflow="fold")
146
+ table.add_column("Kind")
147
+ for r in reports:
148
+ row = r.to_row()
149
+ table.add_row(*row)
150
+ console.print(table)
151
+ console.print("\n[bold]Details:[/bold]")
152
+ for r in reports:
153
+ console.print(f" • [cyan]{r.field}[/cyan]: {r.fix_description}")
154
+ console.print(
155
+ "\nRun [bold]drydock --doctor --fix[/bold] to apply safe corrections "
156
+ "(writes a backup to config.toml.bak).\n"
157
+ "Auto-mergeable lists are ALREADY merged at runtime — fixing only "
158
+ "updates the FILE to reflect what's loaded.\n"
159
+ )
160
+
161
+
162
+ def apply_fix(config_path: Path, data: dict, reports: list[DriftReport]) -> int:
163
+ """Union missing defaults into the user's TOML file. Returns count of fields updated."""
164
+ if tomli_w is None:
165
+ raise RuntimeError(
166
+ "tomli_w is not installed. Add `pip install tomli_w` to use --fix."
167
+ )
168
+ updated = 0
169
+ for r in reports:
170
+ if r.kind != "list_merge":
171
+ continue
172
+ # r.field is e.g. "tools.bash.allowlist"
173
+ parts = r.field.split(".")
174
+ cur: Any = data
175
+ for p in parts[:-1]:
176
+ if p not in cur or not isinstance(cur[p], dict):
177
+ cur[p] = {}
178
+ cur = cur[p]
179
+ final_field = parts[-1]
180
+ defaults_path = ".".join(parts[1:]) # strip leading "tools."
181
+ defaults = _get_default_list(defaults_path)
182
+ user_list = cur.get(final_field, [])
183
+ merged = list(user_list) if isinstance(user_list, list) else []
184
+ for d in defaults:
185
+ if d not in merged:
186
+ merged.append(d)
187
+ cur[final_field] = merged
188
+ updated += 1
189
+
190
+ if updated == 0:
191
+ return 0
192
+
193
+ # Write backup then new file.
194
+ backup = config_path.with_suffix(config_path.suffix + ".bak")
195
+ if config_path.exists():
196
+ backup.write_bytes(config_path.read_bytes())
197
+ with config_path.open("wb") as f:
198
+ tomli_w.dump(data, f)
199
+ return updated
200
+
201
+
202
+ def run_doctor(apply: bool = False) -> int:
203
+ """Entry point for `drydock --doctor [--fix]`. Returns shell exit code."""
204
+ from drydock.core.config.harness_files import get_harness_files_manager
205
+ from rich.console import Console
206
+ console = Console()
207
+
208
+ mgr = get_harness_files_manager()
209
+ config_path = mgr.config_file
210
+ if config_path is None:
211
+ console.print("[yellow]No user config file found.[/yellow]")
212
+ return 0
213
+ console.print(f"Analyzing [bold]{config_path}[/bold] ...\n")
214
+ data, reports = analyze_config(config_path)
215
+ print_drift_report(reports)
216
+ if apply and reports:
217
+ updated = apply_fix(config_path, data, reports)
218
+ console.print(
219
+ f"\n[green]Applied fixes to {updated} field(s). "
220
+ f"Backup saved to {config_path}.bak[/green]"
221
+ )
222
+ return 0
@@ -51,6 +51,11 @@ class InvokeContext:
51
51
  entrypoint_metadata: EntrypointMetadata | None = field(default=None)
52
52
  plan_file_path: Path | None = field(default=None)
53
53
  switch_agent_callback: SwitchAgentCallback | None = field(default=None)
54
+ # Shared across all tool invocations within a session. The same dict
55
+ # reference lives on AgentLoop; write_file / read_file / search_replace
56
+ # mutate it to track what the model has observed (Read-before-Write
57
+ # + read dedup, per Claude Code's tool contract model).
58
+ read_file_state: dict[str, dict] | None = field(default=None)
54
59
 
55
60
 
56
61
  class ToolError(Exception):
@@ -1,7 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import asyncio
4
- from collections.abc import AsyncGenerator
4
+ from collections.abc import AsyncGenerator, Callable
5
+ from typing import Any
5
6
  from functools import lru_cache
6
7
  import os
7
8
  from pathlib import Path
@@ -9,7 +10,7 @@ import signal
9
10
  import sys
10
11
  from typing import ClassVar, Literal, final
11
12
 
12
- from pydantic import BaseModel, Field
13
+ from pydantic import BaseModel, Field, field_validator
13
14
  from tree_sitter import Language, Node, Parser
14
15
  import tree_sitter_bash as tsbash
15
16
 
@@ -161,8 +162,25 @@ async def _kill_process_tree(proc: asyncio.subprocess.Process) -> None:
161
162
 
162
163
 
163
164
  def _get_default_allowlist() -> list[str]:
165
+ # Auto-accepted because they are read-only / non-destructive.
166
+ # Each entry is a prefix — commands starting with any of these are
167
+ # ALWAYS allowed. Parser splits at pipes/chains so `ls | rm` is
168
+ # checked as two separate commands.
164
169
  common = [
165
- "echo", "find", "git diff", "git log", "git status", "tree", "whoami",
170
+ "echo", "find", "tree", "whoami",
171
+ # Git read-only subcommands
172
+ "git diff", "git log", "git status", "git show",
173
+ "git branch", "git ls-files", "git grep", "git remote",
174
+ "git rev-parse", "git blame", "git config --get",
175
+ "git tag", "git stash list",
176
+ # Search tools (read-only by design)
177
+ "grep", "rg", "fd", "fdfind", "ag",
178
+ # Text/file inspection
179
+ "diff", "cmp", "sort", "uniq", "awk", "cut", "tr",
180
+ "basename", "dirname", "realpath", "readlink",
181
+ # System info (read-only)
182
+ "date", "id", "hostname", "pwd", "env", "printenv",
183
+ "du", "df", "ps", "free", "uptime",
166
184
  # Python project management — safe read/install operations
167
185
  "pip install", "pip list", "pip show", "pip freeze", "pip check",
168
186
  "pip install -e", "pip install -r",
@@ -221,6 +239,26 @@ def _get_default_denylist_standalone() -> list[str]:
221
239
  return common + ["bash", "sh", "nohup", "vi", "vim", "emacs", "nano", "su"]
222
240
 
223
241
 
242
+ def _merge_with_defaults(user_value: Any, defaults_fn: Callable[[], list[str]]) -> list[str]:
243
+ """Union user list with package defaults so `pip install -U` propagates
244
+ new defaults without clobbering user additions (Config Option A). If the
245
+ user list ends with an entry '__override__', their list is used verbatim
246
+ (escape hatch for anyone who needs to intentionally remove a default).
247
+ """
248
+ if user_value is None:
249
+ return defaults_fn()
250
+ if not isinstance(user_value, list):
251
+ return user_value # pydantic will re-type-check and fail cleanly
252
+ if "__override__" in user_value:
253
+ return [v for v in user_value if v != "__override__"]
254
+ defaults = defaults_fn()
255
+ merged = list(defaults)
256
+ for item in user_value:
257
+ if item not in merged:
258
+ merged.append(item)
259
+ return merged
260
+
261
+
224
262
  class BashToolConfig(BaseToolConfig):
225
263
  permission: ToolPermission = ToolPermission.ASK
226
264
  max_output_bytes: int = Field(
@@ -231,17 +269,40 @@ class BashToolConfig(BaseToolConfig):
231
269
  )
232
270
  allowlist: list[str] = Field(
233
271
  default_factory=_get_default_allowlist,
234
- description="Command prefixes that are automatically allowed",
272
+ description=(
273
+ "Command prefixes that are automatically allowed. User entries "
274
+ "are UNIONED with package defaults (new defaults auto-propagate "
275
+ "on pip install -U). Include '__override__' in the list to use "
276
+ "your list verbatim and skip defaults."
277
+ ),
235
278
  )
236
279
  denylist: list[str] = Field(
237
280
  default_factory=_get_default_denylist,
238
- description="Command prefixes that are automatically denied",
281
+ description=(
282
+ "Command prefixes that are automatically denied. User entries "
283
+ "unioned with package defaults; see allowlist for override."
284
+ ),
239
285
  )
240
286
  denylist_standalone: list[str] = Field(
241
287
  default_factory=_get_default_denylist_standalone,
242
288
  description="Commands that are denied only when run without arguments",
243
289
  )
244
290
 
291
+ @field_validator("allowlist", mode="before")
292
+ @classmethod
293
+ def _merge_allowlist(cls, v: Any) -> list[str]:
294
+ return _merge_with_defaults(v, _get_default_allowlist)
295
+
296
+ @field_validator("denylist", mode="before")
297
+ @classmethod
298
+ def _merge_denylist(cls, v: Any) -> list[str]:
299
+ return _merge_with_defaults(v, _get_default_denylist)
300
+
301
+ @field_validator("denylist_standalone", mode="before")
302
+ @classmethod
303
+ def _merge_denylist_standalone(cls, v: Any) -> list[str]:
304
+ return _merge_with_defaults(v, _get_default_denylist_standalone)
305
+
245
306
 
246
307
  class BashArgs(BaseModel):
247
308
  command: str
@@ -92,63 +92,56 @@ class ReadFile(
92
92
  )
93
93
  return
94
94
 
95
+ # mtime-based read dedup (Claude Code tool-contract pattern).
96
+ # If the model reads a file it has already read this session and
97
+ # nothing has changed on disk since, return a compact stub
98
+ # pointing to the earlier tool_result. Saves context + kills the
99
+ # "re-read 50x for no reason" pattern. Also preserves Read-before-
100
+ # Write because the stub still counts as having read the file.
101
+ read_state = ctx.read_file_state if ctx else None
102
+ path_key = str(file_path)
103
+ try:
104
+ current_mtime = file_path.stat().st_mtime_ns
105
+ except OSError:
106
+ current_mtime = 0
107
+ prior = read_state.get(path_key) if read_state is not None else None
108
+ if (
109
+ prior is not None
110
+ and prior.get("timestamp") == current_mtime
111
+ and prior.get("offset") == args.offset
112
+ and prior.get("limit") == args.limit
113
+ ):
114
+ yield ReadFileResult(
115
+ 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,
127
+ )
128
+ return
129
+
95
130
  read_result = await self._read_file(args, file_path)
96
131
  content = "".join(read_result.lines)
97
132
 
98
- # Mechanical loop-breaker: if the model reads the SAME path with
99
- # the SAME (offset, limit) 3+ times in a row and the content
100
- # hasn't changed, replace the body with a compact notice so the
101
- # loop is visible. The model keeps burning context on identical
102
- # reads (confirmed: one session had 52 identical read_file calls
103
- # on lang_interp/lexer.py). This makes the re-read USELESS so it
104
- # stops being attractive.
105
- state = self.state.__dict__.setdefault("_read_history", {})
106
- key = (str(file_path), args.offset, args.limit)
107
- entry = state.get(key)
108
- now_hash = hash(content)
109
- if entry and entry["hash"] == now_hash:
110
- entry["count"] += 1
111
- # Tier 2 (5th identical read): ToolError — notice alone is
112
- # being ignored by Gemma 4. An error forces the model through
113
- # the error-handling path, which it reacts to.
114
- if entry["count"] >= 5:
115
- from drydock.core.tools.base import ToolError as _TE
116
- raise _TE(
117
- f"REFUSED: you have already read {file_path.name} "
118
- f"{entry['count']} times with no file changes in "
119
- f"between. The content is in your context already. "
120
- f"STOP re-reading and DO something: edit the file, "
121
- f"read a DIFFERENT file, or run the code. This read "
122
- f"is refused until a different action happens."
123
- )
124
- if entry["count"] >= 3:
125
- notice = (
126
- f"[NOTICE: this is read_file call #{entry['count']} "
127
- f"for {file_path.name} with no file changes since the "
128
- f"previous reads. The content below is IDENTICAL to "
129
- f"what you already have. STOP re-reading — use the "
130
- f"content from your context. Either edit the file "
131
- f"with search_replace/write_file, or call a different "
132
- f"tool.]\n"
133
- )
134
- # Return only the first 10 lines + the notice, so the
135
- # model isn't spending context on identical body.
136
- short = content.split("\n", 10)
137
- shortened = "\n".join(short[:10])
138
- if len(short) > 10:
139
- shortened += f"\n... [body elided on repeat read #{entry['count']}]"
140
- yield ReadFileResult(
141
- path=str(file_path),
142
- content=notice + shortened,
143
- lines_read=len(read_result.lines),
144
- was_truncated=True,
145
- )
146
- return
147
- else:
148
- state[key] = {"hash": now_hash, "count": 1}
133
+ # Record read state so Write/Edit can enforce Read-before-Write
134
+ # and so future re-reads can dedup against this one.
135
+ if read_state is not None:
136
+ read_state[path_key] = {
137
+ "content": content,
138
+ "timestamp": current_mtime,
139
+ "offset": args.offset,
140
+ "limit": args.limit,
141
+ }
149
142
 
150
143
  yield ReadFileResult(
151
- path=str(file_path),
144
+ path=path_key,
152
145
  content=content,
153
146
  lines_read=len(read_result.lines),
154
147
  was_truncated=read_result.was_truncated,
@@ -180,6 +180,53 @@ class SearchReplace(
180
180
  return
181
181
  raise
182
182
 
183
+ # Read-before-Edit enforcement (Claude Code tool contract).
184
+ # Editing a file without having seen it is the #1 cause of the
185
+ # "SEARCH text not found" failure cascade. Require the model to
186
+ # have read this path (or just written it) this session.
187
+ # Structured rejection (not ToolError) — model sees guidance in
188
+ # the result content and pivots to read_file.
189
+ read_state = ctx.read_file_state if ctx else None
190
+ path_key = str(file_path)
191
+ if read_state is not None and file_path.exists():
192
+ prior = read_state.get(path_key)
193
+ if prior is None:
194
+ yield SearchReplaceResult(
195
+ file=path_key,
196
+ blocks_applied=0,
197
+ lines_changed=0,
198
+ warnings=[],
199
+ content=(
200
+ "<system-reminder>\n"
201
+ f"{file_path.name} has not been read this session. "
202
+ "Use read_file first so you can see the current "
203
+ "contents — then search_replace with the actual "
204
+ "text from the file. This edit was NOT applied.\n"
205
+ "</system-reminder>"
206
+ ),
207
+ )
208
+ return
209
+ try:
210
+ current_mtime = file_path.stat().st_mtime_ns
211
+ except OSError:
212
+ current_mtime = 0
213
+ if prior.get("timestamp") and current_mtime and current_mtime > prior["timestamp"]:
214
+ yield SearchReplaceResult(
215
+ file=path_key,
216
+ blocks_applied=0,
217
+ lines_changed=0,
218
+ warnings=[],
219
+ content=(
220
+ "<system-reminder>\n"
221
+ f"{file_path.name} was modified on disk since your "
222
+ "last read. Re-read before editing to avoid "
223
+ "clobbering changes you haven't seen. This edit "
224
+ "was NOT applied.\n"
225
+ "</system-reminder>"
226
+ ),
227
+ )
228
+ return
229
+
183
230
  # Injection guard: scan replacement content for suspicious patterns
184
231
  from drydock.core.tools.injection_guard import check_content_for_injection
185
232
  if warning := check_content_for_injection(args.content, args.file_path):
@@ -277,6 +324,20 @@ class SearchReplace(
277
324
 
278
325
  await self._write_file(file_path, modified_content)
279
326
 
327
+ # Update read_file_state so chained edits don't trip Read-
328
+ # before-Edit. We just wrote — we know disk state.
329
+ if read_state is not None:
330
+ try:
331
+ new_mtime = file_path.stat().st_mtime_ns
332
+ except OSError:
333
+ new_mtime = 0
334
+ read_state[path_key] = {
335
+ "content": modified_content,
336
+ "timestamp": new_mtime,
337
+ "offset": 0,
338
+ "limit": None,
339
+ }
340
+
280
341
  # Auto-verify syntax for Python files
281
342
  if file_path.suffix == ".py":
282
343
  try: