drydock-cli 1.5.4__tar.gz → 1.5.5__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-1.5.4 → drydock_cli-1.5.5}/PKG-INFO +1 -1
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/agent_loop.py +134 -14
- drydock_cli-1.5.5/drydock/core/build_orchestrator.py +346 -0
- drydock_cli-1.5.5/drydock/core/prompts/builder.md +16 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/prompts/cli.md +11 -5
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/pyproject.toml +1 -1
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.github/CODEOWNERS +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.github/DISCUSSION_TEMPLATE/ideas.yml +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.github/workflows/build-and-upload.yml +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.github/workflows/ci.yml +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.github/workflows/issue-labeler.yml +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.github/workflows/release.yml +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.gitignore +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.pre-commit-config.yaml +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.python-version +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.typos.toml +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.vscode/extensions.json +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.vscode/launch.json +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/.vscode/settings.json +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/AGENTS.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/CHANGELOG.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/CLAUDE.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/CONTRIBUTING.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/Drydock_rebrand.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/LICENSE +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/NOTICE +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/PRD.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/README.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/action.yml +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/distribution/zed/LICENSE +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/distribution/zed/extension.toml +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/distribution/zed/icons/mistral_vibe.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/docs/README.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/docs/acp-setup.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/docs/proxy-setup.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/acp/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/acp/acp_agent_loop.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/acp/acp_logger.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/acp/entrypoint.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/acp/tools/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/acp/tools/base.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/acp/tools/builtins/bash.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/acp/tools/builtins/read_file.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/acp/tools/builtins/search_replace.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/acp/tools/builtins/todo.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/acp/tools/builtins/write_file.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/acp/tools/session_update.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/acp/utils.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/autocompletion/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/autocompletion/base.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/autocompletion/path_completion.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/autocompletion/slash_command.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/cli.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/clipboard.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/commands.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/entrypoint.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/history_manager.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/plan_offer/adapters/http_whoami_gateway.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/plan_offer/decide_plan_offer.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/plan_offer/ports/whoami_gateway.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/terminal_setup.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/ansi_markdown.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/app.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/app.tcss +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/external_editor.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/handlers/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/handlers/event_handler.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/notifications/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/notifications/adapters/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/notifications/adapters/textual_notification_adapter.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/notifications/ports/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/notifications/ports/notification_port.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/approval_app.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/banner/banner.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/banner/petit_chat.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/braille_renderer.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/chat_input/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/chat_input/body.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/chat_input/completion_manager.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/chat_input/completion_popup.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/chat_input/container.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/chat_input/text_area.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/compact.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/config_app.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/context_progress.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/load_more.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/loading.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/messages.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/no_markup_static.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/path_display.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/proxy_setup_app.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/question_app.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/session_picker.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/spinner.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/status_message.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/teleport_message.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/tool_widgets.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/tools.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/widgets/vscode_compat.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/windowing/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/windowing/history.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/windowing/history_windowing.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/textual_ui/windowing/state.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/update_notifier/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/update_notifier/adapters/filesystem_update_cache_repository.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/update_notifier/adapters/github_update_gateway.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/update_notifier/adapters/pypi_update_gateway.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/update_notifier/ports/update_cache_repository.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/update_notifier/ports/update_gateway.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/update_notifier/update.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/cli/update_notifier/whats_new.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/agents/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/agents/manager.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/agents/models.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/auth/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/auth/crypto.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/auth/github.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/autocompletion/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/autocompletion/completers.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/autocompletion/file_indexer/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/autocompletion/file_indexer/ignore_rules.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/autocompletion/file_indexer/indexer.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/autocompletion/file_indexer/store.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/autocompletion/file_indexer/watcher.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/autocompletion/fuzzy.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/autocompletion/path_prompt.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/autocompletion/path_prompt_adapter.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/config/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/config/_settings.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/config/harness_files/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/config/harness_files/_harness_manager.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/config/harness_files/_paths.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/consultant.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/drydock_states.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/hooks.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/llm/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/llm/backend/anthropic.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/llm/backend/base.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/llm/backend/factory.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/llm/backend/generic.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/llm/backend/mistral.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/llm/backend/reasoning_adapter.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/llm/backend/vertex.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/llm/exceptions.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/llm/format.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/llm/message_utils.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/llm/types.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/logger.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/middleware.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/output_formatters.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/paths/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/paths/_local_config_walk.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/paths/_vibe_home.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/paths/conventions.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/plan_session.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/plugins.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/programmatic.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/prompts/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/prompts/compact.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/prompts/dangerous_directory.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/prompts/diagnostic.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/prompts/explore.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/prompts/planner.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/prompts/project_context.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/prompts/tests.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/proxy_setup.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/session/agent_memory.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/session/checkpoints.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/session/session_loader.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/session/session_logger.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/session/session_migration.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/session/state_file.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/skills/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/skills/manager.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/skills/models.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/skills/parser.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/slug.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/system_prompt.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/telemetry/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/telemetry/send.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/teleport/errors.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/teleport/git.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/teleport/nuage.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/teleport/teleport.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/teleport/types.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/base.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/ask_user_question.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/bash.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/cron.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/exit_plan_mode.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/glob_tool.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/grep.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/invoke_skill.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/lsp.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/mcp_resources.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/notebook_edit.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/powershell.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/ask_user_question.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/bash.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/cron.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/glob.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/grep.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/invoke_skill.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/lsp.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/mcp_resources.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/notebook_edit.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/powershell.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/read_file.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/search_replace.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/swe_bench.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/task.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/task_manager.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/todo.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/tool_search.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/webfetch.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/websearch.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/worktree.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/prompts/write_file.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/read_file.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/search_replace.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/task.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/task_manager.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/todo.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/tool_search.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/webfetch.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/websearch.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/worktree.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/builtins/write_file.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/injection_guard.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/manager.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/mcp/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/mcp/registry.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/mcp/tools.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/mcp_sampling.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/ui.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/tools/utils.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/trusted_folders.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/types.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/core/utils.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/setup/onboarding/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/setup/onboarding/base.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/setup/onboarding/onboarding.tcss +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/setup/onboarding/screens/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/setup/onboarding/screens/api_key.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/setup/onboarding/screens/welcome.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/setup/trusted_folders/trust_folder_dialog.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/setup/trusted_folders/trust_folder_dialog.tcss +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/skills/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/skills/batch/SKILL.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/skills/create-presentation/SKILL.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/skills/deep-research/SKILL.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/skills/investigate/SKILL.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/skills/review/SKILL.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/skills/ship/SKILL.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/skills/simplify/SKILL.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock/whats_new.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock-acp.spec +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/drydock_terms.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/flake.lock +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/flake.nix +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/scripts/README.md +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/scripts/backup.sh +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/scripts/bump_version.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/scripts/deploy_to_github.sh +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/scripts/install.sh +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/scripts/monitor_test_battery.sh +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/scripts/prepare_release.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/scripts/publish_to_pypi.sh +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/scripts/test_bank.sh +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/scripts/test_full.sh +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/scripts/test_smoke.sh +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/conftest.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_acp.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_agent_thought.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_bash.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_compact_session_updates.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_content.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_initialize.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_list_sessions.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_load_session.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_multi_session.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_new_session.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_proxy_setup_acp.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_read_file.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_search_replace.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_set_config_option.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_set_mode.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_set_model.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_tool_call_session_update.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_utils.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/acp/test_write_file.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/autocompletion/test_file_indexer.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/autocompletion/test_fuzzy.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/autocompletion/test_path_completer_fuzzy.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/autocompletion/test_path_completer_recursive.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/autocompletion/test_path_completion_controller.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/autocompletion/test_path_prompt_transformer.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/autocompletion/test_slash_command_controller.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/autocompletion/test_ui_chat_autocompletion.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/backend/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/backend/data/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/backend/data/fireworks.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/backend/data/mistral.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/backend/test_anthropic_adapter.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/backend/test_backend.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/backend/test_reasoning_adapter.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/backend/test_vertex_anthropic_adapter.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/plan_offer/adapters/fake_whoami_gateway.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/plan_offer/test_decide_plan_offer.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/plan_offer/test_http_whoami_gateway.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/test_bell_notifications.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/test_braille_renderer.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/test_clipboard.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/test_commands.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/test_copy_shortcuts.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/test_external_editor.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/test_no_markup_static.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/test_question_app.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/test_spinner.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/test_switching_mode.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/test_ui_clipboard_notifications.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/test_ui_session_incremental_renderer.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/test_ui_session_resume.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/test_ui_skill_dispatch.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/textual_ui/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/cli/textual_ui/test_session_picker.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/conftest.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_agents.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_auth_crypto.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_auth_github.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_config_load_dotenv.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_config_paths.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_config_resolution.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_file_logging.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_plan_session.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_proxy_setup.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_slug.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_telemetry_send.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_teleport_git.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_teleport_nuage.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_teleport_service.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_trusted_folders.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/core/test_utils.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/e2e/common.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/e2e/conftest.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/e2e/mock_server.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/e2e/test_cli_tui_onboarding.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/e2e/test_cli_tui_streaming.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/e2e/test_cli_tui_tool_approval.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/mock/__init__.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/mock/mock_backend_factory.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/mock/mock_entrypoint.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/mock/utils.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/onboarding/test_run_onboarding.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/onboarding/test_ui_onboarding.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/session/test_session_loader.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/session/test_session_logger.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/session/test_session_migration.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/skills/conftest.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/skills/test_manager.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/skills/test_models.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/skills/test_parser.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_collapsed.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_ask_user_question/test_snapshot_ask_user_question_expanded.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_basic_conversation/test_snapshot_shows_basic_conversation.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_code_block_horizontal_scrolling/test_snapshot_allows_horizontal_scrolling_for_long_code_blocks.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_empty_assistant_before_reasoning/test_snapshot_empty_assistant_removed_when_reasoning_starts.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_accept_edits_mode.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_auto_approve_mode.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_to_plan_mode.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_cycle_wraps_to_default.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_modes/test_snapshot_default_mode.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_pending.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_parallel_tool_calls/test_snapshot_parallel_tool_calls_resolved.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_cancel_discards_changes.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_edit_existing_values.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_empty.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_initial_with_values.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_error.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_proxy_setup/test_snapshot_proxy_setup_save_new_values.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_answer_first_advance.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_first_answered_checkmark.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_initial.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_left_wraps.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_navigate_right.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_question_tab_to_second.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_initial.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_mixed_selection.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_navigate_to_submit.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_other_with_text.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_first.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_toggle_multiple.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_multi_select_untoggle.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_initial.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_down.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_other.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_to_third_option.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_navigate_up_wraps.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_question_app/test_snapshot_question_app_other_typing.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_buffered_reasoning_yields_before_content.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_interleaved_reasoning.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_reasoning_content/test_snapshot_shows_reasoning_content_expanded.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_release_update_notification/test_snapshot_shows_release_update_notification.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_session_resume/test_snapshot_shows_resumed_session_messages.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_partial.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_streaming_tool_call/test_snapshot_tool_call_updated.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_cancel_selected.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_multiple_commits.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_push_confirmation_single_commit.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_complete.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_auth_required.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_checking_git.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_complete.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_error.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_pushing.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_sending_token.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_teleport/test_snapshot_teleport_status_starting_workflow.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_no_plan_message.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_switch_message.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_upgrade_message.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/__snapshots__/test_ui_snapshot_whats_new/test_snapshot_shows_whats_new_message.svg +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/base_snapshot_test_app.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/conftest.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/snap_compare.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/test_ui_snapshot_ask_user_question.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/test_ui_snapshot_basic_conversation.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/test_ui_snapshot_code_block_horizontal_scrolling.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/test_ui_snapshot_empty_assistant_before_reasoning.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/test_ui_snapshot_modes.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/test_ui_snapshot_parallel_tool_calls.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/test_ui_snapshot_proxy_setup.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/test_ui_snapshot_question_app.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/test_ui_snapshot_reasoning_content.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/test_ui_snapshot_release_update_notification.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/test_ui_snapshot_session_resume.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/test_ui_snapshot_streaming_tool_call.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/test_ui_snapshot_teleport.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/snapshots/test_ui_snapshot_whats_new.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/stubs/fake_backend.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/stubs/fake_client.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/stubs/fake_tool.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_agent_auto_compact.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_agent_backend.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_agent_observer_streaming.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_agent_stats.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_agent_tasks.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_agent_tool_call.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_agents.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_bank_build.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_bank_debug.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_bank_multiagent.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_bank_prd.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_bank_prd_extended.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_bank_tools.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_bank_update.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_build_projects.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_cli_programmatic_preload.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_current_bugs.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_drydock_regression.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_drydock_tasks.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_full_regression.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_history_manager.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_integration.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_loop_detection.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_message_id.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_message_merging.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_middleware.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_multi_agent.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_real_failures.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_real_issues.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_real_workflow.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_reasoning_content.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_smoke.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_system_prompt.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_tagged_text.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_ui_external_editor.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_ui_input_history.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_user_issues.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/test_workloads.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/testbank_helpers.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/tools/test_ask_user_question.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/tools/test_bash.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/tools/test_exit_plan_mode.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/tools/test_grep.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/tools/test_invoke_context.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/tools/test_manager_get_tool_config.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/tools/test_mcp.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/tools/test_mcp_sampling.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/tools/test_task.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/tools/test_ui_bash_execution.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/tools/test_webfetch.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/tools/test_websearch.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/update_notifier/adapters/fake_update_cache_repository.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/update_notifier/adapters/fake_update_gateway.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/update_notifier/test_do_update.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/update_notifier/test_filesystem_update_cache_repository.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/update_notifier/test_github_update_gateway.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/update_notifier/test_pypi_update_gateway.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/update_notifier/test_ui_update_notification.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/update_notifier/test_update_use_case.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/tests/update_notifier/test_whats_new.py +0 -0
- {drydock_cli-1.5.4 → drydock_cli-1.5.5}/uv.lock +0 -0
|
@@ -474,12 +474,29 @@ class AgentLoop:
|
|
|
474
474
|
|
|
475
475
|
yield UserMessageEvent(content=user_msg, message_id=user_message.message_id)
|
|
476
476
|
|
|
477
|
-
# ===
|
|
478
|
-
#
|
|
479
|
-
#
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
477
|
+
# === BUILD ORCHESTRATION ===
|
|
478
|
+
# For complex build tasks (PRD + multiple files), run the multi-phase
|
|
479
|
+
# pipeline instead of letting the model do everything in one context.
|
|
480
|
+
if self._is_build_task(user_msg):
|
|
481
|
+
try:
|
|
482
|
+
from drydock.core.build_orchestrator import run_build_pipeline
|
|
483
|
+
summary = await run_build_pipeline(
|
|
484
|
+
user_prompt=user_msg,
|
|
485
|
+
config=self.config,
|
|
486
|
+
base_dir=Path.cwd(),
|
|
487
|
+
)
|
|
488
|
+
self._inject_system_note(summary)
|
|
489
|
+
logger.info("Build orchestrator completed successfully")
|
|
490
|
+
except Exception as e:
|
|
491
|
+
logger.warning("Build orchestrator failed (%s), falling back to normal flow", e)
|
|
492
|
+
auto_context = self._build_auto_context(user_msg)
|
|
493
|
+
if auto_context:
|
|
494
|
+
self._inject_system_note(auto_context)
|
|
495
|
+
else:
|
|
496
|
+
# Normal flow: inject context for non-build tasks
|
|
497
|
+
auto_context = self._build_auto_context(user_msg)
|
|
498
|
+
if auto_context:
|
|
499
|
+
self._inject_system_note(auto_context)
|
|
483
500
|
|
|
484
501
|
try:
|
|
485
502
|
should_break_loop = False
|
|
@@ -585,6 +602,10 @@ class AgentLoop:
|
|
|
585
602
|
except (json.JSONDecodeError, AttributeError):
|
|
586
603
|
edit_path = ""
|
|
587
604
|
|
|
605
|
+
# AUTO-FIX: Fix packaging issues the model gets wrong
|
|
606
|
+
if edit_path and edit_path.endswith(".py"):
|
|
607
|
+
self._auto_fix_package(edit_path)
|
|
608
|
+
|
|
588
609
|
# Auto-run diagnostics on edited Python files
|
|
589
610
|
if edit_path and edit_path.endswith(".py"):
|
|
590
611
|
try:
|
|
@@ -1658,6 +1679,98 @@ class AgentLoop:
|
|
|
1658
1679
|
|
|
1659
1680
|
return None
|
|
1660
1681
|
|
|
1682
|
+
def _is_build_task(self, user_msg: str) -> bool:
|
|
1683
|
+
"""Detect if a user message is a complex build task that needs orchestration."""
|
|
1684
|
+
msg_lower = user_msg.lower()
|
|
1685
|
+
has_build_verb = any(kw in msg_lower for kw in (
|
|
1686
|
+
"build", "create a", "implement", "get started",
|
|
1687
|
+
"set up", "scaffold", "review the prd", "review prd",
|
|
1688
|
+
))
|
|
1689
|
+
has_complexity = (
|
|
1690
|
+
len(user_msg) > 200
|
|
1691
|
+
or any(kw in msg_lower for kw in (
|
|
1692
|
+
"prd", "multiple", "package", "modules", "cli",
|
|
1693
|
+
"features", "commands", "architecture", "structure",
|
|
1694
|
+
))
|
|
1695
|
+
)
|
|
1696
|
+
# Check if a PRD.md exists in the working directory
|
|
1697
|
+
has_prd = Path.cwd().joinpath("PRD.md").exists() or Path.cwd().joinpath("prd.md").exists()
|
|
1698
|
+
return has_build_verb and (has_complexity or has_prd)
|
|
1699
|
+
|
|
1700
|
+
def _auto_fix_package(self, file_path: str) -> None:
|
|
1701
|
+
"""Silently fix common packaging mistakes after model writes a file.
|
|
1702
|
+
|
|
1703
|
+
The model (devstral-24B) consistently fails at:
|
|
1704
|
+
1. Creating __main__.py for packages
|
|
1705
|
+
2. Using relative imports instead of absolute
|
|
1706
|
+
This runs after every write_file/search_replace and fixes both.
|
|
1707
|
+
"""
|
|
1708
|
+
try:
|
|
1709
|
+
fp = Path(file_path)
|
|
1710
|
+
if not fp.exists() or not fp.is_file():
|
|
1711
|
+
return
|
|
1712
|
+
|
|
1713
|
+
pkg_dir = fp.parent
|
|
1714
|
+
init_file = pkg_dir / "__init__.py"
|
|
1715
|
+
|
|
1716
|
+
# Only fix files inside a package (has __init__.py)
|
|
1717
|
+
if not init_file.exists():
|
|
1718
|
+
return
|
|
1719
|
+
|
|
1720
|
+
pkg_name = pkg_dir.name
|
|
1721
|
+
|
|
1722
|
+
# 1. Create __main__.py if missing
|
|
1723
|
+
main_file = pkg_dir / "__main__.py"
|
|
1724
|
+
if not main_file.exists():
|
|
1725
|
+
# Find the most likely entry point (cli.py, main.py, app.py)
|
|
1726
|
+
entry = None
|
|
1727
|
+
entry_func = "main"
|
|
1728
|
+
for candidate in ["cli.py", "main.py", "app.py", "__init__.py"]:
|
|
1729
|
+
cand_path = pkg_dir / candidate
|
|
1730
|
+
if cand_path.exists() and candidate != "__init__.py":
|
|
1731
|
+
# Check if it has a main() function
|
|
1732
|
+
try:
|
|
1733
|
+
content = cand_path.read_text()
|
|
1734
|
+
if "def main(" in content:
|
|
1735
|
+
entry = candidate[:-3] # strip .py
|
|
1736
|
+
break
|
|
1737
|
+
except Exception:
|
|
1738
|
+
pass
|
|
1739
|
+
if entry:
|
|
1740
|
+
main_content = (
|
|
1741
|
+
f"from {pkg_name}.{entry} import {entry_func}\n\n"
|
|
1742
|
+
f"if __name__ == \"__main__\":\n"
|
|
1743
|
+
f" {entry_func}()\n"
|
|
1744
|
+
)
|
|
1745
|
+
main_file.write_text(main_content)
|
|
1746
|
+
logger.info("Auto-created %s/__main__.py (entry: %s.%s)", pkg_name, entry, entry_func)
|
|
1747
|
+
|
|
1748
|
+
# 2. Fix relative imports → absolute imports
|
|
1749
|
+
try:
|
|
1750
|
+
content = fp.read_text()
|
|
1751
|
+
if f"from .{'' if content else ''}" in content:
|
|
1752
|
+
import re
|
|
1753
|
+
# Replace from .module import X → from pkg.module import X
|
|
1754
|
+
fixed = re.sub(
|
|
1755
|
+
r"from \.([\w.]+) import",
|
|
1756
|
+
f"from {pkg_name}.\\1 import",
|
|
1757
|
+
content,
|
|
1758
|
+
)
|
|
1759
|
+
# Replace from . import X → from pkg import X
|
|
1760
|
+
fixed = re.sub(
|
|
1761
|
+
r"from \. import",
|
|
1762
|
+
f"from {pkg_name} import",
|
|
1763
|
+
fixed,
|
|
1764
|
+
)
|
|
1765
|
+
if fixed != content:
|
|
1766
|
+
fp.write_text(fixed)
|
|
1767
|
+
logger.info("Auto-fixed relative imports in %s", fp.name)
|
|
1768
|
+
except Exception:
|
|
1769
|
+
pass
|
|
1770
|
+
|
|
1771
|
+
except Exception as e:
|
|
1772
|
+
logger.debug("Auto-fix package failed for %s: %s", file_path, e)
|
|
1773
|
+
|
|
1661
1774
|
def _build_auto_context(self, user_msg: str) -> str | None:
|
|
1662
1775
|
"""Build auto-delegation context based on the prompt and project state.
|
|
1663
1776
|
|
|
@@ -1727,17 +1840,24 @@ class AgentLoop:
|
|
|
1727
1840
|
))
|
|
1728
1841
|
if is_build and is_complex:
|
|
1729
1842
|
parts.append(
|
|
1730
|
-
"
|
|
1731
|
-
"1.
|
|
1732
|
-
"2.
|
|
1733
|
-
"
|
|
1734
|
-
"
|
|
1735
|
-
"
|
|
1736
|
-
"
|
|
1843
|
+
"MANDATORY BUILD RULES:\n"
|
|
1844
|
+
"1. Plan first: list ALL files you will create\n"
|
|
1845
|
+
"2. ALWAYS create __main__.py so 'python3 -m package_name' works:\n"
|
|
1846
|
+
" ```python\n"
|
|
1847
|
+
" from package_name.cli import main\n"
|
|
1848
|
+
" if __name__ == '__main__':\n"
|
|
1849
|
+
" main()\n"
|
|
1850
|
+
" ```\n"
|
|
1851
|
+
"3. Use ABSOLUTE imports: 'from pkg.module import X', NOT 'from .module import X'\n"
|
|
1852
|
+
"4. Create test/sample data files BEFORE testing (the tool needs input to work)\n"
|
|
1853
|
+
"5. Test with: python3 -m package_name (NOT python3 package/file.py)\n"
|
|
1854
|
+
"6. If a test fails, read the error, fix with search_replace, then retry\n"
|
|
1855
|
+
"7. After 1-2 successful tests, STOP and tell the user it's done"
|
|
1737
1856
|
)
|
|
1738
1857
|
elif is_build:
|
|
1739
1858
|
parts.append(
|
|
1740
|
-
"
|
|
1859
|
+
"BUILD RULES: Use write_file to create files. Use absolute imports. "
|
|
1860
|
+
"Create __main__.py for packages. Create test data before testing. "
|
|
1741
1861
|
"Test with python3 -m package_name (not python3 package/file.py)."
|
|
1742
1862
|
)
|
|
1743
1863
|
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
"""Multi-phase build orchestrator.
|
|
2
|
+
|
|
3
|
+
Instead of running everything in one context window (where the model wastes
|
|
4
|
+
turns on packaging/import errors), this splits project builds into phases:
|
|
5
|
+
|
|
6
|
+
Phase 1: PLAN — planner subagent reads the PRD, outputs a JSON build plan
|
|
7
|
+
Phase 2: SCAFFOLD — pure Python creates dirs, __init__.py, __main__.py
|
|
8
|
+
Phase 3: IMPLEMENT — one subagent per file, each with clean context
|
|
9
|
+
Phase 4: (back in main loop) — test and fix
|
|
10
|
+
|
|
11
|
+
Each phase gets a separate context window, so the model only does what
|
|
12
|
+
it's good at (writing logic) and the framework handles what it's bad at
|
|
13
|
+
(packaging, imports, project structure).
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import json
|
|
19
|
+
import logging
|
|
20
|
+
import re
|
|
21
|
+
from dataclasses import dataclass, field
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
from typing import TYPE_CHECKING, Any
|
|
24
|
+
|
|
25
|
+
from drydock.core.agent_loop import AgentLoop
|
|
26
|
+
from drydock.core.agents.models import BuiltinAgentName
|
|
27
|
+
from drydock.core.config import Backend, ModelConfig, ProviderConfig, SessionLoggingConfig, VibeConfig
|
|
28
|
+
from drydock.core.types import AssistantEvent, ToolResultEvent
|
|
29
|
+
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
from drydock.core.agents.manager import AgentManager
|
|
32
|
+
from drydock.core.types import EntrypointMetadata
|
|
33
|
+
|
|
34
|
+
logger = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# ============================================================================
|
|
38
|
+
# Data structures
|
|
39
|
+
# ============================================================================
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class FileSpec:
|
|
43
|
+
path: str
|
|
44
|
+
purpose: str
|
|
45
|
+
imports: list[str] = field(default_factory=list)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass
|
|
49
|
+
class BuildPlan:
|
|
50
|
+
package_name: str
|
|
51
|
+
description: str
|
|
52
|
+
entry_point: str
|
|
53
|
+
files: list[FileSpec]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# ============================================================================
|
|
57
|
+
# Phase 1: PLAN
|
|
58
|
+
# ============================================================================
|
|
59
|
+
|
|
60
|
+
PLAN_PROMPT = """Analyze this project request and output a JSON build plan.
|
|
61
|
+
|
|
62
|
+
PROJECT REQUEST:
|
|
63
|
+
{user_prompt}
|
|
64
|
+
|
|
65
|
+
Output a JSON block inside ```json fences with this EXACT structure:
|
|
66
|
+
```json
|
|
67
|
+
{{
|
|
68
|
+
"package_name": "my_package",
|
|
69
|
+
"description": "One-line description of the project",
|
|
70
|
+
"entry_point": "cli",
|
|
71
|
+
"files": [
|
|
72
|
+
{{"path": "my_package/utils.py", "purpose": "Utility functions for X and Y", "imports": []}},
|
|
73
|
+
{{"path": "my_package/core.py", "purpose": "Core logic that does Z", "imports": ["my_package.utils"]}},
|
|
74
|
+
{{"path": "my_package/cli.py", "purpose": "CLI entry point with main() function using argparse", "imports": ["my_package.core"]}}
|
|
75
|
+
]
|
|
76
|
+
}}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
RULES:
|
|
80
|
+
- package_name: valid Python identifier, lowercase, underscores OK
|
|
81
|
+
- entry_point: the module with main() function (usually "cli")
|
|
82
|
+
- files: list in DEPENDENCY ORDER (dependencies first, entry_point last)
|
|
83
|
+
- Each purpose must be specific enough to implement the file from
|
|
84
|
+
- Do NOT include __init__.py or __main__.py (created automatically)
|
|
85
|
+
- The entry_point module MUST have a main() function
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def extract_plan(response_text: str) -> BuildPlan:
|
|
90
|
+
"""Extract a BuildPlan from the planner's free-text response."""
|
|
91
|
+
# Try fenced JSON block first
|
|
92
|
+
match = re.search(r"```(?:json)?\s*\n(.*?)\n```", response_text, re.DOTALL)
|
|
93
|
+
if match:
|
|
94
|
+
raw = match.group(1)
|
|
95
|
+
else:
|
|
96
|
+
# Fallback: find first { ... } with "package_name"
|
|
97
|
+
match = re.search(r"\{[^{}]*\"package_name\".*\}", response_text, re.DOTALL)
|
|
98
|
+
if match:
|
|
99
|
+
raw = match.group(0)
|
|
100
|
+
else:
|
|
101
|
+
raise ValueError("No JSON build plan found in planner response")
|
|
102
|
+
|
|
103
|
+
data = json.loads(raw)
|
|
104
|
+
|
|
105
|
+
files = []
|
|
106
|
+
for f in data.get("files", []):
|
|
107
|
+
files.append(FileSpec(
|
|
108
|
+
path=f["path"],
|
|
109
|
+
purpose=f["purpose"],
|
|
110
|
+
imports=f.get("imports", []),
|
|
111
|
+
))
|
|
112
|
+
|
|
113
|
+
return BuildPlan(
|
|
114
|
+
package_name=data["package_name"],
|
|
115
|
+
description=data.get("description", ""),
|
|
116
|
+
entry_point=data.get("entry_point", "cli"),
|
|
117
|
+
files=files,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
async def run_planner(
|
|
122
|
+
user_prompt: str,
|
|
123
|
+
config: VibeConfig,
|
|
124
|
+
max_turns: int = 8,
|
|
125
|
+
) -> BuildPlan:
|
|
126
|
+
"""Phase 1: Spawn a planner subagent to create a build plan."""
|
|
127
|
+
plan_prompt = PLAN_PROMPT.format(user_prompt=user_prompt)
|
|
128
|
+
|
|
129
|
+
planner = AgentLoop(
|
|
130
|
+
config=config,
|
|
131
|
+
agent_name=BuiltinAgentName.AUTO_APPROVE,
|
|
132
|
+
max_turns=max_turns,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
response_parts = []
|
|
136
|
+
async for event in planner.act(plan_prompt):
|
|
137
|
+
if isinstance(event, AssistantEvent) and event.content:
|
|
138
|
+
response_parts.append(event.content)
|
|
139
|
+
|
|
140
|
+
full_response = "\n".join(response_parts)
|
|
141
|
+
logger.info("Planner response length: %d chars", len(full_response))
|
|
142
|
+
|
|
143
|
+
return extract_plan(full_response)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
# ============================================================================
|
|
147
|
+
# Phase 2: SCAFFOLD
|
|
148
|
+
# ============================================================================
|
|
149
|
+
|
|
150
|
+
def scaffold_package(plan: BuildPlan, base_dir: Path) -> list[Path]:
|
|
151
|
+
"""Phase 2: Create package structure deterministically. No LLM needed."""
|
|
152
|
+
pkg_dir = base_dir / plan.package_name
|
|
153
|
+
pkg_dir.mkdir(parents=True, exist_ok=True)
|
|
154
|
+
|
|
155
|
+
created = []
|
|
156
|
+
|
|
157
|
+
# __init__.py
|
|
158
|
+
init_path = pkg_dir / "__init__.py"
|
|
159
|
+
init_path.write_text(f'"""{plan.description}"""\n')
|
|
160
|
+
created.append(init_path)
|
|
161
|
+
|
|
162
|
+
# __main__.py with correct absolute import
|
|
163
|
+
main_path = pkg_dir / "__main__.py"
|
|
164
|
+
main_path.write_text(
|
|
165
|
+
f"from {plan.package_name}.{plan.entry_point} import main\n\n"
|
|
166
|
+
f'if __name__ == "__main__":\n'
|
|
167
|
+
f" main()\n"
|
|
168
|
+
)
|
|
169
|
+
created.append(main_path)
|
|
170
|
+
|
|
171
|
+
# Create stub files so imports resolve during implementation
|
|
172
|
+
for file_spec in plan.files:
|
|
173
|
+
fp = base_dir / file_spec.path
|
|
174
|
+
fp.parent.mkdir(parents=True, exist_ok=True)
|
|
175
|
+
fp.write_text(f'"""{file_spec.purpose}"""\n\n# TODO: implement\n')
|
|
176
|
+
created.append(fp)
|
|
177
|
+
|
|
178
|
+
return created
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
# ============================================================================
|
|
182
|
+
# Phase 3: IMPLEMENT (one subagent per file)
|
|
183
|
+
# ============================================================================
|
|
184
|
+
|
|
185
|
+
FILE_PROMPT = """Write the COMPLETE implementation for `{file_path}`.
|
|
186
|
+
|
|
187
|
+
Package: {package_name}
|
|
188
|
+
Purpose: {purpose}
|
|
189
|
+
|
|
190
|
+
Other modules in this package:
|
|
191
|
+
{module_listing}
|
|
192
|
+
|
|
193
|
+
{import_note}
|
|
194
|
+
|
|
195
|
+
RULES:
|
|
196
|
+
- Use write_file to write the complete file
|
|
197
|
+
- Use ABSOLUTE imports: `from {package_name}.module import X`
|
|
198
|
+
- Do NOT use relative imports (from .module)
|
|
199
|
+
- Write production-quality code with type hints and docstrings
|
|
200
|
+
- If this is the CLI module, it MUST have a `def main():` function using argparse
|
|
201
|
+
- After writing the file, STOP immediately
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
async def implement_file(
|
|
206
|
+
file_spec: FileSpec,
|
|
207
|
+
plan: BuildPlan,
|
|
208
|
+
config: VibeConfig,
|
|
209
|
+
) -> bool:
|
|
210
|
+
"""Spawn a builder subagent to implement one file."""
|
|
211
|
+
# Build module listing
|
|
212
|
+
module_lines = []
|
|
213
|
+
for f in plan.files:
|
|
214
|
+
marker = " ← THIS FILE" if f.path == file_spec.path else ""
|
|
215
|
+
module_lines.append(f" {f.path}: {f.purpose}{marker}")
|
|
216
|
+
module_listing = "\n".join(module_lines)
|
|
217
|
+
|
|
218
|
+
import_note = ""
|
|
219
|
+
if file_spec.imports:
|
|
220
|
+
import_note = f"This file should import from: {', '.join(file_spec.imports)}"
|
|
221
|
+
|
|
222
|
+
prompt = FILE_PROMPT.format(
|
|
223
|
+
file_path=file_spec.path,
|
|
224
|
+
package_name=plan.package_name,
|
|
225
|
+
purpose=file_spec.purpose,
|
|
226
|
+
module_listing=module_listing,
|
|
227
|
+
import_note=import_note,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
builder = AgentLoop(
|
|
231
|
+
config=config,
|
|
232
|
+
agent_name=BuiltinAgentName.AUTO_APPROVE,
|
|
233
|
+
max_turns=6,
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
wrote_file = False
|
|
237
|
+
async for event in builder.act(prompt):
|
|
238
|
+
if isinstance(event, ToolResultEvent) and event.tool_name == "write_file":
|
|
239
|
+
if not event.error:
|
|
240
|
+
wrote_file = True
|
|
241
|
+
|
|
242
|
+
return wrote_file
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
# ============================================================================
|
|
246
|
+
# Main orchestrator
|
|
247
|
+
# ============================================================================
|
|
248
|
+
|
|
249
|
+
async def run_build_pipeline(
|
|
250
|
+
user_prompt: str,
|
|
251
|
+
config: VibeConfig,
|
|
252
|
+
base_dir: Path | None = None,
|
|
253
|
+
) -> str:
|
|
254
|
+
"""Run the full multi-phase build pipeline.
|
|
255
|
+
|
|
256
|
+
Returns a summary string for the main agent to display.
|
|
257
|
+
"""
|
|
258
|
+
if base_dir is None:
|
|
259
|
+
base_dir = Path.cwd()
|
|
260
|
+
|
|
261
|
+
# Phase 1: Plan
|
|
262
|
+
logger.info("BUILD PHASE 1: Planning...")
|
|
263
|
+
try:
|
|
264
|
+
plan = await run_planner(user_prompt, config)
|
|
265
|
+
except (ValueError, json.JSONDecodeError, KeyError) as e:
|
|
266
|
+
raise RuntimeError(f"Planning failed: {e}") from e
|
|
267
|
+
|
|
268
|
+
logger.info("Plan: package=%s, files=%d, entry=%s",
|
|
269
|
+
plan.package_name, len(plan.files), plan.entry_point)
|
|
270
|
+
|
|
271
|
+
# Phase 2: Scaffold
|
|
272
|
+
logger.info("BUILD PHASE 2: Scaffolding...")
|
|
273
|
+
created = scaffold_package(plan, base_dir)
|
|
274
|
+
logger.info("Scaffolded %d files", len(created))
|
|
275
|
+
|
|
276
|
+
# Phase 3: Implement each file
|
|
277
|
+
logger.info("BUILD PHASE 3: Implementing %d files...", len(plan.files))
|
|
278
|
+
results = []
|
|
279
|
+
for i, file_spec in enumerate(plan.files):
|
|
280
|
+
logger.info(" Implementing [%d/%d]: %s", i + 1, len(plan.files), file_spec.path)
|
|
281
|
+
try:
|
|
282
|
+
success = await implement_file(file_spec, plan, config)
|
|
283
|
+
results.append((file_spec.path, success))
|
|
284
|
+
if success:
|
|
285
|
+
# Post-fix: ensure absolute imports
|
|
286
|
+
_fix_imports(base_dir / file_spec.path, plan.package_name)
|
|
287
|
+
except Exception as e:
|
|
288
|
+
logger.warning(" Failed to implement %s: %s", file_spec.path, e)
|
|
289
|
+
results.append((file_spec.path, False))
|
|
290
|
+
|
|
291
|
+
# Build summary
|
|
292
|
+
succeeded = sum(1 for _, ok in results if ok)
|
|
293
|
+
failed_files = [path for path, ok in results if not ok]
|
|
294
|
+
|
|
295
|
+
summary_lines = [
|
|
296
|
+
f"PROJECT BUILT: {plan.package_name}",
|
|
297
|
+
f"Description: {plan.description}",
|
|
298
|
+
f"Files: {succeeded}/{len(plan.files)} implemented",
|
|
299
|
+
f"",
|
|
300
|
+
f"Package structure:",
|
|
301
|
+
]
|
|
302
|
+
for f in plan.files:
|
|
303
|
+
status = "OK" if any(p == f.path and ok for p, ok in results) else "STUB"
|
|
304
|
+
summary_lines.append(f" {f.path} [{status}] — {f.purpose}")
|
|
305
|
+
|
|
306
|
+
summary_lines.extend([
|
|
307
|
+
f"",
|
|
308
|
+
f"Entry point: python3 -m {plan.package_name}",
|
|
309
|
+
f"",
|
|
310
|
+
f"Test the project now by running: python3 -m {plan.package_name} --help",
|
|
311
|
+
f"If it fails, read the error and fix with search_replace.",
|
|
312
|
+
])
|
|
313
|
+
|
|
314
|
+
if failed_files:
|
|
315
|
+
summary_lines.extend([
|
|
316
|
+
f"",
|
|
317
|
+
f"NEEDS IMPLEMENTATION: {', '.join(failed_files)}",
|
|
318
|
+
f"These files have stubs only. Implement them with write_file.",
|
|
319
|
+
])
|
|
320
|
+
|
|
321
|
+
return "\n".join(summary_lines)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def _fix_imports(file_path: Path, package_name: str) -> None:
|
|
325
|
+
"""Fix relative imports in a file to absolute imports."""
|
|
326
|
+
try:
|
|
327
|
+
if not file_path.exists():
|
|
328
|
+
return
|
|
329
|
+
content = file_path.read_text()
|
|
330
|
+
if "from ." not in content:
|
|
331
|
+
return
|
|
332
|
+
fixed = re.sub(
|
|
333
|
+
r"from \.([\w.]+) import",
|
|
334
|
+
f"from {package_name}.\\1 import",
|
|
335
|
+
content,
|
|
336
|
+
)
|
|
337
|
+
fixed = re.sub(
|
|
338
|
+
r"from \. import",
|
|
339
|
+
f"from {package_name} import",
|
|
340
|
+
fixed,
|
|
341
|
+
)
|
|
342
|
+
if fixed != content:
|
|
343
|
+
file_path.write_text(fixed)
|
|
344
|
+
logger.info("Fixed relative imports in %s", file_path.name)
|
|
345
|
+
except Exception:
|
|
346
|
+
pass
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
You are a code implementation agent. You write ONE file for a Python package.
|
|
2
|
+
|
|
3
|
+
You will be given:
|
|
4
|
+
- The file path to create
|
|
5
|
+
- The file's purpose
|
|
6
|
+
- The package structure (what other modules exist)
|
|
7
|
+
- Which modules this file imports from
|
|
8
|
+
|
|
9
|
+
Rules:
|
|
10
|
+
- Write the COMPLETE file using write_file. Include all imports, classes, functions.
|
|
11
|
+
- Use ABSOLUTE imports: `from package_name.module import X`, NOT `from .module import X`
|
|
12
|
+
- Do NOT create __init__.py or __main__.py (already done)
|
|
13
|
+
- Do NOT run bash commands or tests
|
|
14
|
+
- Do NOT read other files unless absolutely necessary
|
|
15
|
+
- After writing the file, STOP. Do not do anything else.
|
|
16
|
+
- Write production-quality code: type hints, docstrings, error handling.
|
|
@@ -223,12 +223,18 @@ Error Handling:
|
|
|
223
223
|
- After ANY error, your next action must be DIFFERENT from what just failed.
|
|
224
224
|
- Never run the same failing command twice — the result won't change.
|
|
225
225
|
|
|
226
|
-
Python Package Rules:
|
|
226
|
+
Python Package Rules (MANDATORY):
|
|
227
227
|
When creating Python packages (directories with __init__.py):
|
|
228
|
-
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
228
|
+
- ALWAYS create __main__.py so `python3 -m mypackage` works. Contents:
|
|
229
|
+
```
|
|
230
|
+
from mypackage.cli import main
|
|
231
|
+
if __name__ == "__main__":
|
|
232
|
+
main()
|
|
233
|
+
```
|
|
234
|
+
- Use ABSOLUTE imports: `from mypackage.module import X`, NOT `from .module import X`
|
|
235
|
+
- NEVER run `python3 mypackage/file.py` — ALWAYS use `python3 -m mypackage`
|
|
236
|
+
- Create sample/test data BEFORE running tests (e.g., create test.log before analyzing it)
|
|
237
|
+
- After 1-2 successful test runs, STOP testing and summarize what you built
|
|
232
238
|
|
|
233
239
|
Debugging Best Practices:
|
|
234
240
|
When fixing bugs, follow this cycle: RUN → READ → FIX → VERIFY.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|