drydock-cli 2.1.3__tar.gz → 2.2.1__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.1.3 → drydock_cli-2.2.1}/PKG-INFO +1 -1
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/PRD.md +42 -5
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/app.py +2 -1
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/agent_loop.py +28 -52
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/pyproject.toml +1 -1
- drydock_cli-2.2.1/scripts/overnight_agents_test.sh +219 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_drydock_tasks.py +8 -8
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_loop_detection.py +18 -20
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_user_issues.py +15 -18
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.github/CODEOWNERS +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.github/workflows/build-and-upload.yml +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.github/workflows/ci.yml +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.github/workflows/issue-labeler.yml +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.github/workflows/release.yml +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.gitignore +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.pre-commit-config.yaml +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.python-version +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.typos.toml +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.vscode/extensions.json +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.vscode/launch.json +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/.vscode/settings.json +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/AGENTS.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/CHANGELOG.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/CLAUDE.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/CONTRIBUTING.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/Drydock_rebrand.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/LICENSE +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/NOTICE +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/README.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/action.yml +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/distribution/zed/LICENSE +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/distribution/zed/extension.toml +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/distribution/zed/icons/mistral_vibe.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/docs/README.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/docs/acp-setup.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/docs/proxy-setup.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/acp/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/acp/acp_agent_loop.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/acp/acp_logger.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/acp/entrypoint.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/acp/tools/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/acp/tools/base.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/acp/tools/builtins/bash.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/acp/tools/builtins/read_file.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/acp/tools/builtins/search_replace.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/acp/tools/builtins/todo.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/acp/tools/builtins/write_file.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/acp/tools/session_update.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/acp/utils.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/autocompletion/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/autocompletion/base.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/autocompletion/path_completion.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/autocompletion/slash_command.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/cli.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/clipboard.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/commands.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/entrypoint.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/history_manager.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/terminal_setup.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/app.tcss +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/external_editor.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/compact.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/loading.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/messages.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/tools.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/windowing/history.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/textual_ui/windowing/state.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/update_notifier/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/update_notifier/update.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/cli/update_notifier/whats_new.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/agents/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/agents/manager.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/agents/models.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/auth/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/auth/crypto.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/auth/github.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/autocompletion/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/autocompletion/completers.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/autocompletion/file_indexer/store.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/autocompletion/fuzzy.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/autocompletion/path_prompt.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/build_orchestrator.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/config/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/config/_settings.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/config/harness_files/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/config/harness_files/_harness_manager.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/config/harness_files/_paths.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/consultant.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/drydock_states.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/hooks.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/llm/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/llm/backend/anthropic.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/llm/backend/base.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/llm/backend/factory.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/llm/backend/generic.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/llm/backend/mistral.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/llm/backend/vertex.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/llm/exceptions.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/llm/format.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/llm/message_utils.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/llm/types.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/logger.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/middleware.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/output_formatters.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/paths/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/paths/_local_config_walk.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/paths/_vibe_home.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/paths/conventions.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/plan_session.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/plugins.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/programmatic.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/prompts/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/prompts/builder.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/prompts/cli.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/prompts/compact.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/prompts/dangerous_directory.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/prompts/diagnostic.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/prompts/explore.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/prompts/planner.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/prompts/project_context.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/prompts/tests.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/proxy_setup.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/session/agent_memory.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/session/checkpoints.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/session/session_loader.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/session/session_logger.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/session/session_migration.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/session/state_file.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/skills/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/skills/manager.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/skills/models.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/skills/parser.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/slug.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/system_prompt.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/telemetry/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/telemetry/send.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/teleport/errors.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/teleport/git.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/teleport/nuage.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/teleport/teleport.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/teleport/types.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/base.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/ask_user_question.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/bash.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/cron.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/glob_tool.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/grep.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/invoke_skill.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/lsp.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/mcp_resources.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/notebook_edit.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/powershell.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/bash.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/cron.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/glob.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/grep.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/invoke_skill.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/lsp.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/mcp_resources.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/powershell.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/task.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/todo.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/tool_search.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/worktree.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/read_file.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/search_replace.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/task.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/task_manager.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/todo.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/tool_search.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/webfetch.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/websearch.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/worktree.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/builtins/write_file.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/injection_guard.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/manager.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/mcp/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/mcp/registry.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/mcp/tools.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/mcp_sampling.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/ui.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/tools/utils.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/trusted_folders.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/types.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/core/utils.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/setup/onboarding/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/setup/onboarding/base.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/setup/onboarding/onboarding.tcss +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/setup/onboarding/screens/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/setup/onboarding/screens/api_key.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/setup/onboarding/screens/welcome.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/skills/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/skills/batch/SKILL.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/skills/create-presentation/SKILL.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/skills/deep-research/SKILL.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/skills/investigate/SKILL.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/skills/review/SKILL.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/skills/ship/SKILL.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/skills/simplify/SKILL.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock/whats_new.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock-acp.spec +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/drydock_terms.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/flake.lock +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/flake.nix +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/scripts/README.md +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/scripts/auto_test_loop.sh +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/scripts/backup.sh +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/scripts/bump_version.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/scripts/deploy_to_github.sh +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/scripts/install.sh +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/scripts/monitor_test_battery.sh +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/scripts/notify_release.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/scripts/prepare_release.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/scripts/publish_to_pypi.sh +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/scripts/test_bank.sh +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/scripts/test_full.sh +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/scripts/test_smoke.sh +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/conftest.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_acp.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_agent_thought.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_bash.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_compact_session_updates.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_content.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_initialize.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_list_sessions.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_load_session.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_multi_session.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_new_session.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_proxy_setup_acp.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_read_file.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_search_replace.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_set_config_option.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_set_mode.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_set_model.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_tool_call_session_update.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_utils.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/acp/test_write_file.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/autocompletion/test_file_indexer.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/autocompletion/test_fuzzy.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/autocompletion/test_path_completer_recursive.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/autocompletion/test_path_completion_controller.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/autocompletion/test_slash_command_controller.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/backend/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/backend/data/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/backend/data/fireworks.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/backend/data/mistral.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/backend/test_anthropic_adapter.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/backend/test_backend.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/backend/test_reasoning_adapter.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/test_bell_notifications.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/test_braille_renderer.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/test_clipboard.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/test_commands.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/test_copy_shortcuts.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/test_external_editor.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/test_no_markup_static.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/test_question_app.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/test_spinner.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/test_switching_mode.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/test_ui_clipboard_notifications.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/test_ui_session_resume.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/test_ui_skill_dispatch.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/cli/textual_ui/test_session_picker.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/conftest.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_agents.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_auth_crypto.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_auth_github.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_config_load_dotenv.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_config_paths.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_config_resolution.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_file_logging.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_plan_session.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_proxy_setup.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_slug.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_telemetry_send.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_teleport_git.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_teleport_nuage.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_teleport_service.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_trusted_folders.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/core/test_utils.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/e2e/common.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/e2e/conftest.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/e2e/mock_server.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/e2e/test_cli_tui_onboarding.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/e2e/test_cli_tui_streaming.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/mock/__init__.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/mock/mock_backend_factory.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/mock/mock_entrypoint.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/mock/utils.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/onboarding/test_run_onboarding.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/onboarding/test_ui_onboarding.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/session/test_session_loader.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/session/test_session_logger.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/session/test_session_migration.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/skills/conftest.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/skills/test_manager.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/skills/test_models.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/skills/test_parser.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/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.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/base_snapshot_test_app.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/conftest.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/snap_compare.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/stubs/fake_backend.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/stubs/fake_client.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/stubs/fake_tool.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_agent_auto_compact.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_agent_backend.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_agent_observer_streaming.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_agent_stats.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_agent_tasks.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_agent_tool_call.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_agents.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_bank_build.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_bank_debug.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_bank_multiagent.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_bank_prd.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_bank_prd_extended.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_bank_tools.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_bank_update.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_build_projects.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_cli_programmatic_preload.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_current_bugs.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_drydock_regression.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_full_regression.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_history_manager.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_integration.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_message_id.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_message_merging.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_middleware.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_multi_agent.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_real_failures.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_real_issues.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_real_workflow.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_reasoning_content.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_smoke.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_system_prompt.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_tagged_text.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_ui_external_editor.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_ui_input_history.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/test_workloads.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/testbank_helpers.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/tools/test_ask_user_question.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/tools/test_bash.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/tools/test_exit_plan_mode.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/tools/test_grep.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/tools/test_invoke_context.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/tools/test_manager_get_tool_config.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/tools/test_mcp.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/tools/test_mcp_sampling.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/tools/test_task.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/tools/test_ui_bash_execution.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/tools/test_webfetch.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/tools/test_websearch.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/update_notifier/test_do_update.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/update_notifier/test_github_update_gateway.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/update_notifier/test_ui_update_notification.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/update_notifier/test_update_use_case.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/tests/update_notifier/test_whats_new.py +0 -0
- {drydock_cli-2.1.3 → drydock_cli-2.2.1}/uv.lock +0 -0
|
@@ -547,11 +547,48 @@ Evidence: removing this one line improved `task(agent="explore")` usage from 1/5
|
|
|
547
547
|
- Telegram release notifications
|
|
548
548
|
- `whats_new.md` updated
|
|
549
549
|
|
|
550
|
+
### Phase 15 (Mar 31): Meta-Harness Framework + SWE-bench Push
|
|
551
|
+
|
|
552
|
+
**Paper:** "Meta-Harness: End-to-End Optimization of Model Harnesses" (arXiv:2603.28052)
|
|
553
|
+
**Key insight:** Optimize the harness around the model, not the model itself. A harness change gave +18pp on TerminalBench-2.
|
|
554
|
+
|
|
555
|
+
**What we implemented from Meta-Harness:**
|
|
556
|
+
|
|
557
|
+
1. **Environment bootstrapping** — Single compound shell command before first LLM call gathers:
|
|
558
|
+
- Repo structure (`find . -name "*.py" | head -30`)
|
|
559
|
+
- Python version, test framework
|
|
560
|
+
- Top-level directories, recent commits
|
|
561
|
+
- Injected as `[Environment Snapshot]` in the prompt
|
|
562
|
+
- Eliminates 2-4 wasted exploratory turns
|
|
563
|
+
|
|
564
|
+
2. **AGENTS.md per SWE-bench task** — Auto-created in each worktree with bug-fix workflow instructions
|
|
565
|
+
|
|
566
|
+
3. **Additive-only changes** — Paper proved that modifying control flow regresses. Only ADD context before the agent loop. This validates our decision to disable the orchestrator and circuit breaker.
|
|
567
|
+
|
|
568
|
+
**SWE-bench status:**
|
|
569
|
+
- Baseline (v2.1.3 + AGENTS.md): 4/10 file matches (40%)
|
|
570
|
+
- 50-task eval running with env bootstrapping
|
|
571
|
+
- Previous "39-42% pass rate" was file-match only — actual test pass rate was 0%
|
|
572
|
+
- Target: 68% (devstral-small-2 24B, per Mistral's published results)
|
|
573
|
+
- Mistral achieved 68% with Vibe CLI + Cline harness
|
|
574
|
+
|
|
575
|
+
**Meta-Harness techniques still to implement:**
|
|
576
|
+
- Double-confirmation before completion (verify checklist)
|
|
577
|
+
- Execution trace logging for systematic failure diagnosis
|
|
578
|
+
- Repo-specific routing (different strategies per SWE-bench repo)
|
|
579
|
+
- Draft-then-verify for patches
|
|
580
|
+
- Contrastive examples for decision boundaries
|
|
581
|
+
|
|
582
|
+
**Reference:** https://github.com/stanford-iris-lab/meta-harness-tbench2-artifact
|
|
583
|
+
|
|
550
584
|
### Lessons Learned (Updated)
|
|
551
585
|
|
|
552
586
|
1. **One prompt line can block an entire feature.** "Restate the goal" prevented tool calling for months.
|
|
553
|
-
2. **
|
|
554
|
-
3. **
|
|
555
|
-
4. **
|
|
556
|
-
5. **
|
|
557
|
-
6. **
|
|
587
|
+
2. **AGENTS.md is essential for devstral.** Without per-project instructions file, model loops on ls/bash. Auto-created on first session.
|
|
588
|
+
3. **Additive-only harness changes work best.** Every control flow modification (circuit breaker, orchestrator, nudges) caused regressions. Just inject better context.
|
|
589
|
+
4. **The harness matters as much as the model.** Meta-Harness paper shows 6x performance gap from harness changes alone.
|
|
590
|
+
5. **Environment bootstrapping saves turns.** Pre-gathering repo structure/versions eliminates 2-4 wasted exploration turns.
|
|
591
|
+
6. **Plan→Edit workflow is Mistral's design.** Use plan mode first, then switch to accept-edits. Don't try to do everything in one agent shot.
|
|
592
|
+
7. **Same-process API calls can fail.** httpx from inside DryDock got 404 from vLLM. Use the existing backend connection.
|
|
593
|
+
8. **Test the installed package, not source.** Different Python envs (miniconda3 vs miniforge3) have different behavior.
|
|
594
|
+
9. **Explicit Python paths everywhere.** Cron doesn't inherit PATH. Every script must use the full path.
|
|
@@ -398,7 +398,8 @@ class VibeApp(App): # noqa: PLR0904
|
|
|
398
398
|
if not hasattr(self, "_pending_messages"):
|
|
399
399
|
self._pending_messages: list[str] = []
|
|
400
400
|
self._pending_messages.append(value)
|
|
401
|
-
|
|
401
|
+
preview = value[:60] + "..." if len(value) > 60 else value
|
|
402
|
+
self.notify(f"Queued: \"{preview}\" ({len(self._pending_messages)} pending)")
|
|
402
403
|
return
|
|
403
404
|
|
|
404
405
|
if value.startswith("!"):
|
|
@@ -299,7 +299,8 @@ class AgentLoop:
|
|
|
299
299
|
# Auto-create AGENTS.md if no project instructions exist.
|
|
300
300
|
# devstral needs per-project AGENTS.md to anchor its behavior —
|
|
301
301
|
# without it the model loops on ls/bash instead of using subagents.
|
|
302
|
-
self.
|
|
302
|
+
if self.stats.steps <= 1:
|
|
303
|
+
self._ensure_agents_md()
|
|
303
304
|
|
|
304
305
|
# Load project state for cross-session context
|
|
305
306
|
try:
|
|
@@ -541,11 +542,14 @@ class AgentLoop:
|
|
|
541
542
|
except (RuntimeError, AgentLoopLLMResponseError) as e:
|
|
542
543
|
api_error_count += 1
|
|
543
544
|
if api_error_count > MAX_API_ERRORS:
|
|
545
|
+
# Don't stop — reset and let the user know
|
|
546
|
+
import asyncio as _aio
|
|
544
547
|
yield AssistantEvent(
|
|
545
|
-
content=f"\n\n[
|
|
546
|
-
stopped_by_middleware=True,
|
|
548
|
+
content=f"\n\n[{api_error_count} consecutive API errors. Waiting 10s then retrying. Last error: {str(e)[:200]}]\n",
|
|
547
549
|
)
|
|
548
|
-
|
|
550
|
+
await _aio.sleep(10)
|
|
551
|
+
api_error_count = 0 # Reset — give it another chance
|
|
552
|
+
continue
|
|
549
553
|
# Check if the error is about invalid function/tool name
|
|
550
554
|
error_str = str(e)
|
|
551
555
|
if "Function name" in error_str or "function" in error_str.lower() and "must be" in error_str.lower():
|
|
@@ -695,12 +699,12 @@ class AgentLoop:
|
|
|
695
699
|
"Your NEXT action MUST be write_file to create a file or "
|
|
696
700
|
"search_replace to edit one. Do NOT run any more bash commands."
|
|
697
701
|
)
|
|
698
|
-
elif bash_count >= 10:
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
+
elif bash_count >= 10 and bash_count % 5 == 0:
|
|
703
|
+
# Nudge every 5 bash calls, never stop
|
|
704
|
+
self._inject_system_note(
|
|
705
|
+
"You have run many bash commands. Consider using write_file "
|
|
706
|
+
"or search_replace to create/edit files."
|
|
702
707
|
)
|
|
703
|
-
return
|
|
704
708
|
|
|
705
709
|
# 3-Strike Rule: search_replace keeps failing
|
|
706
710
|
if search_replace_failures >= 3:
|
|
@@ -817,54 +821,26 @@ class AgentLoop:
|
|
|
817
821
|
if nudge_text:
|
|
818
822
|
self._inject_system_note(nudge_text)
|
|
819
823
|
|
|
820
|
-
#
|
|
824
|
+
# Loop guidance — prune duplicates and nudge, NEVER stop
|
|
821
825
|
if not should_break_loop:
|
|
822
826
|
rep = self._check_tool_call_repetition()
|
|
823
|
-
if rep == "FORCE_STOP":
|
|
824
|
-
repeat_warnings += 1
|
|
825
|
-
logger.warning("Detected infinite loop: same tool call %d+ times (warning %d)", REPEAT_FORCE_STOP_THRESHOLD, repeat_warnings)
|
|
826
|
-
if repeat_warnings >= 5:
|
|
827
|
-
# Stop after 5 redirects — model is not recovering
|
|
828
|
-
yield AssistantEvent(
|
|
829
|
-
content="\n\n[Stopping: exhausted all retry attempts.]\n",
|
|
830
|
-
stopped_by_middleware=True,
|
|
831
|
-
)
|
|
832
|
-
return
|
|
833
|
-
# Redirect instead of kill — force an edit attempt
|
|
834
|
-
self._inject_system_note(
|
|
835
|
-
"CRITICAL: You are in an infinite loop. STOP all searching/reading. "
|
|
836
|
-
"Based on what you have already seen, use search_replace RIGHT NOW to make "
|
|
837
|
-
"your best fix attempt. If you don't know the exact text, use read_file ONE MORE TIME "
|
|
838
|
-
"on the specific function, then search_replace immediately.",
|
|
839
|
-
replace_last_tool=True,
|
|
840
|
-
)
|
|
841
|
-
self._prune_repeated_tool_calls()
|
|
842
|
-
elif rep and rep.startswith("WARNING"):
|
|
843
|
-
# During investigation (no edit yet), soft-count warnings from
|
|
844
|
-
# investigation tools — they need room to explore.
|
|
827
|
+
if rep == "FORCE_STOP" or (rep and rep.startswith("WARNING")):
|
|
845
828
|
stuck_tool = ""
|
|
846
|
-
if "|" in rep:
|
|
829
|
+
if rep and "|" in rep:
|
|
847
830
|
stuck_tool = rep.split("|", 1)[1]
|
|
848
|
-
is_investigation_warning = (
|
|
849
|
-
not has_made_edit
|
|
850
|
-
and stuck_tool in ("grep", "read_file")
|
|
851
|
-
)
|
|
852
|
-
if is_investigation_warning:
|
|
853
|
-
repeat_warnings += 0.3 # Count less — investigation needs room
|
|
854
|
-
else:
|
|
855
|
-
repeat_warnings += 1
|
|
856
|
-
logger.warning("Detected repeated tool calls (warning %.1f, investigation=%s)", repeat_warnings, is_investigation_warning)
|
|
857
|
-
if repeat_warnings >= 6:
|
|
858
|
-
yield AssistantEvent(
|
|
859
|
-
content="\n\n[Stopping: too many repeated actions despite warnings.]\n",
|
|
860
|
-
stopped_by_middleware=True,
|
|
861
|
-
)
|
|
862
|
-
return
|
|
863
831
|
|
|
864
|
-
#
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
832
|
+
# Prune duplicate tool calls to give model fresh context
|
|
833
|
+
self._prune_repeated_tool_calls()
|
|
834
|
+
|
|
835
|
+
# Gentle nudge — just suggest a different approach
|
|
836
|
+
nudge = "Try a different approach."
|
|
837
|
+
if stuck_tool in ("read_file",):
|
|
838
|
+
nudge = "You already read this. Try search_replace or a different file."
|
|
839
|
+
elif stuck_tool in ("grep",):
|
|
840
|
+
nudge = "Try a different search term or read a file you found."
|
|
841
|
+
elif stuck_tool in ("bash", "run_command"):
|
|
842
|
+
nudge = "If the command failed, read the error and fix the code."
|
|
843
|
+
self._inject_system_note(nudge)
|
|
868
844
|
|
|
869
845
|
# Extract tool-specific nudge
|
|
870
846
|
nudge = ""
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Overnight test: Try different AGENTS.md versions with plan→build workflow
|
|
3
|
+
# Tests DryDock's ability to build the log analyzer from PRD
|
|
4
|
+
# Runs for up to 20 hours, logs all results
|
|
5
|
+
|
|
6
|
+
set -uo pipefail
|
|
7
|
+
export PATH="/home/bobef/miniconda3/bin:$PATH"
|
|
8
|
+
PYTHON="/home/bobef/miniconda3/bin/python3"
|
|
9
|
+
DRYDOCK="/data3/drydock"
|
|
10
|
+
RESULTS="$DRYDOCK/test_bank_results/agents_md_test"
|
|
11
|
+
PRD="/data3/test_drydock/PRD.md"
|
|
12
|
+
MAX_HOURS=20
|
|
13
|
+
START=$(date +%s)
|
|
14
|
+
|
|
15
|
+
mkdir -p "$RESULTS"
|
|
16
|
+
|
|
17
|
+
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$RESULTS/run.log"; }
|
|
18
|
+
|
|
19
|
+
check_time() {
|
|
20
|
+
NOW=$(date +%s)
|
|
21
|
+
ELAPSED=$(( (NOW - START) / 3600 ))
|
|
22
|
+
if [ "$ELAPSED" -ge "$MAX_HOURS" ]; then
|
|
23
|
+
log "Time limit reached ($ELAPSED hours). Stopping."
|
|
24
|
+
$PYTHON "$DRYDOCK/scripts/notify_release.py" "test" "Overnight AGENTS.md test complete. $PASS passes, $FAIL fails. Check results."
|
|
25
|
+
exit 0
|
|
26
|
+
fi
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# Test a single AGENTS.md variant
|
|
30
|
+
run_test() {
|
|
31
|
+
local variant_name="$1"
|
|
32
|
+
local agents_md_content="$2"
|
|
33
|
+
local test_dir="/tmp/drydock_agentsmd_test_$$"
|
|
34
|
+
local result_file="$RESULTS/${variant_name}_$(date +%H%M%S).txt"
|
|
35
|
+
|
|
36
|
+
log "=== Testing variant: $variant_name ==="
|
|
37
|
+
|
|
38
|
+
rm -rf "$test_dir"
|
|
39
|
+
mkdir -p "$test_dir"
|
|
40
|
+
cp "$PRD" "$test_dir/PRD.md"
|
|
41
|
+
echo "$agents_md_content" > "$test_dir/AGENTS.md"
|
|
42
|
+
|
|
43
|
+
cd "$test_dir"
|
|
44
|
+
|
|
45
|
+
# Run DryDock programmatically: simulate plan→build
|
|
46
|
+
timeout 600 $PYTHON -c "
|
|
47
|
+
import asyncio, os, sys, subprocess
|
|
48
|
+
from pathlib import Path
|
|
49
|
+
sys.path.insert(0, '$DRYDOCK')
|
|
50
|
+
sys.path.insert(0, '$DRYDOCK/tests')
|
|
51
|
+
os.chdir('$test_dir')
|
|
52
|
+
from drydock.core.config.harness_files import init_harness_files_manager
|
|
53
|
+
try: init_harness_files_manager('u','p')
|
|
54
|
+
except: pass
|
|
55
|
+
from testbank_helpers import make_agent, run_workload, count_python_files, check_syntax_all
|
|
56
|
+
|
|
57
|
+
async def test():
|
|
58
|
+
agent = make_agent(Path('$test_dir'), max_turns=40)
|
|
59
|
+
r = await run_workload(agent, max_events=400, prompt='review the PRD and build the log analyzer. Test it.')
|
|
60
|
+
n = count_python_files(Path('$test_dir'))
|
|
61
|
+
errs = check_syntax_all(Path('$test_dir'))
|
|
62
|
+
print(f'RESULT: files={n} syntax_errors={len(errs)} tools={r.total_tool_calls} stops={r.force_stops}')
|
|
63
|
+
print(f'TOOLS: {r.summary()}')
|
|
64
|
+
# Check subagent usage
|
|
65
|
+
task_calls = r.tool_counts.get('task', 0)
|
|
66
|
+
print(f'SUBAGENT_CALLS: {task_calls}')
|
|
67
|
+
# Try to run
|
|
68
|
+
for d in Path('$test_dir').iterdir():
|
|
69
|
+
if d.is_dir() and (d / '__init__.py').exists():
|
|
70
|
+
result = subprocess.run(f'python3 -m {d.name} --help', shell=True, capture_output=True, text=True, timeout=10)
|
|
71
|
+
print(f'HELP: rc={result.returncode}')
|
|
72
|
+
if result.returncode == 0:
|
|
73
|
+
print(f'HELP_OUT: {result.stdout[:200]}')
|
|
74
|
+
# Try analyze
|
|
75
|
+
Path('$test_dir/test.log').write_text('2026-03-01 10:01:22 ERROR DBConnection failed: timeout\n2026-03-01 10:01:23 WARN Retrying\n2026-03-01 10:02:00 INFO Recovered\n')
|
|
76
|
+
result2 = subprocess.run(f'python3 -m {d.name} analyze test.log', shell=True, capture_output=True, text=True, timeout=10)
|
|
77
|
+
print(f'ANALYZE: rc={result2.returncode}')
|
|
78
|
+
if result2.returncode == 0:
|
|
79
|
+
print(f'ANALYZE_OUT: {result2.stdout[:300]}')
|
|
80
|
+
break
|
|
81
|
+
else:
|
|
82
|
+
print('HELP: no_package')
|
|
83
|
+
|
|
84
|
+
asyncio.run(test())
|
|
85
|
+
" > "$result_file" 2>&1
|
|
86
|
+
|
|
87
|
+
local rc=$?
|
|
88
|
+
|
|
89
|
+
# Parse results
|
|
90
|
+
local files=$(grep "RESULT:" "$result_file" 2>/dev/null | grep -o "files=[0-9]*" | cut -d= -f2)
|
|
91
|
+
local help_rc=$(grep "HELP:" "$result_file" 2>/dev/null | grep -o "rc=[0-9]*" | cut -d= -f2)
|
|
92
|
+
local analyze_rc=$(grep "ANALYZE:" "$result_file" 2>/dev/null | grep -o "rc=[0-9]*" | cut -d= -f2)
|
|
93
|
+
local subagent=$(grep "SUBAGENT_CALLS:" "$result_file" 2>/dev/null | grep -o "[0-9]*")
|
|
94
|
+
|
|
95
|
+
if [ "${analyze_rc:-1}" = "0" ]; then
|
|
96
|
+
log " FULL PASS: $files files, analyze works, subagents=$subagent"
|
|
97
|
+
echo "FULL_PASS" > "$result_file.status"
|
|
98
|
+
return 0
|
|
99
|
+
elif [ "${help_rc:-1}" = "0" ]; then
|
|
100
|
+
log " HELP PASS: $files files, --help works, subagents=$subagent"
|
|
101
|
+
echo "HELP_PASS" > "$result_file.status"
|
|
102
|
+
return 1
|
|
103
|
+
elif [ "${files:-0}" -gt "3" ]; then
|
|
104
|
+
log " PARTIAL: $files files, subagents=$subagent"
|
|
105
|
+
echo "PARTIAL" > "$result_file.status"
|
|
106
|
+
return 1
|
|
107
|
+
else
|
|
108
|
+
log " FAIL: ${files:-0} files, subagents=${subagent:-0}"
|
|
109
|
+
echo "FAIL" > "$result_file.status"
|
|
110
|
+
return 1
|
|
111
|
+
fi
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
# ============================================================================
|
|
115
|
+
# AGENTS.md Variants
|
|
116
|
+
# ============================================================================
|
|
117
|
+
|
|
118
|
+
VARIANT_A='# Project Instructions
|
|
119
|
+
|
|
120
|
+
## Workflow
|
|
121
|
+
When building a project:
|
|
122
|
+
1. Use `task(agent="planner")` to create an implementation plan first
|
|
123
|
+
2. Use `task(agent="explore")` to understand existing code
|
|
124
|
+
3. Create files using `write_file` with absolute imports
|
|
125
|
+
4. Always create `__main__.py` so `python3 -m package_name` works
|
|
126
|
+
5. Test with `bash` after creating files
|
|
127
|
+
|
|
128
|
+
## Rules
|
|
129
|
+
- Use absolute imports: `from package.module import X`, NOT `from .module import X`
|
|
130
|
+
- Always create `__init__.py` and `__main__.py` for packages
|
|
131
|
+
- Create sample test data before testing
|
|
132
|
+
- Use `python3 -m package_name` to run, NOT `python3 package/file.py`'
|
|
133
|
+
|
|
134
|
+
VARIANT_B='# Project Instructions
|
|
135
|
+
|
|
136
|
+
## Build Workflow
|
|
137
|
+
1. Read the PRD with `read_file`
|
|
138
|
+
2. Plan: use `task(agent="planner")` to create an implementation plan
|
|
139
|
+
3. Create each file with `write_file` using absolute imports
|
|
140
|
+
4. Create `__init__.py` and `__main__.py` for every package
|
|
141
|
+
5. Create sample data and test with `bash`
|
|
142
|
+
|
|
143
|
+
## Import Rules
|
|
144
|
+
- ALWAYS: `from package.module import X`
|
|
145
|
+
- NEVER: `from .module import X`
|
|
146
|
+
- Run with: `python3 -m package_name`'
|
|
147
|
+
|
|
148
|
+
VARIANT_C='# Instructions for AI Agent
|
|
149
|
+
|
|
150
|
+
When asked to build a project:
|
|
151
|
+
- Start by reading any PRD or requirements files
|
|
152
|
+
- Use task(agent="planner") to plan the implementation
|
|
153
|
+
- Create files one at a time with write_file
|
|
154
|
+
- Use absolute imports (from pkg.mod import X, not from .mod import X)
|
|
155
|
+
- Create __init__.py and __main__.py for packages
|
|
156
|
+
- Test with python3 -m package_name after building'
|
|
157
|
+
|
|
158
|
+
VARIANT_D='# Build Rules
|
|
159
|
+
|
|
160
|
+
1. Read requirements (PRD.md)
|
|
161
|
+
2. Plan with task(agent="planner")
|
|
162
|
+
3. Explore existing code with task(agent="explore")
|
|
163
|
+
4. Create files with write_file
|
|
164
|
+
5. Use absolute imports only
|
|
165
|
+
6. Always create __init__.py and __main__.py
|
|
166
|
+
7. Test with python3 -m package_name
|
|
167
|
+
8. Fix errors with search_replace'
|
|
168
|
+
|
|
169
|
+
VARIANT_E='# Project Configuration
|
|
170
|
+
|
|
171
|
+
## Agent Workflow
|
|
172
|
+
- For new projects: task(agent="planner") → write_file → bash test
|
|
173
|
+
- For existing projects: task(agent="explore") → read_file → search_replace
|
|
174
|
+
- For reviews: task(agent="explore") → invoke_skill(skill_name="review")
|
|
175
|
+
|
|
176
|
+
## Package Rules
|
|
177
|
+
- Absolute imports: from package.module import X
|
|
178
|
+
- Always: __init__.py + __main__.py
|
|
179
|
+
- Test: python3 -m package_name
|
|
180
|
+
- Never: from .module import X'
|
|
181
|
+
|
|
182
|
+
# ============================================================================
|
|
183
|
+
# Main Loop
|
|
184
|
+
# ============================================================================
|
|
185
|
+
|
|
186
|
+
log "Starting overnight AGENTS.md test (max $MAX_HOURS hours)"
|
|
187
|
+
log "Variants: A B C D E"
|
|
188
|
+
|
|
189
|
+
PASS=0
|
|
190
|
+
FAIL=0
|
|
191
|
+
ROUND=0
|
|
192
|
+
|
|
193
|
+
while true; do
|
|
194
|
+
check_time
|
|
195
|
+
ROUND=$((ROUND + 1))
|
|
196
|
+
log ""
|
|
197
|
+
log "========== ROUND $ROUND =========="
|
|
198
|
+
|
|
199
|
+
for variant in A B C D E; do
|
|
200
|
+
check_time
|
|
201
|
+
eval "content=\$VARIANT_$variant"
|
|
202
|
+
if run_test "variant_$variant" "$content"; then
|
|
203
|
+
PASS=$((PASS + 1))
|
|
204
|
+
else
|
|
205
|
+
FAIL=$((FAIL + 1))
|
|
206
|
+
fi
|
|
207
|
+
done
|
|
208
|
+
|
|
209
|
+
TOTAL=$((PASS + FAIL))
|
|
210
|
+
PASS_RATE=$((PASS * 100 / TOTAL))
|
|
211
|
+
log "Round $ROUND: $PASS/$TOTAL pass ($PASS_RATE%)"
|
|
212
|
+
|
|
213
|
+
# Send Telegram update every 5 rounds
|
|
214
|
+
if [ $((ROUND % 5)) -eq 0 ]; then
|
|
215
|
+
$PYTHON "$DRYDOCK/scripts/notify_release.py" "test-r$ROUND" "AGENTS.md test round $ROUND: $PASS/$TOTAL pass ($PASS_RATE%). Best variant TBD."
|
|
216
|
+
fi
|
|
217
|
+
|
|
218
|
+
sleep 30
|
|
219
|
+
done
|
|
@@ -408,8 +408,8 @@ class TestCircuitBreaker:
|
|
|
408
408
|
|
|
409
409
|
assert al._circuit_breaker_check(tc) is None
|
|
410
410
|
|
|
411
|
-
def
|
|
412
|
-
"""
|
|
411
|
+
def test_circuit_breaker_disabled_for_failed_commands(self):
|
|
412
|
+
"""Circuit breaker is disabled — even failed commands are not blocked."""
|
|
413
413
|
from drydock.core.agent_loop import AgentLoop
|
|
414
414
|
from drydock.core.types import MessageList
|
|
415
415
|
from types import SimpleNamespace
|
|
@@ -426,12 +426,11 @@ class TestCircuitBreaker:
|
|
|
426
426
|
assert al._circuit_breaker_check(tc) is None
|
|
427
427
|
al._circuit_breaker_record(tc, "FAILED: command not found")
|
|
428
428
|
|
|
429
|
-
|
|
430
|
-
assert
|
|
431
|
-
assert "failed" in result
|
|
429
|
+
# CB is disabled — always returns None
|
|
430
|
+
assert al._circuit_breaker_check(tc) is None
|
|
432
431
|
|
|
433
|
-
def
|
|
434
|
-
"""
|
|
432
|
+
def test_circuit_breaker_disabled_for_all_args(self):
|
|
433
|
+
"""Circuit breaker is disabled — no arguments are ever blocked."""
|
|
435
434
|
from drydock.core.agent_loop import AgentLoop
|
|
436
435
|
from drydock.core.types import MessageList
|
|
437
436
|
from types import SimpleNamespace
|
|
@@ -445,7 +444,8 @@ class TestCircuitBreaker:
|
|
|
445
444
|
|
|
446
445
|
for _ in range(3):
|
|
447
446
|
al._circuit_breaker_record(tc1, "FAILED: command not found")
|
|
448
|
-
|
|
447
|
+
# CB is disabled — both return None
|
|
448
|
+
assert al._circuit_breaker_check(tc1) is None
|
|
449
449
|
assert al._circuit_breaker_check(tc2) is None
|
|
450
450
|
|
|
451
451
|
|
|
@@ -55,7 +55,7 @@ def _add_tool_call(al: AgentLoop, tool_name: str, arguments: str = "{}") -> None
|
|
|
55
55
|
# ============================================================================
|
|
56
56
|
|
|
57
57
|
class TestCircuitBreaker:
|
|
58
|
-
"""Circuit breaker
|
|
58
|
+
"""Circuit breaker is fully disabled — always returns None."""
|
|
59
59
|
|
|
60
60
|
def test_first_call_allowed(self):
|
|
61
61
|
al = _make_agent()
|
|
@@ -68,18 +68,16 @@ class TestCircuitBreaker:
|
|
|
68
68
|
al._circuit_breaker_record(tc, "file1.py\nfile2.py")
|
|
69
69
|
assert al._circuit_breaker_check(tc) is None
|
|
70
70
|
|
|
71
|
-
def
|
|
72
|
-
"""
|
|
71
|
+
def test_disabled_for_failed_after_3(self):
|
|
72
|
+
"""CB disabled — failed commands are NOT blocked even after 3 repeats."""
|
|
73
73
|
al = _make_agent()
|
|
74
74
|
tc = SimpleNamespace(tool_name="bash", args_dict={"command":"bad_cmd"})
|
|
75
75
|
for _ in range(3):
|
|
76
76
|
al._circuit_breaker_record(tc, "FAILED: command not found")
|
|
77
|
-
|
|
78
|
-
assert result is not None
|
|
79
|
-
assert "failed" in result
|
|
77
|
+
assert al._circuit_breaker_check(tc) is None
|
|
80
78
|
|
|
81
79
|
def test_failed_2_not_blocked(self):
|
|
82
|
-
"""Failed commands with only 2 repeats are not blocked
|
|
80
|
+
"""Failed commands with only 2 repeats are not blocked."""
|
|
83
81
|
al = _make_agent()
|
|
84
82
|
tc = SimpleNamespace(tool_name="bash", args_dict={"command":"bad_cmd"})
|
|
85
83
|
al._circuit_breaker_record(tc, "FAILED: command not found")
|
|
@@ -102,39 +100,40 @@ class TestCircuitBreaker:
|
|
|
102
100
|
al._circuit_breaker_record(tc, "match.py:10:foo")
|
|
103
101
|
assert al._circuit_breaker_check(tc) is None
|
|
104
102
|
|
|
105
|
-
def
|
|
103
|
+
def test_disabled_returns_none_even_for_failed(self):
|
|
104
|
+
"""CB disabled — returns None even for commands that would have been blocked."""
|
|
106
105
|
al = _make_agent()
|
|
107
106
|
tc = SimpleNamespace(tool_name="bash", args_dict={"command":"python3 run.py"})
|
|
108
107
|
for _ in range(3):
|
|
109
108
|
al._circuit_breaker_record(tc, "FAILED: module not found")
|
|
110
|
-
|
|
111
|
-
assert result is not None
|
|
112
|
-
assert "DIFFERENT" in result or "different" in result
|
|
109
|
+
assert al._circuit_breaker_check(tc) is None
|
|
113
110
|
|
|
114
|
-
def
|
|
111
|
+
def test_disabled_returns_none_for_repeated_failures(self):
|
|
112
|
+
"""CB disabled — returns None regardless of failure count."""
|
|
115
113
|
al = _make_agent()
|
|
116
114
|
tc = SimpleNamespace(tool_name="bash", args_dict={"command":"python3 run.py"})
|
|
117
115
|
for _ in range(3):
|
|
118
116
|
al._circuit_breaker_record(tc, "FAILED: error")
|
|
119
|
-
|
|
120
|
-
assert "3" in result
|
|
117
|
+
assert al._circuit_breaker_check(tc) is None
|
|
121
118
|
|
|
122
|
-
def
|
|
119
|
+
def test_disabled_for_all_args(self):
|
|
120
|
+
"""CB disabled — no args are blocked, even after repeated failures."""
|
|
123
121
|
al = _make_agent()
|
|
124
122
|
tc1 = SimpleNamespace(tool_name="bash", args_dict={"command":"bad_cmd"})
|
|
125
123
|
tc2 = SimpleNamespace(tool_name="bash", args_dict={"command":"ls -la"})
|
|
126
124
|
for _ in range(3):
|
|
127
125
|
al._circuit_breaker_record(tc1, "FAILED: not found")
|
|
128
|
-
assert al._circuit_breaker_check(tc1) is
|
|
129
|
-
assert al._circuit_breaker_check(tc2) is None
|
|
126
|
+
assert al._circuit_breaker_check(tc1) is None
|
|
127
|
+
assert al._circuit_breaker_check(tc2) is None
|
|
130
128
|
|
|
131
|
-
def
|
|
129
|
+
def test_disabled_for_all_tools(self):
|
|
130
|
+
"""CB disabled — no tools are blocked, even after repeated failures."""
|
|
132
131
|
al = _make_agent()
|
|
133
132
|
tc1 = SimpleNamespace(tool_name="bash", args_dict={"command":"bad_cmd"})
|
|
134
133
|
tc2 = SimpleNamespace(tool_name="grep", args_dict={"pattern":"foo"})
|
|
135
134
|
for _ in range(3):
|
|
136
135
|
al._circuit_breaker_record(tc1, "FAILED: not found")
|
|
137
|
-
assert al._circuit_breaker_check(tc1) is
|
|
136
|
+
assert al._circuit_breaker_check(tc1) is None
|
|
138
137
|
assert al._circuit_breaker_check(tc2) is None
|
|
139
138
|
|
|
140
139
|
def test_failed_then_success_not_blocked(self):
|
|
@@ -143,7 +142,6 @@ class TestCircuitBreaker:
|
|
|
143
142
|
tc = SimpleNamespace(tool_name="bash", args_dict={"command":"python3 run.py"})
|
|
144
143
|
al._circuit_breaker_record(tc, "FAILED: error")
|
|
145
144
|
al._circuit_breaker_record(tc, "FAILED: error")
|
|
146
|
-
# Now it succeeds — last_result no longer starts with FAILED:
|
|
147
145
|
al._circuit_breaker_record(tc, "output ok")
|
|
148
146
|
assert al._circuit_breaker_check(tc) is None
|
|
149
147
|
|
|
@@ -62,8 +62,8 @@ class TestCondaEnv:
|
|
|
62
62
|
# ============================================================================
|
|
63
63
|
|
|
64
64
|
class TestCircuitBreakerEnforcement:
|
|
65
|
-
def
|
|
66
|
-
"""
|
|
65
|
+
def test_circuit_breaker_disabled(self):
|
|
66
|
+
"""Circuit breaker is disabled — even failed commands are never blocked."""
|
|
67
67
|
from drydock.core.agent_loop import AgentLoop
|
|
68
68
|
from drydock.core.types import MessageList
|
|
69
69
|
|
|
@@ -75,13 +75,11 @@ class TestCircuitBreakerEnforcement:
|
|
|
75
75
|
for _ in range(3):
|
|
76
76
|
al._circuit_breaker_record(tc, "FAILED: command not found")
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
assert
|
|
80
|
-
assert "failed" in result
|
|
81
|
-
assert "DIFFERENT" in result or "different" in result
|
|
78
|
+
# CB is disabled — always returns None
|
|
79
|
+
assert al._circuit_breaker_check(tc) is None
|
|
82
80
|
|
|
83
81
|
def test_circuit_breaker_resets_for_new_conversation(self):
|
|
84
|
-
"""Circuit breaker
|
|
82
|
+
"""Circuit breaker history is clearable between conversations."""
|
|
85
83
|
from drydock.core.agent_loop import AgentLoop
|
|
86
84
|
from drydock.core.types import MessageList
|
|
87
85
|
|
|
@@ -92,11 +90,12 @@ class TestCircuitBreakerEnforcement:
|
|
|
92
90
|
tc = SimpleNamespace(tool_name="bash", args_dict={"command": "bad_cmd"})
|
|
93
91
|
for _ in range(3):
|
|
94
92
|
al._circuit_breaker_record(tc, "FAILED: command not found")
|
|
95
|
-
|
|
93
|
+
# CB is disabled — returns None even before clearing
|
|
94
|
+
assert al._circuit_breaker_check(tc) is None
|
|
96
95
|
|
|
97
96
|
# Simulate new conversation — history should be clearable
|
|
98
97
|
al._tool_call_history.clear()
|
|
99
|
-
assert al._circuit_breaker_check(tc) is None #
|
|
98
|
+
assert al._circuit_breaker_check(tc) is None # Still None
|
|
100
99
|
|
|
101
100
|
|
|
102
101
|
# ============================================================================
|
|
@@ -119,7 +118,7 @@ class TestUnderstoodBug:
|
|
|
119
118
|
|
|
120
119
|
class TestCircuitBreakerSensitivity:
|
|
121
120
|
def test_successful_commands_never_blocked(self):
|
|
122
|
-
"""Successful commands are never blocked
|
|
121
|
+
"""Successful commands are never blocked."""
|
|
123
122
|
from drydock.core.agent_loop import AgentLoop
|
|
124
123
|
from drydock.core.types import MessageList
|
|
125
124
|
|
|
@@ -132,8 +131,8 @@ class TestCircuitBreakerSensitivity:
|
|
|
132
131
|
al._circuit_breaker_record(tc, "clean")
|
|
133
132
|
assert al._circuit_breaker_check(tc) is None # Never blocked
|
|
134
133
|
|
|
135
|
-
def
|
|
136
|
-
"""
|
|
134
|
+
def test_failed_commands_not_blocked_cb_disabled(self):
|
|
135
|
+
"""CB disabled — failed commands are NOT blocked even after 3 repeats."""
|
|
137
136
|
from drydock.core.agent_loop import AgentLoop
|
|
138
137
|
from drydock.core.types import MessageList
|
|
139
138
|
|
|
@@ -144,7 +143,7 @@ class TestCircuitBreakerSensitivity:
|
|
|
144
143
|
tc = SimpleNamespace(tool_name="bash", args_dict={"command": "git status"})
|
|
145
144
|
for _ in range(3):
|
|
146
145
|
al._circuit_breaker_record(tc, "FAILED: not a git repo")
|
|
147
|
-
assert al._circuit_breaker_check(tc) is
|
|
146
|
+
assert al._circuit_breaker_check(tc) is None # CB disabled
|
|
148
147
|
|
|
149
148
|
|
|
150
149
|
# ============================================================================
|
|
@@ -207,8 +206,8 @@ class TestConsultantConfig:
|
|
|
207
206
|
# ============================================================================
|
|
208
207
|
|
|
209
208
|
class TestAutoConsult:
|
|
210
|
-
def
|
|
211
|
-
"""
|
|
209
|
+
def test_circuit_breaker_disabled_returns_none(self):
|
|
210
|
+
"""CB is disabled — returns None even for repeatedly failed commands."""
|
|
212
211
|
from drydock.core.agent_loop import AgentLoop
|
|
213
212
|
from drydock.core.types import MessageList
|
|
214
213
|
|
|
@@ -219,9 +218,7 @@ class TestAutoConsult:
|
|
|
219
218
|
tc = SimpleNamespace(tool_name="bash", args_dict={"command": "bad_cmd"})
|
|
220
219
|
for _ in range(3):
|
|
221
220
|
al._circuit_breaker_record(tc, "FAILED: command not found")
|
|
222
|
-
|
|
223
|
-
assert result is not None, "Circuit breaker should have fired for failed command"
|
|
224
|
-
assert "different" in result.lower()
|
|
221
|
+
assert al._circuit_breaker_check(tc) is None
|
|
225
222
|
|
|
226
223
|
|
|
227
224
|
# ============================================================================
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|