wade-cli 0.30.2__tar.gz → 0.33.0__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.
- {wade_cli-0.30.2 → wade_cli-0.33.0}/.wade.yml +22 -23
- {wade_cli-0.30.2 → wade_cli-0.33.0}/AGENTS.md +1 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/CHANGELOG.md +42 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/KNOWLEDGE.md +86 -2
- wade_cli-0.33.0/KNOWLEDGE.ratings.yml +62 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/PKG-INFO +16 -4
- {wade_cli-0.30.2 → wade_cli-0.33.0}/README.md +14 -2
- {wade_cli-0.30.2 → wade_cli-0.33.0}/docs/dev/architecture.md +4 -5
- {wade_cli-0.30.2 → wade_cli-0.33.0}/docs/dev/skills-system.md +2 -3
- {wade_cli-0.30.2 → wade_cli-0.33.0}/pyproject.toml +2 -2
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/__init__.py +1 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/hooks/plan_write_guard.py +4 -5
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/hooks/worktree_guard.py +4 -5
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/models/delegation.py +1 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/models/task.py +12 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/providers/base.py +6 -3
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/providers/clickup.py +7 -2
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/providers/github.py +8 -4
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/providers/markdown.py +5 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/ai_resolution.py +12 -3
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/check_service.py +51 -12
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/delegation_service.py +1 -19
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/deps_service.py +4 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/implementation_service/__init__.py +6 -0
- wade_cli-0.33.0/src/wade/services/implementation_service/_shared.py +55 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/implementation_service/batch.py +1 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/implementation_service/bootstrap.py +2 -12
- wade_cli-0.33.0/src/wade/services/implementation_service/cleanup.py +370 -0
- wade_cli-0.33.0/src/wade/services/implementation_service/core.py +772 -0
- wade_cli-0.33.0/src/wade/services/implementation_service/done.py +488 -0
- wade_cli-0.33.0/src/wade/services/implementation_service/draft_pr.py +191 -0
- wade_cli-0.33.0/src/wade/services/implementation_service/lifecycle.py +472 -0
- wade_cli-0.33.0/src/wade/services/implementation_service/sync.py +722 -0
- wade_cli-0.33.0/src/wade/services/init_service/__init__.py +16 -0
- wade_cli-0.33.0/src/wade/services/init_service/auth.py +96 -0
- wade_cli-0.33.0/src/wade/services/init_service/commands.py +707 -0
- wade_cli-0.33.0/src/wade/services/init_service/config_io.py +516 -0
- wade_cli-0.33.0/src/wade/services/init_service/manifest.py +146 -0
- wade_cli-0.33.0/src/wade/services/init_service/migrations.py +354 -0
- wade_cli-0.33.0/src/wade/services/init_service/prompts_ai.py +339 -0
- wade_cli-0.33.0/src/wade/services/init_service/prompts_setup.py +675 -0
- wade_cli-0.33.0/src/wade/services/init_service/shell.py +185 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/plan_service.py +123 -26
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/prompt_delivery.py +1 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/review_delegation_service.py +1 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/skills/installer.py +1 -6
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/ui/console.py +1 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/utils/install.py +23 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/skills/implementation-session/SKILL.md +1 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/e2e/test_implement_work_done_contract.py +1 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/integration/test_autostash.py +9 -9
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/integration/test_implementation_lifecycle.py +15 -7
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/integration/test_skill_install.py +2 -2
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/live/test_wade_live_ai_taskr.py +0 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_effort.py +8 -2
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_hooks/test_plan_write_guard.py +1 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_hooks/test_worktree_guard.py +1 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_models/test_delegation.py +1 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_providers/test_clickup.py +14 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_providers/test_github.py +22 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_providers/test_markdown.py +9 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_ai_resolution.py +15 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_bootstrap_allowlist.py +1 -8
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_catchup.py +28 -28
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_check.py +8 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_deps_service.py +54 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_done_plan_flag.py +12 -12
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_done_via_direct_cleanup.py +27 -27
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_implementation_done_sync.py +194 -90
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_implementation_service.py +74 -34
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_init.py +158 -80
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_init_shell_integration.py +14 -14
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_plan_service.py +354 -4
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_post_implementation_lifecycle.py +52 -52
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_pr_summary_path.py +8 -8
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_preserve_session_data.py +16 -16
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_prompt_delivery.py +1 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_smart_start_resume.py +1 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_sync_base_branch.py +12 -12
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_utils/test_install.py +45 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_utils/test_markdown.py +1 -1
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_yolo.py +26 -40
- wade_cli-0.30.2/KNOWLEDGE.ratings.yml +0 -30
- wade_cli-0.30.2/src/wade/services/implementation_service/core.py +0 -2869
- wade_cli-0.30.2/src/wade/services/init_service.py +0 -2770
- wade_cli-0.30.2/tests/fixtures/transcripts/gemini_session.txt +0 -30
- {wade_cli-0.30.2 → wade_cli-0.33.0}/.github/workflows/auto-version.yml +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/.github/workflows/ci.yml +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/.github/workflows/pr-title-lint.yml +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/.github/workflows/publish.yml +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/.github/workflows/release.yml +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/.gitignore +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/.pre-commit-config.yaml +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/CONTRIBUTING.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/assets/wade.png +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/docker-compose.e2e.yml +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/docs/dev/documentation-policies.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/docs/dev/extending.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/docs/dev/testing.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/install.sh +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/auto_version.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/changelog.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/check-all.sh +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/check.sh +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/fmt.sh +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/hooks/pre-push +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/install-hooks.sh +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/release.sh +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/setup-worktree.sh +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/test-e2e-docker.sh +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/test-e2e.sh +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/test-live-ai-taskr.sh +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/test-live-ai.sh +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/test-live-gh.sh +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/scripts/test.sh +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/__main__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/cli/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/cli/admin.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/cli/autocomplete.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/cli/implementation_session.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/cli/knowledge.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/cli/main.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/cli/plan_session.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/cli/review.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/cli/review_pr_comments_session.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/cli/session_shared.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/cli/task.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/cli/worktree.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/config/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/config/loader.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/config/migrations.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/config/schema.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/db/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/db/engine.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/db/repositories.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/db/tables.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/git/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/git/branch.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/git/pr.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/git/repo.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/git/stash.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/git/sync.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/git/worktree.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/hooks/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/logging/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/logging/context.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/logging/setup.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/models/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/models/batch.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/models/config.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/models/deps.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/models/events.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/models/review.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/models/session.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/providers/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/providers/_pr_delegate.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/providers/registry.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/batch_review_service.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/implementation_service/usage_tracking.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/knowledge_search.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/knowledge_service.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/review_service.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/review_settle.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/smart_start.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/services/task_service.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/skills/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/skills/pointer.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/ui/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/ui/prompts.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/utils/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/utils/clipboard.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/utils/http.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/utils/markdown.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/utils/process.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/utils/slug.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/utils/terminal.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/utils/token_usage_markdown.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/src/wade/utils/update_check.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/agents-pointer.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/prompts/deps-analysis.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/prompts/implement-context.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/prompts/plan-session.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/prompts/review-batch.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/prompts/review-code.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/prompts/review-plan.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/prompts/review-pr-comments.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/setup-worktree.sh.example +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/skills/_partials/review-enforcement-rule.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/skills/_partials/review-implementation-closing-step.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/skills/_partials/review-plan-step.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/skills/_partials/user-interaction.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/skills/deps/SKILL.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/skills/knowledge/SKILL.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/skills/plan-session/SKILL.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/skills/review-pr-comments-session/SKILL.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/skills/task/SKILL.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/skills/task/examples.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/skills/task/plan-format.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/templates/statusline-command.sh +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/conftest.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/e2e/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/e2e/_support.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/e2e/conftest.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/e2e/mock_gh_script.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/e2e/test_admin_contract.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/e2e/test_check_contract.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/e2e/test_knowledge_contract.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/e2e/test_mock_gh_contract.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/e2e/test_plan_contract.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/e2e/test_review_contract.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/e2e/test_smart_start_contract.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/e2e/test_task_contract.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/e2e/test_work_sync_list_contract.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/fixtures/live/taskr_header_hi_body.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/fixtures/live/taskr_header_howdy_body.md +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/fixtures/transcripts/claude_session.txt +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/fixtures/transcripts/codex_session.txt +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/fixtures/transcripts/copilot_session.txt +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/fixtures/transcripts/generic_session.txt +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/integration/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/integration/test_check.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/integration/test_git.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/integration/test_init.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/integration/test_knowledge.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/integration/test_markdown_provider.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/live/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/live/test_wade_live_ai.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/live/test_wade_live_gh.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/test_cli_basics.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/conftest.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_cli/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_cli/test_done_review_hint.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_cli/test_knowledge_cli.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_cli/test_review_cli.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_cli/test_session_subapps.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_cli/test_shell_init.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_cli/test_task_cli.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_cli/test_work_ai_flags.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_cli/test_work_cli.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_config/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_config/test_loader.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_config/test_migrations.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_config/test_migrations_atomic.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_console.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_db/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_db/test_repository_transactions.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_git/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_git/test_branch_slugify.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_git/test_detached_worktree.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_git/test_pr_base.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_git/test_repo.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_git/test_scaffold_commit.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_git/test_sync_conflicted_files.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_git/test_worktree_remove.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_hooks/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_models/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_models/test_batch.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_models/test_config_models.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_models/test_db.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_models/test_deps_models.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_models/test_deps_partition.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_models/test_review.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_models/test_task_models.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_providers/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_providers/test_github_pr.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_batch_review_service.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_bootstrap_hook_timeout.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_delegation_service.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_implementation_service_resume.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_knowledge_search.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_knowledge_service.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_poll_for_reviews.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_review_delegation_service.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_review_service.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_smart_start.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_task_service.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_tracked_managed_files.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_services/test_worktree_gitignore.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_skills/test_managed_gitignore.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_utils/__init__.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_utils/test_http.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_utils/test_process.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_utils/test_prompts.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_utils/test_slug.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_utils/test_terminal.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_utils/test_terminal_launch.py +0 -0
- {wade_cli-0.30.2 → wade_cli-0.33.0}/tests/unit/test_utils/test_update_check.py +0 -0
|
@@ -7,50 +7,49 @@ project:
|
|
|
7
7
|
merge_strategy: PR
|
|
8
8
|
ai:
|
|
9
9
|
default_tool: claude
|
|
10
|
-
default_model: claude-
|
|
11
|
-
effort:
|
|
10
|
+
default_model: claude-opus-4.8
|
|
11
|
+
effort: xhigh
|
|
12
12
|
plan:
|
|
13
|
-
tool: claude
|
|
14
|
-
model: claude-opus-4.7
|
|
15
13
|
effort: xhigh
|
|
16
14
|
yolo: true
|
|
17
15
|
deps:
|
|
18
|
-
tool:
|
|
19
|
-
model: claude-sonnet-
|
|
16
|
+
tool: claude
|
|
17
|
+
model: claude-sonnet-5
|
|
20
18
|
mode: headless
|
|
21
|
-
|
|
19
|
+
effort: high
|
|
22
20
|
review_plan:
|
|
23
|
-
tool:
|
|
24
|
-
model: claude-sonnet-
|
|
21
|
+
tool: claude
|
|
22
|
+
model: claude-sonnet-5
|
|
25
23
|
mode: headless
|
|
24
|
+
effort: high
|
|
26
25
|
enabled: true
|
|
27
|
-
yolo: false
|
|
28
26
|
review_implementation:
|
|
29
|
-
tool:
|
|
30
|
-
model: claude-sonnet-
|
|
27
|
+
tool: claude
|
|
28
|
+
model: claude-sonnet-5
|
|
31
29
|
mode: headless
|
|
30
|
+
effort: high
|
|
32
31
|
enabled: true
|
|
33
|
-
yolo: false
|
|
34
32
|
review_batch:
|
|
35
|
-
tool:
|
|
36
|
-
model: claude-sonnet-
|
|
33
|
+
tool: claude
|
|
34
|
+
model: claude-sonnet-5
|
|
37
35
|
mode: interactive
|
|
36
|
+
effort: high
|
|
38
37
|
enabled: true
|
|
39
38
|
yolo: true
|
|
40
|
-
yolo:
|
|
39
|
+
yolo: false
|
|
41
40
|
models:
|
|
42
41
|
claude:
|
|
43
42
|
easy:
|
|
44
|
-
model: claude-
|
|
45
|
-
effort: xhigh
|
|
46
|
-
medium:
|
|
47
|
-
model: claude-sonnet-4.6
|
|
43
|
+
model: claude-haiku-4.5
|
|
48
44
|
effort: max
|
|
49
|
-
|
|
50
|
-
model: claude-
|
|
45
|
+
medium:
|
|
46
|
+
model: claude-sonnet-5
|
|
51
47
|
effort: high
|
|
48
|
+
complex:
|
|
49
|
+
model: claude-sonnet-5
|
|
50
|
+
effort: xhigh
|
|
52
51
|
very_complex:
|
|
53
|
-
model: claude-opus-4.
|
|
52
|
+
model: claude-opus-4.8
|
|
54
53
|
effort: xhigh
|
|
55
54
|
provider:
|
|
56
55
|
name: github
|
|
@@ -70,7 +70,7 @@ CLI modules are thin dispatch — they parse flags via Typer, then call service
|
|
|
70
70
|
|
|
71
71
|
### Key Design Patterns
|
|
72
72
|
|
|
73
|
-
- **AI Tool Adapters via crossby**: `AbstractAITool` and every tool-specific adapter (Claude, Cursor, Copilot,
|
|
73
|
+
- **AI Tool Adapters via crossby**: `AbstractAITool` and every tool-specific adapter (Claude, Cursor, Copilot, Codex, OpenCode, Antigravity, Antigravity CLI, VS Code) live in the external `crossby` dependency, not this repo. Wade's services import `crossby.ai_tools` and `crossby.models.ai` directly. Adding a new AI tool means contributing to crossby, not wade.
|
|
74
74
|
- **Provider Abstraction**: `AbstractTaskProvider` ABC with pluggable backends (GitHub via `gh` CLI, ClickUp via REST API, Markdown via a single central file). Non-GitHub providers compose `GitHubPRDelegateMixin` so PR-review APIs still flow through `gh`.
|
|
75
75
|
- **Prompts as .md Templates**: All AI prompts live in `templates/prompts/`, not inline strings.
|
|
76
76
|
- **Synchronous Only**: No asyncio. Process-level parallelism via multiple terminals.
|
|
@@ -4,6 +4,48 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Conventional Commits](https://conventionalcommits.org/).
|
|
6
6
|
|
|
7
|
+
## [v0.33.0] — 2026-07-23
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
- replace Gemini CLI support with Antigravity CLI (bump crossby to 0.10.x) (#336) (c54af6d)
|
|
12
|
+
|
|
13
|
+
## [v0.32.0] — 2026-07-23
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
- supersede existing issue when planning splits it into multiple plan files (#331) (2f1fb93)
|
|
18
|
+
|
|
19
|
+
## [v0.31.3] — 2026-07-22
|
|
20
|
+
|
|
21
|
+
### Bug Fixes
|
|
22
|
+
|
|
23
|
+
- --mode headless still blocks on TTY AI-selection confirm prompt (#332) (3095ed7)
|
|
24
|
+
|
|
25
|
+
## [v0.31.2] — 2026-07-17
|
|
26
|
+
|
|
27
|
+
### Refactoring
|
|
28
|
+
|
|
29
|
+
- convert init_service.py into a package of focused modules (#325) (25d19ef)
|
|
30
|
+
|
|
31
|
+
## [v0.31.1] — 2026-07-17
|
|
32
|
+
|
|
33
|
+
### Bug Fixes
|
|
34
|
+
|
|
35
|
+
- remove(stale=True) misclassifies worktree as ACTIVE when provider read fails in CI (regression from #315) (#327) (83edda9)
|
|
36
|
+
|
|
37
|
+
## [v0.31.0] — 2026-07-17
|
|
38
|
+
|
|
39
|
+
### Features
|
|
40
|
+
|
|
41
|
+
- modularize implementation_service/core.py into focused submodules (#315) (97c5767)
|
|
42
|
+
|
|
43
|
+
## [v0.30.3] — 2026-07-17
|
|
44
|
+
|
|
45
|
+
### Bug Fixes
|
|
46
|
+
|
|
47
|
+
- skip self-upgrade for editable uv-tool installs (#323) (65666ec)
|
|
48
|
+
|
|
7
49
|
## [v0.30.2] — 2026-07-16
|
|
8
50
|
|
|
9
51
|
### Bug Fixes
|
|
@@ -7,7 +7,7 @@ Read this at the start of every session. Add new entries via `wade knowledge add
|
|
|
7
7
|
|
|
8
8
|
## 6e38b3aa | 2026-03-27 | implementation | Issue #233
|
|
9
9
|
|
|
10
|
-
After migrating AI tool artifacts off main (#233): The managed gitignore (get_managed_gitignore_patterns in installer.py) now includes .claude/settings.json, .cursor/cli.json, and hook config files (.cursor/hooks.json, .
|
|
10
|
+
After migrating AI tool artifacts off main (#233): The managed gitignore (get_managed_gitignore_patterns in installer.py) now includes .claude/settings.json, .cursor/cli.json, and hook config files (.cursor/hooks.json, .github/hooks/hooks.json). These were not in the managed block before. The wade repo's own .gitignore also needed manual entries for the session files because the managed block is stale (it's regenerated by wade update, which can't be run from worktrees during implementation). When working in worktrees for the wade repo, always expect untracked session files if the managed gitignore block hasn't been updated recently.
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
@@ -87,7 +87,7 @@ When editing agent session rules, check BOTH templates/skills/<name>/SKILL.md AN
|
|
|
87
87
|
|
|
88
88
|
## 1c18f1d4 | 2026-04-28 | plan | tags: delegation, yolo, headless, ai-tools
|
|
89
89
|
|
|
90
|
-
wade's headless AI delegation (mode: headless for deps and review_*) should rely on permissions.allowed_commands, not yolo. Why: (1) codex exec auto-defaults approval_policy=never, making yolo args (-a never) redundant. (2) For Claude/Copilot/
|
|
90
|
+
wade's headless AI delegation (mode: headless for deps and review_*) should rely on permissions.allowed_commands, not yolo. Why: (1) codex exec auto-defaults approval_policy=never, making yolo args (-a never) redundant. (2) For Claude/Copilot/Cursor, headless analytical tasks (read repo, emit output) don't need write permissions, so yolo over-grants. (3) Headless yolo passthrough was added in PR #146 (commit 26771d3) but worked fine before that. The init wizard prompting "Enable YOLO mode for plan review?" on a headless subprocess is confusing UX.
|
|
91
91
|
|
|
92
92
|
---
|
|
93
93
|
|
|
@@ -129,3 +129,87 @@ When splitting a wade service module into submodules, moving a function to a new
|
|
|
129
129
|
Fix: add a re-exec breadcrumb env var (WADE_SELF_UPGRADE_FROM=<old version>) so a post-re-exec process detects the version did NOT advance and stops with a warning; force a cache-bypassing fresh PyPI check for the explicit self-upgrade path; and skip yanked releases when selecting the latest version.
|
|
130
130
|
|
|
131
131
|
---
|
|
132
|
+
|
|
133
|
+
## d65003eb | 2026-07-16 | implementation | tags: testing, mocking | Issue #321
|
|
134
|
+
|
|
135
|
+
Functions imported locally inside a function body (e.g. `from wade.utils.install import detect_install_method` inside `_maybe_self_upgrade()`) must be mock-patched at their *source* module (`wade.utils.install.detect_install_method`), not at the importing module (`wade.services.init_service.detect_install_method`) — the local import re-resolves the name from the source module at call time, so patching the importer's namespace has no effect.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## c71d1a70 | 2026-07-16 | implementation | tags: pypi | Issue #321
|
|
140
|
+
|
|
141
|
+
PyPI's JSON API (pypi.org/pypi/<pkg>/json) does not expose a top-level 'yanked' flag on `info` — yanked status lives per-file inside `releases[version]`, where each file dict has a `yanked` bool. `info.version` does not account for yanking, so it can point at a release that pip/uv will refuse to install; select from `releases` and filter out versions where every file is yanked instead of trusting `info.version`.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## bcfa4bb3 | 2026-07-17 | implementation | tags: skills, prompts, architecture | Issue #314
|
|
146
|
+
|
|
147
|
+
Session prompt templates (templates/prompts/) are NOT symlinked — they are read directly by service code: plan_service.py and implementation_service/draft_pr.py (build_implementation_prompt, moved there from core.py in the #314 split). Skill files (templates/skills/) ARE symlinked into .claude/skills/. When fixing agent instructions, check BOTH the skill files AND the prompt templates.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 0bad70f3 | 2026-07-17 | implementation | tags: testing, mocking, refactoring | Issue #314
|
|
152
|
+
|
|
153
|
+
When splitting a wade service module, a module-level dependency import must stay module-level (not function-local) if any test patches it via that module (e.g. done.load_config). mock.patch resolves the attribute on the module object; a function-local import re-binds from the source module at call time, so the patch is silently ignored. Also: a moved helper imported into several modules is patched in the CALLER's namespace (e.g. find_worktree_path is patched at done./cleanup./core. depending on which function is under test), not where it is defined (_shared).
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## b7ff010c | 2026-07-17 | implementation | tags: refactoring, architecture, imports | Issue #317
|
|
158
|
+
|
|
159
|
+
When splitting a service module into a package, a constant/helper shared by a leaf submodule and an upper one must live in the LEAF, not the upper module — the upper already imports from the leaf, so hosting it upstream creates an import cycle. E.g. init_service `_COMMAND_OVERRIDE_NAMES` belongs in config_io (a leaf), not prompts_setup, since prompts_setup imports `_resolve_models` from config_io.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 129ab9bd | 2026-07-17 | plan | tags: testing, providers, error-handling | Issue #326
|
|
164
|
+
|
|
165
|
+
GitHubProvider.read_task_or_none() raises RuntimeError (not silently returns None) on any gh CLI failure that isn't a genuine 'not found' match — e.g. missing GH_TOKEN, auth, network, rate-limit. Callers relying on it as a fail-safe (e.g. classify_staleness's task_lookup_failed) must catch exceptions around the call, not just check for None.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 3045ea00 | 2026-07-17 | plan | tags: testing, mocking, ci | Issue #326
|
|
170
|
+
|
|
171
|
+
Tests that call remove(stale=True)/_remove_stale() or list_sessions() in cleanup.py must mock wade.services.implementation_service.cleanup.get_provider (not just cleanup.load_config), or they instantiate a real GitHubProvider and shell out to gh — passing locally with authenticated gh but failing in CI with no GH_TOKEN. See TestListSessions.test_gracefully_handles_issue_lookup_failures for the mocking pattern.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 702b274f | 2026-07-21 | plan | tags: prompts, cli, ux
|
|
176
|
+
|
|
177
|
+
wade/ui/prompts.py helpers such as confirm, input_prompt, select, and menu return their configured default when stdin is not a TTY; multi_select returns all items. When adding an interactive prompt in a service/CLI path, do NOT write your own non-interactive detection — just pass a sensible default and rely on this. The idiom for an auto-proceed-under-yolo confirmation is: proceed = yolo or prompts.confirm(msg, default=True).
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## c7a450ff | 2026-07-21 | implementation | tags: testing, python | Issue #330
|
|
182
|
+
|
|
183
|
+
Python's parenthesized with-statement (with (a, b, c):) does not support unpacking a list of context managers via *patches — it's a syntax error, not a runtime one. To share a list of mock.patch(...) objects across multiple tests, use contextlib.ExitStack() and call stack.enter_context(p) for each, capturing return values for assertions.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## b6ca74e5 | 2026-07-23 | plan | tags: git, gh, pr-merge | Issue #333
|
|
188
|
+
|
|
189
|
+
gh pr merge <n> --squash --delete-branch (wrapped by git_pr.merge_pr, run with cwd=repo_root) performs the remote squash-merge FIRST, then does local --delete-branch bookkeeping which resolves the cwd repo's current branch. If that clone has a detached HEAD, gh aborts with "could not determine current branch: not on any branch" AFTER the PR is already merged on GitHub — a "merged-on-GitHub-but-reported-failed" inconsistency. Any guard on repo_root HEAD state (e.g. re-attaching it) MUST run BEFORE calling merge_pr, so a fail-fast path avoids the irreversible remote merge. _merge_pr in lifecycle.py is shared by review_service.py and smart_start.py.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 9f5e5e2c | 2026-07-23 | plan | tags: crossby, ai-tools, permission-mode
|
|
194
|
+
|
|
195
|
+
crossby exposes an autonomy/permission axis orthogonal to WADE's DelegationMode (prompt/interactive/headless): pass yolo/auto/accept_edits booleans to AbstractAITool.launch()/build_launch_command(). crossby owns the precedence ladder yolo > auto > accept_edits > default > plan and does capability-aware downgrades with warnings in _autonomy_launch_args (ai_tools/base.py) — WADE forwards intent, it must not re-implement gating. auto (classifier-mediated) is Claude-only among CLIs and downgrades to accept-edits elsewhere.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## 38aa4f95 | 2026-07-23 | plan | tags: crossby, ai-tools, antigravity
|
|
200
|
+
|
|
201
|
+
crossby has two separate Antigravity adapters, easy to confuse: AIToolID.ANTIGRAVITY (GUI IDE, binary "antigravity", non-blocking/detached, no headless or yolo) and AIToolID.ANTIGRAVITY_CLI = "antigravity-cli" (terminal agent, binary "agy", blocking, supports headless --print, effort, yolo, and plan/accept-edits via --mode). The CLI one is the Gemini-CLI replacement and flows through WADE's standard terminal launch path.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## 669d0bb8 | 2026-07-23 | implementation | tags: migration, symlinks, gotcha | Issue #335
|
|
206
|
+
|
|
207
|
+
wade cross-tool skill alias dirs (.gemini/skills, .github/skills, .agents/skills, .cursor/skills) are SYMLINKS to .claude/skills, not real dirs. Cleanup/migration code must remove them via is_symlink()/unlink(), never is_dir()/rmdir(): Path.is_dir() returns False on a dangling symlink (the .claude/skills target may already be pruned earlier in the same wade update run), and os.rmdir() on a live symlink-to-dir raises NotADirectoryError. Only rmdir the real .gemini sub-dirs (hooks, policies) and guard with 'not is_symlink() and not any(iterdir())'.
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 9b40e000 | 2026-07-23 | implementation | tags: ai-tools, antigravity, testing | Issue #335
|
|
212
|
+
|
|
213
|
+
crossby's antigravity-cli adapter is permissive where the removed gemini adapter was strict: is_model_compatible() returns True for ANY model (including claude-* models), and capabilities().supports_effort is True. Consequences for wade tests: (1) a tool/model incompatibility test (resolve_model -> None) cannot use antigravity-cli — use codex, which rejects claude models; (2) capability-gated interactive wizard tests (_prompt_command_overrides) gain an extra effort prompt when the override tool is antigravity-cli, shifting mock_select index sequences vs the old gemini flow (gemini had supports_effort=False).
|
|
214
|
+
|
|
215
|
+
---
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
0bad70f3:
|
|
2
|
+
down: 0
|
|
3
|
+
stale: 0
|
|
4
|
+
up: 3
|
|
5
|
+
164c355e:
|
|
6
|
+
down: 0
|
|
7
|
+
stale: 0
|
|
8
|
+
up: 1
|
|
9
|
+
1c18f1d4:
|
|
10
|
+
down: 0
|
|
11
|
+
stale: 0
|
|
12
|
+
up: 1
|
|
13
|
+
2b4d5319:
|
|
14
|
+
down: 0
|
|
15
|
+
stale: 0
|
|
16
|
+
up: 2
|
|
17
|
+
3045ea00:
|
|
18
|
+
down: 0
|
|
19
|
+
stale: 0
|
|
20
|
+
up: 1
|
|
21
|
+
3463fbd4:
|
|
22
|
+
down: 0
|
|
23
|
+
stale: 0
|
|
24
|
+
up: 2
|
|
25
|
+
4863036c:
|
|
26
|
+
down: 0
|
|
27
|
+
stale: 0
|
|
28
|
+
up: 4
|
|
29
|
+
54326c98:
|
|
30
|
+
down: 1
|
|
31
|
+
stale: 0
|
|
32
|
+
up: 0
|
|
33
|
+
a24d65b0:
|
|
34
|
+
down: 0
|
|
35
|
+
stale: 0
|
|
36
|
+
superseded_by: c71d1a70
|
|
37
|
+
up: 1
|
|
38
|
+
b61e247e:
|
|
39
|
+
down: 0
|
|
40
|
+
stale: 0
|
|
41
|
+
superseded_by: bcfa4bb3
|
|
42
|
+
up: 4
|
|
43
|
+
b6a3a637:
|
|
44
|
+
down: 0
|
|
45
|
+
stale: 0
|
|
46
|
+
up: 1
|
|
47
|
+
cc91cd11:
|
|
48
|
+
down: 0
|
|
49
|
+
stale: 0
|
|
50
|
+
up: 3
|
|
51
|
+
cedeaad0:
|
|
52
|
+
down: 1
|
|
53
|
+
stale: 0
|
|
54
|
+
up: 1
|
|
55
|
+
d65003eb:
|
|
56
|
+
down: 0
|
|
57
|
+
stale: 0
|
|
58
|
+
up: 2
|
|
59
|
+
e2a49ac1:
|
|
60
|
+
down: 0
|
|
61
|
+
stale: 0
|
|
62
|
+
up: 3
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wade-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.33.0
|
|
4
4
|
Summary: WADE — Workflow for AI-Driven Engineering
|
|
5
5
|
Project-URL: Homepage, https://github.com/ivanviragine/wade
|
|
6
6
|
Project-URL: Repository, https://github.com/ivanviragine/wade
|
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
17
|
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
18
18
|
Requires-Python: >=3.11
|
|
19
|
-
Requires-Dist: crossby<0.
|
|
19
|
+
Requires-Dist: crossby<0.11.0,>=0.10.1
|
|
20
20
|
Requires-Dist: httpx<1.0,>=0.27
|
|
21
21
|
Requires-Dist: pydantic-settings>=2.0
|
|
22
22
|
Requires-Dist: pydantic>=2.0
|
|
@@ -45,7 +45,7 @@ Description-Content-Type: text/markdown
|
|
|
45
45
|
|
|
46
46
|
*Every Wade does the dirty work so the heroes don't have to.*
|
|
47
47
|
|
|
48
|
-
Branches, worktrees, context loading, model selection, PR creation — all the workflow friction that surrounds AI coding sessions. WADE eliminates it. Works with `Claude Code`, `Copilot`, `
|
|
48
|
+
Branches, worktrees, context loading, model selection, PR creation — all the workflow friction that surrounds AI coding sessions. WADE eliminates it. Works with `Claude Code`, `Copilot`, `Antigravity CLI`, `Codex`, and more. Run `wade init` once per project, then just point it at a GitHub *(more to come!)* issue number.
|
|
49
49
|
|
|
50
50
|
## See It in Action
|
|
51
51
|
|
|
@@ -181,6 +181,15 @@ Short aliases: `wade p` (plan), `wade i <N>` (implement), `wade r <N>` (review p
|
|
|
181
181
|
|
|
182
182
|
Most workflow commands accept `--ai <tool>`, `--model <model>`, `--effort <level>`, and `--yolo` to override configured defaults. `implement` also supports `--detach` (new terminal tab) and `--cd` (print worktree path only).
|
|
183
183
|
|
|
184
|
+
`wade plan --issue <N>` re-plans an existing issue. If the session produces a
|
|
185
|
+
single plan file, it's attached to `#N` and the issue stays open. If the
|
|
186
|
+
session decides the work should be split into several independent pieces
|
|
187
|
+
(2+ plan files), `#N` is **superseded**: a new issue + draft PR is created
|
|
188
|
+
per plan file, a comment and a `> **Superseded by ...**` banner are added to
|
|
189
|
+
`#N`, and it's closed as *not planned* (confirmed via prompt unless
|
|
190
|
+
`--yolo`/non-interactive). If any plan file fails to become an issue, `#N` is
|
|
191
|
+
left open with a warning instead of superseding on a partial split.
|
|
192
|
+
|
|
184
193
|
## Supported AI Tools
|
|
185
194
|
|
|
186
195
|
Adapters, model/effort resolution, and per-tool config (allowlists, hooks) are powered by [`crossby`](https://github.com/ivanviragine/crossby), WADE's AI-tool-integration dependency.
|
|
@@ -190,11 +199,14 @@ Adapters, model/effort resolution, and per-tool config (allowlists, hooks) are p
|
|
|
190
199
|
| [Claude Code](https://claude.com/product/claude-code) | `claude` |
|
|
191
200
|
| [Cursor](https://www.cursor.com/) | `cursor` |
|
|
192
201
|
| [GitHub Copilot](https://github.com/features/copilot/cli) | `copilot` |
|
|
193
|
-
| [Google Gemini](https://geminicli.com/) | `gemini` |
|
|
194
202
|
| [OpenAI Codex](https://developers.openai.com/codex/cli/) | `codex` |
|
|
195
203
|
| [OpenCode](https://opencode.ai/) | `opencode` |
|
|
196
204
|
| [VS Code](https://github.com/features/copilot/ai-code-editor) | `code` |
|
|
197
205
|
| [Antigravity](https://antigravity.google/) | `antigravity` |
|
|
206
|
+
| [Antigravity CLI](https://antigravity.google/) | `agy` |
|
|
207
|
+
|
|
208
|
+
> In `.wade.yml`, refer to a tool by its **config ID**, which matches the binary
|
|
209
|
+
> above except for VS Code (`vscode`) and Antigravity CLI (`antigravity-cli`).
|
|
198
210
|
|
|
199
211
|
## Task Providers
|
|
200
212
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
*Every Wade does the dirty work so the heroes don't have to.*
|
|
10
10
|
|
|
11
|
-
Branches, worktrees, context loading, model selection, PR creation — all the workflow friction that surrounds AI coding sessions. WADE eliminates it. Works with `Claude Code`, `Copilot`, `
|
|
11
|
+
Branches, worktrees, context loading, model selection, PR creation — all the workflow friction that surrounds AI coding sessions. WADE eliminates it. Works with `Claude Code`, `Copilot`, `Antigravity CLI`, `Codex`, and more. Run `wade init` once per project, then just point it at a GitHub *(more to come!)* issue number.
|
|
12
12
|
|
|
13
13
|
## See It in Action
|
|
14
14
|
|
|
@@ -144,6 +144,15 @@ Short aliases: `wade p` (plan), `wade i <N>` (implement), `wade r <N>` (review p
|
|
|
144
144
|
|
|
145
145
|
Most workflow commands accept `--ai <tool>`, `--model <model>`, `--effort <level>`, and `--yolo` to override configured defaults. `implement` also supports `--detach` (new terminal tab) and `--cd` (print worktree path only).
|
|
146
146
|
|
|
147
|
+
`wade plan --issue <N>` re-plans an existing issue. If the session produces a
|
|
148
|
+
single plan file, it's attached to `#N` and the issue stays open. If the
|
|
149
|
+
session decides the work should be split into several independent pieces
|
|
150
|
+
(2+ plan files), `#N` is **superseded**: a new issue + draft PR is created
|
|
151
|
+
per plan file, a comment and a `> **Superseded by ...**` banner are added to
|
|
152
|
+
`#N`, and it's closed as *not planned* (confirmed via prompt unless
|
|
153
|
+
`--yolo`/non-interactive). If any plan file fails to become an issue, `#N` is
|
|
154
|
+
left open with a warning instead of superseding on a partial split.
|
|
155
|
+
|
|
147
156
|
## Supported AI Tools
|
|
148
157
|
|
|
149
158
|
Adapters, model/effort resolution, and per-tool config (allowlists, hooks) are powered by [`crossby`](https://github.com/ivanviragine/crossby), WADE's AI-tool-integration dependency.
|
|
@@ -153,11 +162,14 @@ Adapters, model/effort resolution, and per-tool config (allowlists, hooks) are p
|
|
|
153
162
|
| [Claude Code](https://claude.com/product/claude-code) | `claude` |
|
|
154
163
|
| [Cursor](https://www.cursor.com/) | `cursor` |
|
|
155
164
|
| [GitHub Copilot](https://github.com/features/copilot/cli) | `copilot` |
|
|
156
|
-
| [Google Gemini](https://geminicli.com/) | `gemini` |
|
|
157
165
|
| [OpenAI Codex](https://developers.openai.com/codex/cli/) | `codex` |
|
|
158
166
|
| [OpenCode](https://opencode.ai/) | `opencode` |
|
|
159
167
|
| [VS Code](https://github.com/features/copilot/ai-code-editor) | `code` |
|
|
160
168
|
| [Antigravity](https://antigravity.google/) | `antigravity` |
|
|
169
|
+
| [Antigravity CLI](https://antigravity.google/) | `agy` |
|
|
170
|
+
|
|
171
|
+
> In `.wade.yml`, refer to a tool by its **config ID**, which matches the binary
|
|
172
|
+
> above except for VS Code (`vscode`) and Antigravity CLI (`antigravity-cli`).
|
|
161
173
|
|
|
162
174
|
## Task Providers
|
|
163
175
|
|
|
@@ -130,11 +130,11 @@ AI tool adapters, model/effort resolution primitives, the model registry, and pe
|
|
|
130
130
|
|
|
131
131
|
| What | Lives in crossby | Used from wade via |
|
|
132
132
|
|------|-------------------|---------------------|
|
|
133
|
-
| `AbstractAITool` + adapters (Claude, Cursor, Copilot,
|
|
133
|
+
| `AbstractAITool` + adapters (Claude, Cursor, Copilot, Codex, OpenCode, Antigravity, Antigravity CLI, VS Code) | `crossby.ai_tools` | `services/ai_resolution.py`, `delegation_service.py`, `review_service.py`, `plan_service.py`, `prompt_delivery.py` |
|
|
134
134
|
| `AIToolID`, `AIModel`, `ModelTier`, `TokenUsage`, `AIToolCapabilities`, `EffortLevel` | `crossby.models.ai` | re-exported from `wade.models` |
|
|
135
135
|
| Model registry (probed from CLIs, was `data/models.json`) | `crossby.data.get_models_for_tool()` | `ai_resolution.py`, `init_service.py` |
|
|
136
136
|
| Per-tool default model tiers (was `config/defaults.py`) | `crossby.config.defaults.get_defaults()` | `init_service.py` |
|
|
137
|
-
| Claude/Cursor allowlist management, Cursor/Copilot
|
|
137
|
+
| Claude/Cursor allowlist management, Cursor/Copilot hook config (was `config/*_allowlist.py`, `config/*_hooks.py`) | `crossby.config.*`, `crossby.sync.permissions` | `implementation_service/bootstrap.py`, `init_service.py` |
|
|
138
138
|
|
|
139
139
|
Wade still owns a thin `services/ai_resolution.py` rather than delegating outright: wade's `ProjectConfig.ai` uses named per-command fields (e.g. `ai.plan`), while crossby's own config expects a `commands` dict — the two shapes aren't interchangeable yet. See that module's docstring for the up-to-date status.
|
|
140
140
|
|
|
@@ -218,9 +218,8 @@ knowledge:
|
|
|
218
218
|
6. Reload config + backfill probed models
|
|
219
219
|
7. Refresh skill files
|
|
220
220
|
8. Configure AI tool allowlists (Claude via `claude_allowlist.py`, Cursor via `cursor_allowlist.py`)
|
|
221
|
-
9.
|
|
222
|
-
10.
|
|
223
|
-
11. Rebuild manifest with version
|
|
221
|
+
9. Refresh .gitignore + AGENTS.md pointer
|
|
222
|
+
10. Rebuild manifest with version
|
|
224
223
|
|
|
225
224
|
**Self-upgrade mechanism**: `utils/install.py:detect_install_method()` inspects `sys.executable` to determine how wade was installed (`uv-tool`, `pipx`, `brew`, or `editable`). On `wade update`, `self_upgrade()` runs the appropriate package manager command (e.g. `uv tool upgrade wade`), then `re_exec()` replaces the current process via `os.execv()` so the new code is loaded. Editable installs skip this naturally. Pass `--skip-self-upgrade` to bypass.
|
|
226
225
|
|
|
@@ -35,13 +35,12 @@ When `wade init` runs on this repo (self-init mode), the installer creates symli
|
|
|
35
35
|
|
|
36
36
|
.github/skills/ -> (same targets, separate symlinks)
|
|
37
37
|
.agents/skills/ -> (same targets, separate symlinks)
|
|
38
|
-
.gemini/skills/ -> (same targets, separate symlinks)
|
|
39
38
|
.cursor/skills/ -> (same targets, separate symlinks)
|
|
40
39
|
```
|
|
41
40
|
|
|
42
41
|
Note: These symlinks are created by `wade init` with `is_self_init=True`. If they don't exist, run `wade init` in this repo to create them.
|
|
43
42
|
|
|
44
|
-
**Always edit `templates/skills/<name>/SKILL.md`** — never edit files inside `.claude/skills/`, `.github/skills/`, `.agents/skills/`,
|
|
43
|
+
**Always edit `templates/skills/<name>/SKILL.md`** — never edit files inside `.claude/skills/`, `.github/skills/`, `.agents/skills/`, or `.cursor/skills/` directly. In this repo those are symlinks back to templates; in inited projects they are copies that would be overwritten by `wade update`.
|
|
45
44
|
|
|
46
45
|
In inited projects (normal init), `wade init` copies skill files (not symlinks), so agents in those projects read standalone files that don't change unless `wade update` is run.
|
|
47
46
|
|
|
@@ -76,7 +75,7 @@ The installer expands these placeholders when copying skill files to a project.
|
|
|
76
75
|
|
|
77
76
|
> **Scope: inited projects.** The skill templates in `templates/skills/` are installed into inited projects by `wade init`. They are *not* guidance for developing wade itself — they teach AI agents in target projects how to use the wade workflow. When you are developing wade, treat these files as **output artifacts** you are authoring, not as rules you follow.
|
|
78
77
|
|
|
79
|
-
Skill templates are Markdown files installed to an inited project's `.claude/skills/` by `wade init`, with symlinks from `.github/skills/`, `.agents/skills/`,
|
|
78
|
+
Skill templates are Markdown files installed to an inited project's `.claude/skills/` by `wade init`, with symlinks from `.github/skills/`, `.agents/skills/`, and `.cursor/skills/` for cross-tool discovery. They teach AI agents the wade workflow via phase-specific session skills and on-demand task skills.
|
|
80
79
|
|
|
81
80
|
### Phase-Specific Skill Architecture (for inited projects)
|
|
82
81
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "wade-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.33.0"
|
|
8
8
|
description = "WADE — Workflow for AI-Driven Engineering"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -24,7 +24,7 @@ classifiers = [
|
|
|
24
24
|
"Topic :: Software Development :: Version Control :: Git",
|
|
25
25
|
]
|
|
26
26
|
dependencies = [
|
|
27
|
-
"crossby>=0.
|
|
27
|
+
"crossby>=0.10.1,<0.11.0",
|
|
28
28
|
"typer>=0.12,<0.26",
|
|
29
29
|
"pydantic>=2.0",
|
|
30
30
|
"pydantic-settings>=2.0",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"""Plan-session file-write guard for AI tools.
|
|
3
3
|
|
|
4
4
|
Standalone script (no wade imports) that intercepts pre-tool-use hooks from
|
|
5
|
-
Claude Code, Cursor,
|
|
5
|
+
Claude Code, Cursor, and Copilot. Blocks writes to files that
|
|
6
6
|
are NOT plan artifacts.
|
|
7
7
|
|
|
8
8
|
Allowed basenames / patterns:
|
|
@@ -73,9 +73,8 @@ def _extract_file_path(data: dict[str, object]) -> str | None:
|
|
|
73
73
|
- Claude Code: tool_input.file_path or tool_input.command (for Write/Edit)
|
|
74
74
|
- Cursor: tool_input.filePath or tool_input.file_path
|
|
75
75
|
- Copilot: toolArgs (JSON string) with file/path/filePath keys
|
|
76
|
-
- Gemini: tool_input.file_path or tool_input.path
|
|
77
76
|
"""
|
|
78
|
-
# Claude Code / Cursor
|
|
77
|
+
# Claude Code / Cursor: tool_input dict
|
|
79
78
|
tool_input = data.get("tool_input") or data.get("toolInput") or {}
|
|
80
79
|
if isinstance(tool_input, dict):
|
|
81
80
|
for key in ("file_path", "filePath", "path"):
|
|
@@ -130,8 +129,8 @@ def _deny(file_path: str) -> None:
|
|
|
130
129
|
)
|
|
131
130
|
# stderr for human-readable output
|
|
132
131
|
print(msg, file=sys.stderr)
|
|
133
|
-
# stdout JSON — Claude Code strict schema: only hookSpecificOutput at root
|
|
134
|
-
#
|
|
132
|
+
# stdout JSON — Claude Code strict schema: only hookSpecificOutput at root.
|
|
133
|
+
# Exit code 2 is the block signal regardless of whether JSON is consumed.
|
|
135
134
|
result = {
|
|
136
135
|
"hookSpecificOutput": {
|
|
137
136
|
"hookEventName": "PreToolUse",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"""Worktree file-write guard for AI tools.
|
|
3
3
|
|
|
4
4
|
Standalone script (no wade imports) that intercepts pre-tool-use hooks from
|
|
5
|
-
Claude Code, Cursor,
|
|
5
|
+
Claude Code, Cursor, and Copilot. Blocks writes to files outside
|
|
6
6
|
the worktree root.
|
|
7
7
|
|
|
8
8
|
The worktree root is derived from this script's install location:
|
|
@@ -62,9 +62,8 @@ def _extract_file_path(data: dict[str, object]) -> str | None:
|
|
|
62
62
|
- Claude Code: tool_input.file_path or tool_input.path
|
|
63
63
|
- Cursor: tool_input.filePath or tool_input.file_path
|
|
64
64
|
- Copilot: toolArgs (JSON string) with file/path/filePath keys
|
|
65
|
-
- Gemini: tool_input.file_path or tool_input.path
|
|
66
65
|
"""
|
|
67
|
-
# Claude Code / Cursor
|
|
66
|
+
# Claude Code / Cursor: tool_input dict
|
|
68
67
|
tool_input = data.get("tool_input") or data.get("toolInput") or {}
|
|
69
68
|
if isinstance(tool_input, dict):
|
|
70
69
|
for key in ("file_path", "filePath", "path"):
|
|
@@ -117,8 +116,8 @@ def _deny(file_path: str, worktree_root: Path) -> None:
|
|
|
117
116
|
)
|
|
118
117
|
# stderr for human-readable output
|
|
119
118
|
print(msg, file=sys.stderr)
|
|
120
|
-
# stdout JSON — Claude Code strict schema: only hookSpecificOutput at root
|
|
121
|
-
#
|
|
119
|
+
# stdout JSON — Claude Code strict schema: only hookSpecificOutput at root.
|
|
120
|
+
# Exit code 2 is the block signal regardless of whether JSON is consumed.
|
|
122
121
|
result = {
|
|
123
122
|
"hookSpecificOutput": {
|
|
124
123
|
"hookEventName": "PreToolUse",
|
|
@@ -25,7 +25,7 @@ class DelegationRequest(BaseModel):
|
|
|
25
25
|
model: str | None = None
|
|
26
26
|
effort: str | None = None
|
|
27
27
|
cwd: Path | None = None
|
|
28
|
-
timeout: int =
|
|
28
|
+
timeout: int = 300
|
|
29
29
|
output_file: Path | None = None
|
|
30
30
|
trusted_dirs: list[str] = Field(default_factory=list)
|
|
31
31
|
allowed_commands: list[str] = Field(default_factory=list)
|
|
@@ -27,6 +27,18 @@ class TaskState(StrEnum):
|
|
|
27
27
|
CLOSED = "closed"
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
class CloseReason(StrEnum):
|
|
31
|
+
"""Typed reason for closing a task — maps to provider-specific close semantics.
|
|
32
|
+
|
|
33
|
+
GitHub renders ``NOT_PLANNED`` as a grey "closed as not planned" state,
|
|
34
|
+
distinct from the default "closed as completed". Providers without a
|
|
35
|
+
close-reason concept accept and ignore it.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
COMPLETED = "completed"
|
|
39
|
+
NOT_PLANNED = "not planned"
|
|
40
|
+
|
|
41
|
+
|
|
30
42
|
class LabelType(StrEnum):
|
|
31
43
|
"""Categories of labels managed by WADE."""
|
|
32
44
|
|
|
@@ -10,7 +10,7 @@ from abc import ABC, abstractmethod
|
|
|
10
10
|
|
|
11
11
|
from wade.models.config import ProviderConfig
|
|
12
12
|
from wade.models.review import PRComment, PRReviewStatus, ReviewThread
|
|
13
|
-
from wade.models.task import Label, Task, TaskState
|
|
13
|
+
from wade.models.task import CloseReason, Label, Task, TaskState
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class AbstractTaskProvider(ABC):
|
|
@@ -85,8 +85,11 @@ class AbstractTaskProvider(ABC):
|
|
|
85
85
|
"""Update task title and/or body."""
|
|
86
86
|
|
|
87
87
|
@abstractmethod
|
|
88
|
-
def close_task(self, task_id: str) -> Task:
|
|
89
|
-
"""Close a task.""
|
|
88
|
+
def close_task(self, task_id: str, reason: CloseReason | None = None) -> Task:
|
|
89
|
+
"""Close a task, optionally with a typed reason (e.g. GitHub's "not planned").
|
|
90
|
+
|
|
91
|
+
Providers without a close-reason concept accept and ignore ``reason``.
|
|
92
|
+
"""
|
|
90
93
|
|
|
91
94
|
@abstractmethod
|
|
92
95
|
def comment_on_task(self, task_id: str, body: str) -> None:
|
|
@@ -14,6 +14,7 @@ import structlog
|
|
|
14
14
|
|
|
15
15
|
from wade.models.config import ProviderConfig
|
|
16
16
|
from wade.models.task import (
|
|
17
|
+
CloseReason,
|
|
17
18
|
Label,
|
|
18
19
|
Task,
|
|
19
20
|
TaskState,
|
|
@@ -219,8 +220,12 @@ class ClickUpProvider(GitHubPRDelegateMixin, AbstractTaskProvider):
|
|
|
219
220
|
|
|
220
221
|
return self.read_task(task_id)
|
|
221
222
|
|
|
222
|
-
def close_task(self, task_id: str) -> Task:
|
|
223
|
-
"""Close a task by setting its status to 'closed'.
|
|
223
|
+
def close_task(self, task_id: str, reason: CloseReason | None = None) -> Task:
|
|
224
|
+
"""Close a task by setting its status to 'closed'.
|
|
225
|
+
|
|
226
|
+
ClickUp has no close-reason concept — ``reason`` is accepted for
|
|
227
|
+
interface parity with other providers and ignored.
|
|
228
|
+
"""
|
|
224
229
|
self._client.put(
|
|
225
230
|
f"/api/v2/task/{task_id}",
|
|
226
231
|
json={"status": "closed"},
|
|
@@ -31,6 +31,7 @@ from wade.models.review import (
|
|
|
31
31
|
filter_unresolved_threads,
|
|
32
32
|
)
|
|
33
33
|
from wade.models.task import (
|
|
34
|
+
CloseReason,
|
|
34
35
|
Label,
|
|
35
36
|
Task,
|
|
36
37
|
TaskState,
|
|
@@ -269,10 +270,13 @@ class GitHubProvider(AbstractTaskProvider):
|
|
|
269
270
|
|
|
270
271
|
return self.read_task(task_id)
|
|
271
272
|
|
|
272
|
-
def close_task(self, task_id: str) -> Task:
|
|
273
|
-
"""Close an issue."""
|
|
274
|
-
|
|
275
|
-
|
|
273
|
+
def close_task(self, task_id: str, reason: CloseReason | None = None) -> Task:
|
|
274
|
+
"""Close an issue, optionally with a reason (e.g. "not planned")."""
|
|
275
|
+
cmd = ["gh", "issue", "close", task_id]
|
|
276
|
+
if reason is not None:
|
|
277
|
+
cmd.extend(["--reason", reason.value])
|
|
278
|
+
run(cmd, check=True, retries=3)
|
|
279
|
+
logger.info("github.issue_closed", number=task_id, reason=reason.value if reason else None)
|
|
276
280
|
return self.read_task(task_id)
|
|
277
281
|
|
|
278
282
|
def comment_on_task(self, task_id: str, body: str) -> None:
|