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.
- drydock_cli-2.6.83/.auto_release.lock +1 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/PKG-INFO +1 -1
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/entrypoint.py +17 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/agent_loop.py +7 -0
- drydock_cli-2.6.83/drydock/core/config/doctor.py +222 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/base.py +5 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/bash.py +66 -5
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/read_file.py +45 -52
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/search_replace.py +61 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/write_file.py +117 -10
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/pyproject.toml +1 -1
- drydock_cli-2.6.82/.auto_release.lock +0 -1
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.claude/scheduled_tasks.lock +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/CODEOWNERS +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/workflows/build-and-upload.yml +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/workflows/ci.yml +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/workflows/issue-labeler.yml +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.github/workflows/release.yml +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.gitignore +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.pre-commit-config.yaml +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.python-version +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.typos.toml +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.vscode/extensions.json +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.vscode/launch.json +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/.vscode/settings.json +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/AGENTS.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/BASELINE_412.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/CHANGELOG.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/CLAUDE.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/CONTRIBUTING.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/Drydock_rebrand.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/LICENSE +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/MODEL_SHORTCOMINGS.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/NOTICE +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/OVERNIGHT_REPORT_2026_04_13.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/PRD.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/README.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/action.yml +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/README.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results1.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results13.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results14.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results15.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results16.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results17.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results18.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results19.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results2.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results20.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results3.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results4.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results5.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results6.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results7.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results8.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results9.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/baseline_history/results_evolved_v1.tsv +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/distribution/zed/LICENSE +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/distribution/zed/extension.toml +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/distribution/zed/icons/mistral_vibe.svg +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/docs/README.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/docs/acp-setup.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/docs/proxy-setup.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/acp_agent_loop.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/acp_logger.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/entrypoint.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/base.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/bash.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/read_file.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/search_replace.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/todo.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/builtins/write_file.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/tools/session_update.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/acp/utils.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/autocompletion/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/autocompletion/base.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/autocompletion/path_completion.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/autocompletion/slash_command.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/cli.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/clipboard.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/commands.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/history_manager.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/terminal_setup.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/app.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/app.tcss +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/external_editor.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/compact.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/loading.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/messages.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/tools.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/windowing/history.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/textual_ui/windowing/state.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/update.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/cli/update_notifier/whats_new.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/agents/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/agents/manager.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/agents/models.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/auth/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/auth/crypto.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/auth/github.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/completers.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/store.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/fuzzy.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/path_prompt.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/build_orchestrator.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/config/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/config/_settings.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/config/harness_files/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/config/harness_files/_harness_manager.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/config/harness_files/_paths.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/consultant.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/drydock_states.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/hooks.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/backend/anthropic.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/backend/base.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/backend/factory.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/backend/generic.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/backend/mistral.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/backend/vertex.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/exceptions.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/format.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/message_utils.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/llm/types.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/logger.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/middleware.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/output_formatters.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/paths/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/paths/_local_config_walk.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/paths/_vibe_home.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/paths/conventions.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/plan_session.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/plugins.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/programmatic.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/builder.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/cli.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/compact.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/dangerous_directory.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/diagnostic.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/explore.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/gemma4.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/planner.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/project_context.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/prompts/tests.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/proxy_setup.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/session/agent_memory.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/session/checkpoints.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/session/session_loader.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/session/session_logger.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/session/session_migration.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/session/state_file.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/session_checker.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/skills/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/skills/manager.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/skills/models.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/skills/parser.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/slug.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/system_prompt.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/telemetry/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/telemetry/send.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/teleport/errors.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/teleport/git.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/teleport/nuage.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/teleport/teleport.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/teleport/types.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/_task_manager.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/ask_user_question.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/cron.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/glob_tool.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/grep.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/invoke_skill.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/lsp.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/mcp_resources.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/notebook_edit.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/powershell.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/bash.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/cron.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/glob.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/grep.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/invoke_skill.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/lsp.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/mcp_resources.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/powershell.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/task.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/todo.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/tool_search.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/worktree.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/task.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/todo.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/tool_search.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/webfetch.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/websearch.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/builtins/worktree.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/injection_guard.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/manager.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/mcp/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/mcp/registry.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/mcp/tools.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/mcp_sampling.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/ui.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/tools/utils.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/trusted_folders.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/types.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/core/utils.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/onboarding/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/onboarding/base.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/onboarding/onboarding.tcss +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/onboarding/screens/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/onboarding/screens/api_key.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/onboarding/screens/welcome.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/api-design/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/audit-tests/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/batch/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/commit-code/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/context-summary/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/create-presentation/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/deep-research/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/deploy/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/diff-review/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/doc-gen/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/explain-code/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/explore-code/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/fix-issue/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/git-ops/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/init-project/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/investigate/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/loop/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/migrate/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/perf-analyze/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/plan-impl/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/pr-review/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/refactor/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/regex-help/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/review/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/security-review/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/ship/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/simplify/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/strong-tests/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/skills/test-verify/SKILL.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock/whats_new.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock-acp.spec +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/drydock_terms.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/flake.lock +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/flake.nix +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/README.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/audit_sampler.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/auto_generate_tests.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/auto_release.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/auto_test_loop.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/backup.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/bump_version.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/comprehensive_loop.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/deploy_to_github.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/discover_cli_tools.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/evolve_tests.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/install.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/llm_balancer.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/mega_loop.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/meta_ralph_loop.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/monitor_swebench.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/monitor_test_battery.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/notify_release.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/oss_task_harness.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/overnight_agents_test.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/port_task.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/prepare_release.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/publish_to_pypi.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/ralph_loop.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/session_loop_audit.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/shakedown.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/shakedown_interactive.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/shakedown_regression.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/shakedown_suite.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/shakedown_variance.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/telegram_bot.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/test_bank.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/test_full.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/test_smoke.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/test_tui_path.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/tui_test.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/scripts/vllm_failover.sh +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/conftest.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_acp.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_agent_thought.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_bash.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_compact_session_updates.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_content.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_initialize.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_list_sessions.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_load_session.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_multi_session.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_new_session.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_proxy_setup_acp.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_read_file.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_search_replace.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_set_config_option.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_set_mode.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_set_model.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_tool_call_session_update.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_utils.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/acp/test_write_file.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_file_indexer.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_fuzzy.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_path_completer_recursive.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_path_completion_controller.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_slash_command_controller.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/data/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/data/fireworks.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/data/mistral.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/test_anthropic_adapter.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/test_backend.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/test_reasoning_adapter.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_bell_notifications.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_braille_renderer.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_clipboard.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_commands.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_copy_shortcuts.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_external_editor.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_no_markup_static.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_question_app.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_spinner.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_switching_mode.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_ui_clipboard_notifications.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_ui_session_resume.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/test_ui_skill_dispatch.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/cli/textual_ui/test_session_picker.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/conftest.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_agents.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_auth_crypto.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_auth_github.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_config_load_dotenv.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_config_paths.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_config_resolution.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_file_logging.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_plan_session.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_proxy_setup.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_slug.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_telemetry_send.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_teleport_git.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_teleport_nuage.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_teleport_service.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_trusted_folders.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/core/test_utils.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/e2e/common.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/e2e/conftest.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/e2e/mock_server.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/e2e/test_cli_tui_onboarding.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/e2e/test_cli_tui_streaming.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/fixtures/doc_qa_system_prd.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/mock/__init__.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/mock/mock_backend_factory.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/mock/mock_entrypoint.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/mock/utils.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/onboarding/test_run_onboarding.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/onboarding/test_ui_onboarding.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/session/test_session_loader.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/session/test_session_logger.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/session/test_session_migration.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/skills/conftest.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/skills/test_manager.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/skills/test_models.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/skills/test_parser.py +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/base_snapshot_test_app.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/conftest.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/snap_compare.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/stubs/fake_backend.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/stubs/fake_client.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/stubs/fake_tool.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_agent_auto_compact.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_agent_backend.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_agent_observer_streaming.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_agent_stats.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_agent_tasks.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_agent_tool_call.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_agents.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_bank_build.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_bank_debug.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_bank_multiagent.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_bank_prd.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_bank_prd_extended.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_bank_tools.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_bank_update.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_build_projects.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_cli_programmatic_preload.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_current_bugs.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_drydock_regression.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_drydock_tasks.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_full_regression.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_history_manager.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_integration.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_loop_detection.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_message_id.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_message_merging.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_middleware.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_multi_agent.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_real_failures.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_real_issues.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_real_workflow.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_reasoning_content.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_smoke.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_system_prompt.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_tagged_text.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_tool_args.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_ui_external_editor.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_ui_input_history.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_user_issues.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/test_workloads.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/testbank_helpers.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_ask_user_question.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_bash.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_exit_plan_mode.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_grep.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_invoke_context.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_manager_get_tool_config.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_mcp.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_mcp_sampling.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_task.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_ui_bash_execution.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_webfetch.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/tools/test_websearch.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/test_do_update.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/test_github_update_gateway.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/test_ui_update_notification.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/test_update_use_case.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/tests/update_notifier/test_whats_new.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/uv.lock +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/worked_examples/README.md +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/worked_examples/cli_subcommand_dispatch.py +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/worked_examples/lookup.json +0 -0
- {drydock_cli-2.6.82 → drydock_cli-2.6.83}/worked_examples/sql_parser.py +0 -0
- {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.
|
|
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", "
|
|
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=
|
|
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=
|
|
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
|
-
#
|
|
99
|
-
#
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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=
|
|
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:
|