drydock-cli 2.7.6__tar.gz → 2.7.22__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.7.22/.auto_release.lock +1 -0
- drydock_cli-2.7.22/.claude/scheduled_tasks.lock +1 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/PKG-INFO +1 -1
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/PRD.md +59 -2
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/detectors.py +28 -10
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/detectors_proposed.py +9 -2
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/agent_loop.py +62 -9
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/llm/format.py +185 -4
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/bash.py +65 -8
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/read_file.py +74 -15
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/search_replace.py +246 -27
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/write_file.py +30 -0
- drydock_cli-2.7.22/nohup.out +38138 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/pyproject.toml +1 -1
- drydock_cli-2.7.22/resume.md +183 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/auto_release.sh +26 -6
- drydock_cli-2.7.22/scripts/autonomous_review.sh +97 -0
- drydock_cli-2.7.22/scripts/autonomous_review_prompt.md +101 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/llm_balancer.py +5 -1
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/stress_babysitter.sh +6 -2
- drydock_cli-2.7.22/test/project/dummy +32 -0
- drydock_cli-2.7.22/tests/core/test_circuit_breaker_count_escalation.py +93 -0
- drydock_cli-2.7.22/tests/core/test_circuit_breaker_readonly_threshold.py +93 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_admiral_proposed.py +19 -0
- drydock_cli-2.7.22/tests/test_admiral_struggle_dedup.py +99 -0
- drydock_cli-2.7.22/tests/test_hallucinated_tool_suppression.py +87 -0
- drydock_cli-2.7.22/tests/test_read_file_not_found_listing.py +70 -0
- drydock_cli-2.7.22/tests/test_truncated_arg_path_hint.py +124 -0
- drydock_cli-2.7.22/tests/test_truncated_search_replace_escalation.py +76 -0
- drydock_cli-2.7.22/tests/test_truncated_write_escalation.py +104 -0
- drydock_cli-2.7.22/tests/test_write_file_missing_path.py +75 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/tools/test_bash.py +42 -10
- drydock_cli-2.7.22/tests/tools/test_read_file_dedup_reembed.py +136 -0
- drydock_cli-2.7.22/tests/tools/test_read_file_directory.py +65 -0
- drydock_cli-2.7.22/tests/tools/test_read_file_limit_truncation.py +76 -0
- drydock_cli-2.7.22/tests/tools/test_search_replace_dir_path.py +114 -0
- drydock_cli-2.7.22/tests/tools/test_search_replace_empty_content.py +90 -0
- drydock_cli-2.7.22/tests/tools/test_search_replace_hard_stop.py +136 -0
- drydock_cli-2.7.22/tests/tools/test_search_replace_no_op_loop_breaker.py +139 -0
- drydock_cli-2.7.22/tests/tools/test_search_replace_refused_loop_breaker.py +144 -0
- drydock_cli-2.7.22/tests/tools/test_write_file_dedup_missing_imports.py +103 -0
- drydock_cli-2.7.22/tests/tools/test_write_file_missing_path_hint.py +78 -0
- drydock_cli-2.7.22/trip_log.md +772 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/uv.lock +1 -1
- drydock_cli-2.7.6/.auto_release.lock +0 -1
- drydock_cli-2.7.6/.claude/scheduled_tasks.lock +0 -1
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.github/CODEOWNERS +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.github/workflows/build-and-upload.yml +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.github/workflows/ci.yml +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.github/workflows/issue-labeler.yml +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.github/workflows/release.yml +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.gitignore +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.pre-commit-config.yaml +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.python-version +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.typos.toml +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.vscode/extensions.json +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.vscode/launch.json +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/.vscode/settings.json +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/AGENTS.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/Admiral.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/BASELINE_412.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/CHANGELOG.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/CLAUDE.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/CONTRIBUTING.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/DEPLOYMENT.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/Drydock_rebrand.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/LICENSE +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/MODEL_SHORTCOMINGS.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/NOTICE +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/OVERNIGHT_PROGRESS.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/OVERNIGHT_REPORT_2026_04_13.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/README.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/action.yml +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/README.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results1.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results13.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results14.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results15.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results16.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results17.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results18.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results19.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results2.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results20.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results3.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results4.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results5.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results6.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results7.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results8.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results9.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/baseline_history/results_evolved_v1.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/distribution/zed/LICENSE +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/distribution/zed/extension.toml +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/distribution/zed/icons/mistral_vibe.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/docs/README.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/docs/acp-setup.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/docs/proxy-setup.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/acp/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/acp/acp_agent_loop.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/acp/acp_logger.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/acp/entrypoint.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/acp/tools/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/acp/tools/base.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/acp/tools/builtins/bash.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/acp/tools/builtins/read_file.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/acp/tools/builtins/search_replace.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/acp/tools/builtins/todo.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/acp/tools/builtins/write_file.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/acp/tools/session_update.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/acp/utils.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/history.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/interventions.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/llm_analyzer.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/metrics.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/opus_escalator.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/persistence.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/policy.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/proposer.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/stager.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/task_classifier.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/tuning.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/validator.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/admiral/worker.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/autocompletion/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/autocompletion/base.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/autocompletion/path_completion.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/autocompletion/slash_command.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/cli.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/clipboard.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/commands.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/entrypoint.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/history_manager.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/terminal_setup.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/app.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/app.tcss +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/external_editor.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/checkpoint_picker.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/compact.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/loading.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/messages.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/tools.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/windowing/history.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/textual_ui/windowing/state.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/update_notifier/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/update_notifier/update.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/cli/update_notifier/whats_new.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/agents/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/agents/manager.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/agents/models.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/auth/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/auth/crypto.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/auth/github.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/autocompletion/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/autocompletion/completers.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/autocompletion/file_indexer/store.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/autocompletion/fuzzy.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/autocompletion/path_prompt.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/build_orchestrator.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/checkpoint.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/config/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/config/_settings.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/config/doctor.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/config/harness_files/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/config/harness_files/_harness_manager.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/config/harness_files/_paths.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/consultant.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/drydock_states.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/hooks.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/llm/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/llm/backend/anthropic.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/llm/backend/base.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/llm/backend/factory.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/llm/backend/generic.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/llm/backend/mistral.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/llm/backend/vertex.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/llm/exceptions.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/llm/message_utils.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/llm/types.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/logger.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/middleware.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/output_formatters.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/paths/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/paths/_drydock_home.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/paths/_local_config_walk.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/paths/conventions.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/plan_session.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/plugins.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/programmatic.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/prompts/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/prompts/builder.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/prompts/cli.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/prompts/compact.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/prompts/dangerous_directory.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/prompts/diagnostic.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/prompts/explore.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/prompts/gemma4.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/prompts/planner.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/prompts/project_context.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/prompts/tests.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/proxy_setup.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/session/agent_memory.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/session/checkpoints.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/session/session_loader.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/session/session_logger.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/session/session_migration.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/session/state_file.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/session_checker.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/skills/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/skills/manager.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/skills/models.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/skills/parser.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/slug.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/system_prompt.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/telemetry/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/telemetry/send.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/teleport/errors.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/teleport/git.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/teleport/nuage.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/teleport/teleport.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/teleport/types.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/base.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/_task_manager.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/ask_user_question.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/cron.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/glob_tool.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/grep.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/invoke_skill.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/lsp.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/mcp_resources.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/notebook_edit.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/powershell.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/bash.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/cron.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/glob.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/grep.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/invoke_skill.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/lsp.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/mcp_resources.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/powershell.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/task.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/todo.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/tool_search.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/worktree.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/task.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/todo.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/tool_search.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/webfetch.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/websearch.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/builtins/worktree.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/injection_guard.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/manager.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/mcp/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/mcp/registry.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/mcp/tools.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/mcp_sampling.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/ui.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/tools/utils.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/trusted_folders.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/types.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/core/utils.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/setup/onboarding/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/setup/onboarding/base.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/setup/onboarding/onboarding.tcss +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/setup/onboarding/screens/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/setup/onboarding/screens/api_key.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/setup/onboarding/screens/choice.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/setup/onboarding/screens/local_model.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/setup/onboarding/screens/welcome.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/api-design/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/audit-tests/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/batch/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/commit-code/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/context-summary/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/create-presentation/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/deep-research/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/deploy/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/diff-review/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/doc-gen/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/explain-code/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/explore-code/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/fix-issue/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/git-ops/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/init-project/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/investigate/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/loop/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/migrate/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/perf-analyze/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/plan-impl/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/pr-review/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/refactor/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/regex-help/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/review/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/security-review/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/ship/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/simplify/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/strong-tests/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/skills/test-verify/SKILL.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock/whats_new.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock-acp.spec +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/drydock_terms.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/flake.lock +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/flake.nix +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/research/README.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/research/config_base.toml +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/research/config_best.toml +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/research/domain_spec.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/research/experimenter.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/research/kernel.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/research/mini_prd.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/research/mini_prompts.txt +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/research/proposer.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/research/results.tsv +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/README.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/admiral_probe.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/audit_sampler.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/auto_generate_tests.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/auto_test_loop.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/backup.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/bump_version.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/comprehensive_loop.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/deploy_to_github.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/discover_cli_tools.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/evolve_tests.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/gen_2000_prompts.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/install.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/mega_loop.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/meta_ralph_loop.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/monitor_swebench.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/monitor_test_battery.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/notify_release.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/oss_task_harness.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/overnight_agents_test.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/poll_issues.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/port_task.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/prepare_release.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/publish_to_pypi.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/ralph_loop.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/research_babysitter.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/session_loop_audit.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/shakedown.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/shakedown_interactive.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/shakedown_regression.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/shakedown_suite.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/shakedown_variance.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/stress_prompts_50.txt +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/stress_prompts_realuser.txt +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/stress_prompts_tool_agent.txt +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/stress_prompts_tool_agent_2000.txt +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/stress_shakedown.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/stress_telegram_status.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/stress_watcher.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/telegram_bot.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/test_bank.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/test_full.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/test_smoke.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/test_tui_path.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/tui_test.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/scripts/vllm_failover.sh +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/conftest.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_acp.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_agent_thought.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_bash.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_compact_session_updates.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_content.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_initialize.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_list_sessions.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_load_session.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_multi_session.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_new_session.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_proxy_setup_acp.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_read_file.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_search_replace.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_set_config_option.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_set_mode.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_set_model.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_tool_call_session_update.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_utils.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/acp/test_write_file.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/autocompletion/test_file_indexer.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/autocompletion/test_fuzzy.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/autocompletion/test_path_completer_recursive.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/autocompletion/test_path_completion_controller.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/autocompletion/test_slash_command_controller.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/backend/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/backend/data/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/backend/data/fireworks.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/backend/data/mistral.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/backend/test_anthropic_adapter.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/backend/test_backend.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/backend/test_generic_adapter_sanitize.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/backend/test_reasoning_adapter.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/test_bell_notifications.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/test_braille_renderer.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/test_clipboard.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/test_commands.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/test_copy_shortcuts.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/test_external_editor.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/test_no_markup_static.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/test_question_app.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/test_spinner.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/test_switching_mode.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/test_ui_clipboard_notifications.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/test_ui_session_resume.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/test_ui_skill_dispatch.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/cli/textual_ui/test_session_picker.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/conftest.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_agents.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_auth_crypto.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_auth_github.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_config_load_dotenv.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_config_paths.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_config_resolution.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_file_logging.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_plan_session.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_proxy_setup.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_slug.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_telemetry_send.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_teleport_git.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_teleport_nuage.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_teleport_service.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_trusted_folders.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/core/test_utils.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/e2e/common.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/e2e/conftest.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/e2e/mock_server.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/e2e/test_cli_tui_onboarding.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/e2e/test_cli_tui_streaming.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/fixtures/doc_qa_system_prd.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/mock/__init__.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/mock/mock_backend_factory.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/mock/mock_entrypoint.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/mock/utils.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/onboarding/test_run_onboarding.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/onboarding/test_ui_onboarding.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/session/test_session_loader.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/session/test_session_logger.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/session/test_session_migration.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/skills/conftest.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/skills/test_manager.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/skills/test_models.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/skills/test_parser.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/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.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/base_snapshot_test_app.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/conftest.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/snap_compare.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/stubs/fake_backend.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/stubs/fake_client.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/stubs/fake_tool.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_admiral.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_admiral_phase3.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_agent_auto_compact.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_agent_backend.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_agent_observer_streaming.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_agent_stats.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_agent_tasks.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_agent_tool_call.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_agents.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_bank_build.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_bank_debug.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_bank_multiagent.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_bank_prd.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_bank_prd_extended.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_bank_tools.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_bank_update.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_build_projects.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_checkpoint.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_cli_programmatic_preload.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_current_bugs.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_drydock_regression.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_drydock_tasks.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_fake_tool_call_paren_syntax.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_full_regression.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_history_manager.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_integration.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_issue_fixes.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_loop_detection.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_message_id.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_message_merging.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_middleware.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_multi_agent.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_real_failures.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_real_issues.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_real_workflow.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_reasoning_content.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_smoke.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_system_prompt.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_tagged_text.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_tool_args.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_truncate_args_valid_json.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_ui_external_editor.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_ui_input_history.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_user_issues.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_wall_of_text_rescue.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/test_workloads.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/testbank_helpers.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/tools/test_ask_user_question.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/tools/test_exit_plan_mode.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/tools/test_grep.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/tools/test_invoke_context.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/tools/test_manager_gemma_derived_models.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/tools/test_manager_get_tool_config.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/tools/test_mcp.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/tools/test_mcp_sampling.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/tools/test_search_replace_append_fallback.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/tools/test_task.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/tools/test_ui_bash_execution.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/tools/test_webfetch.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/tools/test_websearch.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/update_notifier/test_do_update.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/update_notifier/test_github_update_gateway.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/update_notifier/test_ui_update_notification.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/update_notifier/test_update_use_case.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/tests/update_notifier/test_whats_new.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/worked_examples/README.md +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/worked_examples/cli_subcommand_dispatch.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/worked_examples/lookup.json +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/worked_examples/sql_parser.py +0 -0
- {drydock_cli-2.7.6 → drydock_cli-2.7.22}/worked_examples/tree_walking_interpreter.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
522842
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"sessionId":"facd51cc-fa47-4911-afc8-14485ae9caf3","pid":711220,"acquiredAt":1775966390914}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: drydock-cli
|
|
3
|
-
Version: 2.7.
|
|
3
|
+
Version: 2.7.22
|
|
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
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# DryDock — Local CLI Coding Agent
|
|
2
2
|
|
|
3
3
|
**Repository:** https://github.com/fbobe321/drydock
|
|
4
|
-
**PyPI:** https://pypi.org/project/drydock-cli/ (v2.7.
|
|
4
|
+
**PyPI:** https://pypi.org/project/drydock-cli/ (v2.7.6)
|
|
5
5
|
**License:** Apache 2.0 (fork of [mistralai/mistral-vibe](https://github.com/mistralai/mistral-vibe))
|
|
6
6
|
|
|
7
7
|
## Vision
|
|
@@ -398,6 +398,54 @@ order:
|
|
|
398
398
|
Auto-created if none exist. AGENTS.md is essential for devstral
|
|
399
399
|
(it loops without one) but Gemma 4 works without it.
|
|
400
400
|
|
|
401
|
+
## Recent fixes (April 25, 2026)
|
|
402
|
+
|
|
403
|
+
### v2.7.6 (April 25, 09:18 CDT) — truncation JSON-validity fix
|
|
404
|
+
**Root cause of the recurring vLLM 400 spiral.** Live capture from a
|
|
405
|
+
2000-prompt stress run pinpointed it: `_truncate_old_tool_results` was
|
|
406
|
+
shrinking old assistant `tool_calls.function.arguments` by appending
|
|
407
|
+
`"\n[…truncated N bytes…]"` directly into the JSON-string field. vLLM's
|
|
408
|
+
tool-call parser re-parses arguments as JSON; raw `\n` (0x0A) inside a
|
|
409
|
+
JSON string is invalid → `JSONDecodeError: Invalid control character
|
|
410
|
+
at: line 1 column 401` → HTTP 400 → drydock's "6 consecutive errors"
|
|
411
|
+
banner → harness `/clear` → prompt lost. The pattern repeated every
|
|
412
|
+
~30 prompts as truncation kicked in, costing dozens of prompts per
|
|
413
|
+
batch.
|
|
414
|
+
|
|
415
|
+
Fix in `agent_loop.py::_truncate_old_tool_results`: rebuild the
|
|
416
|
+
truncated arguments as a small VALID JSON stub (`{"_truncated": true,
|
|
417
|
+
"_original_bytes": N, "<id_field>": ...}`) preserving the most-useful
|
|
418
|
+
identifying field (path / file_path / command / cmd / url / file)
|
|
419
|
+
from the parsed original. 5 regression tests in
|
|
420
|
+
`tests/test_truncate_args_valid_json.py`; 2 of them fail with the
|
|
421
|
+
exact "char 400" error without the fix.
|
|
422
|
+
|
|
423
|
+
**Stress measurement:** before fix, write rate 10% / vLLM 400s
|
|
424
|
+
315 per 30 min. After fix, write rate sustained at ~44% / vLLM 400s
|
|
425
|
+
0 per hour. **4.4× correctness improvement** on the same workload.
|
|
426
|
+
|
|
427
|
+
### v2.7.6 (April 25) — search_replace APPEND fallback
|
|
428
|
+
The 2026-04-25 stress run also exposed a search_replace REFUSED loop:
|
|
429
|
+
Gemma 4 sent a single new function with no SEARCH/REPLACE markers,
|
|
430
|
+
the safety check refused as "would shrink the file by 90%", model
|
|
431
|
+
retried the same broken call, prompts dropped. Model intent in this
|
|
432
|
+
shape is APPEND, not rewrite.
|
|
433
|
+
|
|
434
|
+
Fix in `search_replace.py`: try appending the raw content first; for
|
|
435
|
+
.py files only commit if the combined text still parses cleanly; if
|
|
436
|
+
syntax breaks, return a directive REFUSED that explains the
|
|
437
|
+
EOF-anchored SEARCH/REPLACE pattern. Tests in
|
|
438
|
+
`tests/tools/test_search_replace_append_fallback.py`.
|
|
439
|
+
|
|
440
|
+
### v2.7.5 (April 25, 07:25 CDT) — yesterday's GitHub issue batch
|
|
441
|
+
Auto-release shipped the four fixes from 2026-04-24 plus the PRD
|
|
442
|
+
refresh:
|
|
443
|
+
- #13 control-char JSON sanitization in OpenAIAdapter
|
|
444
|
+
- #11 fake `task(...)` text nuker in format.py
|
|
445
|
+
- #12 wall-rescue at stream end in messages.py
|
|
446
|
+
- #10 navygpt auto-disable in tool manager
|
|
447
|
+
- PRD.md refresh for v2.7.4 (Admiral, Meta-Harness sections)
|
|
448
|
+
|
|
401
449
|
## Recent fixes (April 16–24, 2026)
|
|
402
450
|
|
|
403
451
|
### v2.7.4 + unreleased (April 24) — GitHub issue triage batch
|
|
@@ -749,7 +797,16 @@ Second claude-code pass produced two more wins:
|
|
|
749
797
|
|
|
750
798
|
## Roadmap
|
|
751
799
|
|
|
752
|
-
### Currently in flight (April
|
|
800
|
+
### Currently in flight (April 25, 2026)
|
|
801
|
+
- **2000-prompt stress test** running against v2.7.6 on
|
|
802
|
+
`/data3/drydock_test_projects/403_tool_agent` (PID 3713698, log
|
|
803
|
+
`/tmp/stress_2000_1777119799.log`). At 5+ hours in: 189/1658 prompts
|
|
804
|
+
done, write rate ~44% sustained, vLLM 400s eliminated, SKIPs 8%.
|
|
805
|
+
Babysitter cron will auto-restart on death.
|
|
806
|
+
- **Resume sentinel** at `/data3/drydock/resume.md` — point a fresh
|
|
807
|
+
Claude session at it via `review the resume.md file and continue`.
|
|
808
|
+
|
|
809
|
+
### Carried over from April 24, 2026
|
|
753
810
|
- **GitHub issue triage** — 4 user-reported bugs (#10–#13) fixed this
|
|
754
811
|
week, all with regression tests. Remaining open issues should be
|
|
755
812
|
picked up on sight; `feedback_proactive_github_issues.md` codifies
|
|
@@ -80,18 +80,36 @@ def detect_struggle(messages: Sequence[LLMMessage], threshold: int = 20) -> Find
|
|
|
80
80
|
calls_since_write += 1
|
|
81
81
|
if calls_since_write < threshold:
|
|
82
82
|
return None
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
83
|
+
# Stable code (no count) so DEDUP_WINDOW_SEC suppresses repeated firings.
|
|
84
|
+
# Previously included the count, which caused 33 identical interventions
|
|
85
|
+
# in a single session (each with a unique key that bypassed dedup).
|
|
86
|
+
code = f"struggle:{last_write_tool or 'none'}"
|
|
87
|
+
if calls_since_write >= 30:
|
|
88
|
+
if last_write_tool is None:
|
|
89
|
+
directive = (
|
|
90
|
+
f"Admiral: you have made {calls_since_write} tool calls without "
|
|
91
|
+
f"writing a single file. You have enough context. STOP exploring "
|
|
92
|
+
f"and start writing code NOW. Call `write_file` to create your "
|
|
93
|
+
f"first file immediately."
|
|
94
|
+
)
|
|
95
|
+
else:
|
|
96
|
+
directive = (
|
|
97
|
+
f"Admiral: you have made {calls_since_write} tool calls without "
|
|
98
|
+
f"writing any file — search_replace is clearly not finding the text. "
|
|
99
|
+
f"STOP retrying. Call `write_file` with `overwrite=True` to rewrite "
|
|
100
|
+
f"the target file from scratch right now."
|
|
101
|
+
)
|
|
102
|
+
else:
|
|
103
|
+
hint = (
|
|
104
|
+
"Either (a) you already have enough context — commit to a plan and "
|
|
105
|
+
"start writing code now, or (b) you're genuinely stuck — stop and "
|
|
106
|
+
"report what's blocking you to the user."
|
|
107
|
+
)
|
|
108
|
+
directive = (
|
|
91
109
|
f"Admiral: you have made {calls_since_write} tool calls without "
|
|
92
110
|
f"writing or editing any file. {hint}"
|
|
93
|
-
)
|
|
94
|
-
)
|
|
111
|
+
)
|
|
112
|
+
return Finding(code=code, directive=directive)
|
|
95
113
|
|
|
96
114
|
|
|
97
115
|
def run_all(messages: Sequence[LLMMessage]) -> list[Finding]:
|
|
@@ -43,11 +43,18 @@ def _tool_result_errored(m: LLMMessage) -> bool:
|
|
|
43
43
|
"""Heuristic: does this tool-role message look like a failure?
|
|
44
44
|
|
|
45
45
|
Conservative — we only want high-precision firing on actual errors.
|
|
46
|
-
Scanned the first
|
|
46
|
+
Scanned the first 200 chars of the result content (tightened from 800
|
|
47
|
+
to avoid false positives when matched file content contains words like
|
|
48
|
+
"error" or "failed" — grep results starting with "matches:" are always
|
|
49
|
+
successful).
|
|
47
50
|
"""
|
|
48
51
|
if m.role is not Role.tool:
|
|
49
52
|
return False
|
|
50
|
-
|
|
53
|
+
raw = str(getattr(m, "content", "") or "")
|
|
54
|
+
# Successful grep results start with "matches:" — never treat as error.
|
|
55
|
+
if raw.lstrip().startswith("matches:"):
|
|
56
|
+
return False
|
|
57
|
+
content = raw[:200].lower()
|
|
51
58
|
return any(marker in content for marker in _TOOL_ERROR_MARKERS)
|
|
52
59
|
|
|
53
60
|
|
|
@@ -1131,10 +1131,12 @@ class AgentLoop:
|
|
|
1131
1131
|
token-level sampling bumps don't help when the model picks
|
|
1132
1132
|
the SAME serialized args every time.
|
|
1133
1133
|
|
|
1134
|
-
|
|
1135
|
-
|
|
1134
|
+
Thresholds tuned for 45-prompt session windows (stress sessions
|
|
1135
|
+
reset every 45 prompts — a threshold of 12 never fires in practice
|
|
1136
|
+
because the model loops 4-8 times then moves on; admiral advisories
|
|
1137
|
+
fire at 3 but the model ignores them):
|
|
1136
1138
|
search_replace, write_file, bash: after 8 identical calls
|
|
1137
|
-
read_file, grep, glob, ls: after
|
|
1139
|
+
read_file, grep, glob, ls: after 5 identical calls
|
|
1138
1140
|
"""
|
|
1139
1141
|
args_str = json.dumps(tool_call.args_dict, sort_keys=True, default=str)
|
|
1140
1142
|
sig = hashlib.sha256(
|
|
@@ -1143,9 +1145,13 @@ class AgentLoop:
|
|
|
1143
1145
|
count, last_result = self._tool_call_history.get(sig, (0, ""))
|
|
1144
1146
|
tool_name = tool_call.tool_name
|
|
1145
1147
|
is_readonly = tool_name in ("grep", "read_file", "glob", "ls")
|
|
1146
|
-
threshold =
|
|
1148
|
+
threshold = 5 if is_readonly else 8
|
|
1147
1149
|
if count < threshold:
|
|
1148
1150
|
return None
|
|
1151
|
+
# Increment so the count escalates on every repeated fire, giving the
|
|
1152
|
+
# model a growing signal that nothing has changed. Preserve last_result
|
|
1153
|
+
# so the message always shows the real bash/tool output, not a prior NOTE.
|
|
1154
|
+
self._tool_call_history[sig] = (count + 1, last_result)
|
|
1149
1155
|
return (
|
|
1150
1156
|
f"NOTE: this exact call to `{tool_name}` has been made "
|
|
1151
1157
|
f"{count} times this session with identical arguments. "
|
|
@@ -1505,9 +1511,23 @@ class AgentLoop:
|
|
|
1505
1511
|
self.stats.tool_calls_failed += 1
|
|
1506
1512
|
self._handle_tool_response(tool_call, error_msg, "failure", decision)
|
|
1507
1513
|
|
|
1514
|
+
def _silence_suppressed_failures(self, suppressed: list) -> None:
|
|
1515
|
+
"""Add tool result messages for hallucinated tools without TUI events.
|
|
1516
|
+
|
|
1517
|
+
Keeps message history well-formed (assistant tool_call → tool result)
|
|
1518
|
+
while hiding the error from the TUI to avoid confusing the user.
|
|
1519
|
+
"""
|
|
1520
|
+
for failed in suppressed:
|
|
1521
|
+
error_msg = f"<{TOOL_ERROR_TAG}>{failed.tool_name}: {failed.error}</{TOOL_ERROR_TAG}>"
|
|
1522
|
+
self.messages.append(
|
|
1523
|
+
self.format_handler.create_failed_tool_response_message(failed, error_msg)
|
|
1524
|
+
)
|
|
1525
|
+
self.stats.tool_calls_failed += 1
|
|
1526
|
+
|
|
1508
1527
|
async def _handle_tool_calls(
|
|
1509
1528
|
self, resolved: ResolvedMessage
|
|
1510
1529
|
) -> AsyncGenerator[ToolCallEvent | ToolResultEvent | ToolStreamEvent | AssistantEvent]:
|
|
1530
|
+
self._silence_suppressed_failures(resolved.suppressed_failures)
|
|
1511
1531
|
async for event in self._emit_failed_tool_events(resolved.failed_calls):
|
|
1512
1532
|
yield event
|
|
1513
1533
|
for tool_call in resolved.tool_calls:
|
|
@@ -1703,10 +1723,10 @@ class AgentLoop:
|
|
|
1703
1723
|
Runs every turn but is a no-op when nothing exceeds the caps.
|
|
1704
1724
|
Truncation is in-place and idempotent.
|
|
1705
1725
|
"""
|
|
1706
|
-
KEEP_RECENT =
|
|
1707
|
-
SOFT_CAP_BYTES =
|
|
1708
|
-
HEAD_BYTES =
|
|
1709
|
-
TAIL_BYTES =
|
|
1726
|
+
KEEP_RECENT = 4 # last N tool messages stay full
|
|
1727
|
+
SOFT_CAP_BYTES = 500 # tool result longer than this gets shrunk
|
|
1728
|
+
HEAD_BYTES = 200 # bytes kept from the head
|
|
1729
|
+
TAIL_BYTES = 60 # bytes kept from the tail
|
|
1710
1730
|
|
|
1711
1731
|
if len(self.messages) < KEEP_RECENT + 4:
|
|
1712
1732
|
return
|
|
@@ -2334,7 +2354,16 @@ class AgentLoop:
|
|
|
2334
2354
|
if replace_last_tool:
|
|
2335
2355
|
msg.content = f"[SYSTEM: {text}]"
|
|
2336
2356
|
else:
|
|
2337
|
-
|
|
2357
|
+
content = msg.content or ""
|
|
2358
|
+
# Cap at 2 accumulated system notes per message; replace the
|
|
2359
|
+
# last one when the limit is exceeded so repeated admiral
|
|
2360
|
+
# interventions don't unboundedly bloat the context.
|
|
2361
|
+
_SYS_PREFIX = "\n\n[SYSTEM: "
|
|
2362
|
+
if content.count(_SYS_PREFIX) >= 2:
|
|
2363
|
+
last_idx = content.rfind(_SYS_PREFIX)
|
|
2364
|
+
msg.content = content[:last_idx] + _SYS_PREFIX + text + "]"
|
|
2365
|
+
else:
|
|
2366
|
+
msg.content = content + _SYS_PREFIX + text + "]"
|
|
2338
2367
|
return
|
|
2339
2368
|
|
|
2340
2369
|
# Second try: append to last user message
|
|
@@ -2370,6 +2399,30 @@ class AgentLoop:
|
|
|
2370
2399
|
if len(recent_sr) >= 2 and recent_sr[0] == recent_sr[1]:
|
|
2371
2400
|
return "WARNING|search_replace"
|
|
2372
2401
|
|
|
2402
|
+
# Early check: write_file with _truncated args twice in a row for the
|
|
2403
|
+
# same path. format.py already embeds the file content in the error,
|
|
2404
|
+
# but Gemma 4 ignores the advisory and retries identically. Mute
|
|
2405
|
+
# write_file for 1 turn so the model must use read_file or
|
|
2406
|
+
# search_replace instead — same pattern as the search_replace check.
|
|
2407
|
+
recent_wf_truncated: list[str] = []
|
|
2408
|
+
for msg in reversed(self.messages[-20:]):
|
|
2409
|
+
if msg.role == Role.assistant and msg.tool_calls:
|
|
2410
|
+
for tc in msg.tool_calls:
|
|
2411
|
+
if tc.function and tc.function.name == "write_file":
|
|
2412
|
+
try:
|
|
2413
|
+
args = json.loads(tc.function.arguments or "{}")
|
|
2414
|
+
if args.get("_truncated"):
|
|
2415
|
+
p = (args.get("file_path") or args.get("path") or "")
|
|
2416
|
+
recent_wf_truncated.append(p)
|
|
2417
|
+
except (json.JSONDecodeError, AttributeError):
|
|
2418
|
+
pass
|
|
2419
|
+
if len(recent_wf_truncated) >= 2:
|
|
2420
|
+
break
|
|
2421
|
+
if (len(recent_wf_truncated) >= 2
|
|
2422
|
+
and recent_wf_truncated[0] == recent_wf_truncated[1]):
|
|
2423
|
+
self._hot_tool_path = ("write_file", recent_wf_truncated[0])
|
|
2424
|
+
return "FORCE_STOP"
|
|
2425
|
+
|
|
2373
2426
|
sigs: list[str] = []
|
|
2374
2427
|
tool_names: list[str] = []
|
|
2375
2428
|
lookback = 0
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import json
|
|
4
4
|
import logging
|
|
5
5
|
import re as _re
|
|
6
|
+
from pathlib import Path
|
|
6
7
|
from typing import TYPE_CHECKING, Any
|
|
7
8
|
|
|
8
9
|
from pydantic import BaseModel, ConfigDict, Field, ValidationError
|
|
@@ -165,9 +166,17 @@ class ResolvedMessage(BaseModel):
|
|
|
165
166
|
model_config = ConfigDict(frozen=True)
|
|
166
167
|
tool_calls: list[ResolvedToolCall]
|
|
167
168
|
failed_calls: list[FailedToolCall] = Field(default_factory=list)
|
|
169
|
+
# Hallucinated tools: need a tool result in message history (to keep the
|
|
170
|
+
# conversation well-formed) but should NOT be shown as errors in the TUI.
|
|
171
|
+
suppressed_failures: list[FailedToolCall] = Field(default_factory=list)
|
|
168
172
|
|
|
169
173
|
|
|
170
174
|
class APIToolFormatHandler:
|
|
175
|
+
def __init__(self) -> None:
|
|
176
|
+
# Track per-path truncated-history write_file retries so we can
|
|
177
|
+
# escalate on 2nd+ identical failures (model ignores advisory-only msgs).
|
|
178
|
+
self._truncated_hit_count: dict[str, int] = {}
|
|
179
|
+
|
|
171
180
|
@property
|
|
172
181
|
def name(self) -> str:
|
|
173
182
|
return "api"
|
|
@@ -346,12 +355,25 @@ class APIToolFormatHandler:
|
|
|
346
355
|
"list_mcp_resources", "list_resources", "search_resources",
|
|
347
356
|
}
|
|
348
357
|
|
|
358
|
+
suppressed_failures = []
|
|
349
359
|
for parsed_call in parsed.tool_calls:
|
|
350
360
|
tool_class = active_tools.get(parsed_call.tool_name)
|
|
351
361
|
if not tool_class:
|
|
352
|
-
#
|
|
353
|
-
#
|
|
362
|
+
# Hallucinated tools: add a tool result to keep the message
|
|
363
|
+
# history well-formed (prevents empty_after_tool loops) but
|
|
364
|
+
# route to suppressed_failures so the TUI doesn't show an error.
|
|
354
365
|
if parsed_call.tool_name in _IGNORE_TOOLS:
|
|
366
|
+
suppressed_failures.append(
|
|
367
|
+
FailedToolCall(
|
|
368
|
+
tool_name=parsed_call.tool_name,
|
|
369
|
+
call_id=parsed_call.call_id,
|
|
370
|
+
error=(
|
|
371
|
+
f"'{parsed_call.tool_name}' is not available. "
|
|
372
|
+
f"Use only tools from your tool list: "
|
|
373
|
+
f"{', '.join(sorted(active_tools.keys())[:8])}."
|
|
374
|
+
),
|
|
375
|
+
)
|
|
376
|
+
)
|
|
355
377
|
continue
|
|
356
378
|
failed_calls.append(
|
|
357
379
|
FailedToolCall(
|
|
@@ -367,6 +389,102 @@ class APIToolFormatHandler:
|
|
|
367
389
|
continue
|
|
368
390
|
|
|
369
391
|
args_model, _ = tool_class._get_tool_args_results()
|
|
392
|
+
|
|
393
|
+
# Detect when model copied truncated-history args (our truncation
|
|
394
|
+
# code replaces large tool-call args with {_truncated, _original_bytes,
|
|
395
|
+
# path}). Return a clear advisory instead of a pydantic traceback so
|
|
396
|
+
# the model re-does the call with real arguments rather than retrying
|
|
397
|
+
# the truncated form.
|
|
398
|
+
if (isinstance(parsed_call.raw_args, dict)
|
|
399
|
+
and parsed_call.raw_args.get("_truncated")):
|
|
400
|
+
path_hint = (parsed_call.raw_args.get("path")
|
|
401
|
+
or parsed_call.raw_args.get("file_path")
|
|
402
|
+
or "")
|
|
403
|
+
# Track retry count per path to escalate on 2nd+ offense.
|
|
404
|
+
hit_key = path_hint or "<unknown>"
|
|
405
|
+
hit_count = self._truncated_hit_count.get(hit_key, 0) + 1
|
|
406
|
+
self._truncated_hit_count[hit_key] = hit_count
|
|
407
|
+
escalate = hit_count >= 2
|
|
408
|
+
|
|
409
|
+
# Auto-embed the current file content so the model can
|
|
410
|
+
# rewrite immediately without an extra read_file round-trip.
|
|
411
|
+
file_embed = ""
|
|
412
|
+
if path_hint:
|
|
413
|
+
try:
|
|
414
|
+
p = Path(path_hint)
|
|
415
|
+
if p.exists() and p.is_file():
|
|
416
|
+
raw = p.read_text(errors="replace")
|
|
417
|
+
lines = raw.splitlines()
|
|
418
|
+
max_lines = 120
|
|
419
|
+
if len(lines) <= max_lines:
|
|
420
|
+
file_embed = (
|
|
421
|
+
f"\n\nCurrent file content of `{path_hint}`:\n"
|
|
422
|
+
f"```\n{raw}\n```\n"
|
|
423
|
+
f"Rewrite it now using write_file with the correct content."
|
|
424
|
+
)
|
|
425
|
+
else:
|
|
426
|
+
snippet = "\n".join(lines[:max_lines])
|
|
427
|
+
file_embed = (
|
|
428
|
+
f"\n\nCurrent file content of `{path_hint}` "
|
|
429
|
+
f"(first {max_lines} of {len(lines)} lines):\n"
|
|
430
|
+
f"```\n{snippet}\n```\n"
|
|
431
|
+
f"Use read_file to see the rest, then rewrite with write_file."
|
|
432
|
+
)
|
|
433
|
+
except Exception:
|
|
434
|
+
pass
|
|
435
|
+
if not file_embed and path_hint:
|
|
436
|
+
file_embed = f" Re-read `{path_hint}` with read_file first."
|
|
437
|
+
|
|
438
|
+
if escalate:
|
|
439
|
+
# Model is stuck in a truncated-template retry loop.
|
|
440
|
+
# Show project files and give a concrete directive.
|
|
441
|
+
try:
|
|
442
|
+
py_files = sorted(
|
|
443
|
+
str(p2.relative_to(Path.cwd()))
|
|
444
|
+
for p2 in Path.cwd().rglob("*.py")
|
|
445
|
+
if "__pycache__" not in str(p2) and ".git" not in str(p2)
|
|
446
|
+
)[:20]
|
|
447
|
+
dir_listing = "\n".join(f" {f}" for f in py_files)
|
|
448
|
+
except Exception:
|
|
449
|
+
dir_listing = " (could not list files)"
|
|
450
|
+
tool_name_hint = parsed_call.tool_name
|
|
451
|
+
if tool_name_hint == "search_replace":
|
|
452
|
+
recovery_hint = (
|
|
453
|
+
f"Use read_file on '{path_hint}' to see its current content, "
|
|
454
|
+
f"then call search_replace with fresh <<<<<<< SEARCH / ======= / "
|
|
455
|
+
f">>>>>>> REPLACE markers copied from the actual file text."
|
|
456
|
+
)
|
|
457
|
+
else:
|
|
458
|
+
recovery_hint = (
|
|
459
|
+
f"Use read_file on the target file, then call write_file "
|
|
460
|
+
f"with fully typed content, OR use search_replace to make "
|
|
461
|
+
f"targeted edits without rewriting the whole file."
|
|
462
|
+
)
|
|
463
|
+
escalation_suffix = (
|
|
464
|
+
f"\n\n[REPEATED FAILURE #{hit_count}: your {tool_name_hint} call "
|
|
465
|
+
f"keeps using a stale truncated template for '{path_hint}'. "
|
|
466
|
+
f"You MUST NOT copy args from history. "
|
|
467
|
+
f"Current .py files in project:\n{dir_listing}\n"
|
|
468
|
+
f"{recovery_hint}]"
|
|
469
|
+
)
|
|
470
|
+
else:
|
|
471
|
+
escalation_suffix = ""
|
|
472
|
+
|
|
473
|
+
failed_calls.append(
|
|
474
|
+
FailedToolCall(
|
|
475
|
+
tool_name=parsed_call.tool_name,
|
|
476
|
+
call_id=parsed_call.call_id,
|
|
477
|
+
error=(
|
|
478
|
+
f"your call used a "
|
|
479
|
+
f"truncated history entry as a template (it contained "
|
|
480
|
+
f"'_truncated'/'_original_bytes' instead of real "
|
|
481
|
+
f"arguments).{file_embed} Provide the full required "
|
|
482
|
+
f"arguments.{escalation_suffix}"
|
|
483
|
+
),
|
|
484
|
+
)
|
|
485
|
+
)
|
|
486
|
+
continue
|
|
487
|
+
|
|
370
488
|
try:
|
|
371
489
|
validated_args = args_model.model_validate(parsed_call.raw_args)
|
|
372
490
|
resolved_calls.append(
|
|
@@ -378,15 +496,78 @@ class APIToolFormatHandler:
|
|
|
378
496
|
)
|
|
379
497
|
)
|
|
380
498
|
except ValidationError as e:
|
|
499
|
+
error_str = str(e)
|
|
500
|
+
if (
|
|
501
|
+
parsed_call.tool_name == "write_file"
|
|
502
|
+
and "path" in error_str
|
|
503
|
+
and "Field required" in error_str
|
|
504
|
+
):
|
|
505
|
+
# Try to infer path from the first comment line of content.
|
|
506
|
+
# Gemma 4 frequently calls write_file(content="...") without path.
|
|
507
|
+
content_val = parsed_call.raw_args.get("content", "")
|
|
508
|
+
inferred_path: str | None = None
|
|
509
|
+
if content_val:
|
|
510
|
+
for _line in content_val.splitlines()[:5]:
|
|
511
|
+
_line = _line.strip()
|
|
512
|
+
_m = _re.match(
|
|
513
|
+
r'^#\s+([\w./+-]+\.(?:py|js|ts|json|yaml|yml|toml|md|txt|sh|cfg|ini))\s*$',
|
|
514
|
+
_line,
|
|
515
|
+
)
|
|
516
|
+
if _m:
|
|
517
|
+
inferred_path = _m.group(1)
|
|
518
|
+
break
|
|
519
|
+
if inferred_path:
|
|
520
|
+
try:
|
|
521
|
+
_new_args = dict(parsed_call.raw_args)
|
|
522
|
+
_new_args["path"] = inferred_path
|
|
523
|
+
validated_args = args_model.model_validate(_new_args)
|
|
524
|
+
resolved_calls.append(
|
|
525
|
+
ResolvedToolCall(
|
|
526
|
+
tool_name=parsed_call.tool_name,
|
|
527
|
+
tool_class=tool_class,
|
|
528
|
+
validated_args=validated_args,
|
|
529
|
+
call_id=parsed_call.call_id,
|
|
530
|
+
)
|
|
531
|
+
)
|
|
532
|
+
continue
|
|
533
|
+
except ValidationError:
|
|
534
|
+
pass
|
|
535
|
+
# List project .py files as hints so the model can pick the right one
|
|
536
|
+
_candidates: list[str] = []
|
|
537
|
+
try:
|
|
538
|
+
_candidates = [
|
|
539
|
+
str(p.relative_to(Path.cwd()))
|
|
540
|
+
for p in sorted(Path.cwd().rglob("*.py"))
|
|
541
|
+
if "__pycache__" not in str(p) and ".git" not in str(p)
|
|
542
|
+
][:12]
|
|
543
|
+
except Exception:
|
|
544
|
+
pass
|
|
545
|
+
_hint = (
|
|
546
|
+
f"Project .py files: {', '.join(_candidates)}"
|
|
547
|
+
if _candidates
|
|
548
|
+
else "Use read_file or glob to list available files."
|
|
549
|
+
)
|
|
550
|
+
error_msg = (
|
|
551
|
+
"missing required `path` parameter. "
|
|
552
|
+
"You must pass BOTH `path` AND `content` as separate arguments: "
|
|
553
|
+
'write_file(path="pkg/file.py", content="..."). '
|
|
554
|
+
f"Do NOT omit `path`. {_hint}"
|
|
555
|
+
)
|
|
556
|
+
else:
|
|
557
|
+
error_msg = f"Invalid arguments: {e}"
|
|
381
558
|
failed_calls.append(
|
|
382
559
|
FailedToolCall(
|
|
383
560
|
tool_name=parsed_call.tool_name,
|
|
384
561
|
call_id=parsed_call.call_id,
|
|
385
|
-
error=
|
|
562
|
+
error=error_msg,
|
|
386
563
|
)
|
|
387
564
|
)
|
|
388
565
|
|
|
389
|
-
return ResolvedMessage(
|
|
566
|
+
return ResolvedMessage(
|
|
567
|
+
tool_calls=resolved_calls,
|
|
568
|
+
failed_calls=failed_calls,
|
|
569
|
+
suppressed_failures=suppressed_failures,
|
|
570
|
+
)
|
|
390
571
|
|
|
391
572
|
def create_tool_response_message(
|
|
392
573
|
self, tool_call: ResolvedToolCall, result_text: str
|
|
@@ -404,13 +404,38 @@ class Bash(
|
|
|
404
404
|
self, *, command: str, stdout: str, stderr: str, returncode: int
|
|
405
405
|
) -> BashResult:
|
|
406
406
|
if returncode != 0:
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
if
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
407
|
+
# ADVISORY ONLY — never raise ToolError for non-zero exit codes.
|
|
408
|
+
# Raising blocks the model: it gets <tool_error> with no useful
|
|
409
|
+
# output, doesn't know if exit 1 means "no matches" (grep) or a
|
|
410
|
+
# real failure, and retries identically. Same pattern as the
|
|
411
|
+
# timeout handler above. Include a clear exit-code annotation so
|
|
412
|
+
# the model can reason about what happened.
|
|
413
|
+
# See feedback_no_tool_errors_for_loop_detection.md.
|
|
414
|
+
annotation = f"[Exit code {returncode}]"
|
|
415
|
+
if returncode < 0:
|
|
416
|
+
# Negative returncode means killed by a Unix signal.
|
|
417
|
+
try:
|
|
418
|
+
sig_name = signal.Signals(-returncode).name
|
|
419
|
+
except ValueError:
|
|
420
|
+
sig_name = f"signal {-returncode}"
|
|
421
|
+
annotation += (
|
|
422
|
+
f" — process killed by {sig_name}."
|
|
423
|
+
" If this command starts a server or long-running process,"
|
|
424
|
+
" background it with `command &` and verify ports with `ss -tlnp`."
|
|
425
|
+
)
|
|
426
|
+
elif not stdout and not stderr:
|
|
427
|
+
annotation += " (no output)"
|
|
428
|
+
if returncode == 1:
|
|
429
|
+
annotation += (
|
|
430
|
+
" — for grep/find, exit code 1 means no matches found"
|
|
431
|
+
)
|
|
432
|
+
annotated_stdout = (stdout + "\n" + annotation).strip() if stdout else annotation
|
|
433
|
+
return BashResult(
|
|
434
|
+
command=command,
|
|
435
|
+
stdout=annotated_stdout,
|
|
436
|
+
stderr=stderr,
|
|
437
|
+
returncode=returncode,
|
|
438
|
+
)
|
|
414
439
|
|
|
415
440
|
return BashResult(
|
|
416
441
|
command=command, stdout=stdout, stderr=stderr, returncode=returncode
|
|
@@ -445,7 +470,39 @@ class Bash(
|
|
|
445
470
|
)
|
|
446
471
|
except TimeoutError:
|
|
447
472
|
await _kill_process_tree(proc)
|
|
448
|
-
raise
|
|
473
|
+
# ADVISORY ONLY — never raise ToolError on timeout; raising
|
|
474
|
+
# causes the model to retry the exact same command (loop).
|
|
475
|
+
# Track repeat timeouts per command and escalate the hint.
|
|
476
|
+
# See feedback_no_tool_errors_for_loop_detection.md.
|
|
477
|
+
timeout_state = self.state.__dict__.setdefault(
|
|
478
|
+
"_bash_timeout_history", {}
|
|
479
|
+
)
|
|
480
|
+
count = timeout_state.get(args.command, 0) + 1
|
|
481
|
+
timeout_state[args.command] = count
|
|
482
|
+
if count == 1:
|
|
483
|
+
hint = (
|
|
484
|
+
"The command was killed. If it starts a server or "
|
|
485
|
+
"long-running process, background it with `command &` "
|
|
486
|
+
"instead of running it in the foreground."
|
|
487
|
+
)
|
|
488
|
+
else:
|
|
489
|
+
hint = (
|
|
490
|
+
f"[TIMEOUT #{count}] You have timed out {count}x on "
|
|
491
|
+
f"this exact command. Running it again will produce the "
|
|
492
|
+
f"same result. STOP retrying. Background servers with "
|
|
493
|
+
f"`&`, check existing listeners with `ss -tlnp`, or fix "
|
|
494
|
+
f"the underlying cause before re-running."
|
|
495
|
+
)
|
|
496
|
+
yield BashResult(
|
|
497
|
+
command=args.command,
|
|
498
|
+
stdout=(
|
|
499
|
+
f"Command timed out after {timeout}s: {args.command!r}\n"
|
|
500
|
+
f"{hint}"
|
|
501
|
+
),
|
|
502
|
+
stderr="",
|
|
503
|
+
returncode=124,
|
|
504
|
+
)
|
|
505
|
+
return
|
|
449
506
|
|
|
450
507
|
encoding = _get_subprocess_encoding()
|
|
451
508
|
stdout = (
|