wade-cli 1.2.4__tar.gz → 1.2.6__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-1.2.4 → wade_cli-1.2.6}/AGENTS.md +4 -2
- {wade_cli-1.2.4 → wade_cli-1.2.6}/CHANGELOG.md +12 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/PKG-INFO +20 -15
- {wade_cli-1.2.4 → wade_cli-1.2.6}/README.md +18 -13
- {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/architecture.md +10 -6
- {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/native-cli-plan-verification.md +33 -2
- {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/testing.md +8 -2
- {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/workflows-and-skills.md +2 -2
- {wade_cli-1.2.4 → wade_cli-1.2.6}/pyproject.toml +2 -2
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/probe_native_plan_handoff.py +4 -3
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/__init__.py +1 -1
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/plan_service.py +25 -1
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/plan.md +1 -1
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_plan_contract.py +18 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_plan_service.py +13 -0
- wade_cli-1.2.6/tests/unit/test_services/test_plan_startup_events.py +82 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_crossby_contract.py +17 -1
- {wade_cli-1.2.4 → wade_cli-1.2.6}/uv.lock +214 -5
- {wade_cli-1.2.4 → wade_cli-1.2.6}/.gitattributes +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/.github/workflows/auto-version.yml +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/.github/workflows/ci.yml +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/.github/workflows/pr-title-lint.yml +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/.github/workflows/publish.yml +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/.github/workflows/release.yml +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/.gitignore +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/.pre-commit-config.yaml +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/.wade.yml +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/CONTRIBUTING.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/KNOWLEDGE.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/KNOWLEDGE.ratings.jsonl +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/assets/wade.png +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/docker-compose.e2e.yml +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/crossby-native-planning-checkpoint.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/documentation-policies.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/extending.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/skills-system.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/install.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/auto_version.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/changelog.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/check-all.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/check.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/fmt.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/hooks/pre-push +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/install-hooks.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/release.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/setup-worktree.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/test-concurrency.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/test-e2e-docker.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/test-e2e.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/test-live-ai-taskr.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/test-live-ai.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/test-live-gh.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/test.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/__main__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/admin.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/autocomplete.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/deps_session.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/hook.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/implementation_session.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/knowledge.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/main.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/plan_session.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/review.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/review_pr_comments_session.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/session.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/session_shared.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/skills.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/task.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/worktree.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/config/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/config/loader.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/config/migrations.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/config/schema.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/branch.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/hooks.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/pr.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/repo.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/stash.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/sync.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/worktree.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/hooks/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/hooks/cli.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/hooks/policies.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/logging/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/logging/context.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/logging/setup.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/batch.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/config.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/delegation.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/deps.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/events.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/hooks.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/interactive_plan.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/permission.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/plan_bundle.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/readiness.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/review.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/review_cycle.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/session.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/session_manifest.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/skill.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/task.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/workflow.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/worktree.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/providers/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/providers/_pr_delegate.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/providers/base.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/providers/clickup.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/providers/github.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/providers/markdown.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/providers/registry.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/ai_resolution.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/batch_review_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/bot_trigger.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/check_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/delegation_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/deps_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/documentation_receipt_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/_shared.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/batch.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/bootstrap.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/cleanup.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/core.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/done.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/draft_pr.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/lifecycle.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/sync.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/usage_tracking.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/auth.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/commands.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/config_io.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/manifest.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/migrations.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/prompts_ai.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/prompts_setup.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/shell.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/interactive_plan_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/knowledge_recovery.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/knowledge_search.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/knowledge_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/native_plan_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/prompt_delivery.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/review_cycle_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/review_delegation_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/review_record_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/review_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/review_settle.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/session_composition_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/skill_diagnostics_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/skill_invocation_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/smart_start.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/task_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/catalog.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/discovery.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/doc_targets.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/installer.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/materializer.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/pointer.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/resolver.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/validation.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/ui/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/ui/console.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/ui/prompts.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/body_markers.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/clipboard.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/conventional.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/filelock.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/gitref.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/http.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/install.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/knowledge_file.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/markdown.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/markers.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/paths.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/plan_validation.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/process.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/runtime_env.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/safe_state.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/slug.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/stale_base.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/templates.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/terminal.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/token_usage_markdown.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/update_check.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/agents-pointer.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/hooks/commit-msg +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/hooks/pre-commit +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/hooks/pre-push +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/deps-analysis.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/implement-context.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/plan-session.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-batch.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-code.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-finding-admission.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-plan.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-pr-comments.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-result-batch.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-result-code.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-result-deps.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-result-full-branch.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-result-implementation.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-result-plan.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-result-pr-comments.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/session-start-implement.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/session-start-plan.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/session-start-review.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/setup-worktree.sh.example +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/batch-review/SKILL.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/code-review/SKILL.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/dependency-analysis/SKILL.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/feedback-fix-review/SKILL.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/implementation/SKILL.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/knowledge/SKILL.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/plan-review/SKILL.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/planning/SKILL.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/review-comments/SKILL.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/task/SKILL.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/task/examples.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/task/plan-format.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/task/reference/session-summary-format.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/statusline-command.sh +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/_partials/completion.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/_partials/documentation-step.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/_partials/interaction-policy.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/_partials/knowledge-step.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/_partials/review-budget.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/implementation.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/reference/documentation.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/reference/new-plan.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/reference/plan-output-contract.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/reference/pr-summary-format.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/reference/recovery.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/reference/session-summary-format.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/reference/tracking-issues.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/review-pr-comments.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/concurrency/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/concurrency/test_batch_multi_pr.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/concurrency/test_knowledge_merge.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/concurrency/test_lock_retry.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/concurrency/test_stash_race.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/conftest.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/_support.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/conftest.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/mock_gh_script.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_admin_contract.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_check_contract.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_implement_work_done_contract.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_knowledge_contract.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_mock_gh_contract.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_review_contract.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_smart_start_contract.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_task_contract.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_work_sync_list_contract.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/fixtures/live/taskr_header_hi_body.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/fixtures/live/taskr_header_howdy_body.md +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/fixtures/transcripts/claude_session.txt +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/fixtures/transcripts/codex_session.txt +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/fixtures/transcripts/copilot_session.txt +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/fixtures/transcripts/generic_session.txt +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_autostash.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_check.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_dynamic_skill_sessions.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_git.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_implementation_lifecycle.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_init.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_knowledge.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_markdown_provider.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_skill_context_budget.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_skill_install.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/live/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/live/test_wade_live_ai.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/live/test_wade_live_ai_taskr.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/live/test_wade_live_gh.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/test_cli_basics.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/conftest.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_autocomplete.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_done_doc_pass_advisory.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_done_review_hint.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_knowledge_cli.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_review_cli.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_session_subapps.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_shell_init.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_skills_session_cli.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_task_cli.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_work_ai_flags.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_work_cli.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_config/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_config/test_bot_review_config.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_config/test_dynamic_skill_config.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_config/test_loader.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_config/test_merge_strategy_migration.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_config/test_migrations.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_config/test_migrations_atomic.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_console.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_effort.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_all_patches_present.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_branch_list.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_branch_slugify.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_detached_worktree.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_is_merged_into.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_main_checkout_root.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_merge_count.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_pr_base.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_pr_lookup.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_pr_retry.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_pr_title.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_repo.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_reset_branch.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_scaffold_commit.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_stash_drop.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_sync_conflicted_files.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_tip_commit_is_empty.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_worktree_remove.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_hooks/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_hooks/test_hook_cli.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_hooks/test_policies.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_hooks/test_post_tool_use.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_hooks/test_session_start.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_batch.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_config_models.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_delegation.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_deps_models.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_deps_partition.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_review.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_review_expectation.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_task_models.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_workflow_models.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_permission_mode.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_providers/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_providers/test_clickup.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_providers/test_github.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_providers/test_github_pr.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_providers/test_markdown.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_scripts/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_scripts/test_changelog.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_ai_resolution.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_batch_build_cmd.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_batch_pr_index.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_batch_review_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_bootstrap_allowlist.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_bootstrap_guard_matcher.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_bootstrap_hook_timeout.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_bootstrap_post_tool_use.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_bootstrap_pre_push.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_bootstrap_session_start.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_bot_trigger.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_catchup.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_catchup_reconcile.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_check.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_cleanup_loss_guard.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_codex_worktree_launch_context.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_delegation_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_deps_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_documentation_receipt.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_done_gates.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_done_idempotent.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_done_plan_flag.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_done_pr_title_sync.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_draft_pr_base_fetch.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_draft_pr_retarget.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_implementation_done_sync.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_implementation_launch_context.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_implementation_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_implementation_service_resume.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_init.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_init_shell_integration.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_interactive_plan_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_knowledge_recovery.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_knowledge_search.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_knowledge_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_managed_git_hooks.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_native_plan_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_no_direct_git.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_poll_for_reviews.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_post_implementation_lifecycle.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_pr_lookup_guards.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_pr_summary_path.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_pre_push_backstop.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_preserve_session_data.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_prompt_delivery.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_push_recovery.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_resolve_task_branch.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_resume_autonomy.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_review_cycle_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_review_delegation_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_review_receipts.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_review_records.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_review_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_review_status_block.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_skill_diagnostics_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_skill_invocation_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_smart_start.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_smart_start_resume.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_stale_base_surface.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_sync_base_branch.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_task_service.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_tracked_managed_files.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_worktree_gitignore.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_doc_targets.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_dynamic_skills.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_generic_builtin_boundaries.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_knowledge_attributes.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_managed_gitignore.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_pointer.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_review_budget_partial.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/__init__.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_body_markers.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_conventional.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_filelock.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_gitref.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_http.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_install.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_markdown.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_markers.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_plan_validation.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_process.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_prompts.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_runtime_env.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_slug.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_stale_base.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_terminal.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_terminal_launch.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_update_check.py +0 -0
- {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_yolo.py +0 -0
|
@@ -93,8 +93,10 @@ No circular dependencies. Models are pure data. Services orchestrate. **Never im
|
|
|
93
93
|
AI tool adapters are not part of this repo — they live in the external [`crossby`](https://github.com/ivanviragine/crossby) package (`pyproject.toml`). See `docs/dev/architecture.md` for what moved there.
|
|
94
94
|
|
|
95
95
|
Native planning prefers Crossby's ordinary interactive launch with native Plan
|
|
96
|
-
mode and supported approval flags.
|
|
97
|
-
|
|
96
|
+
mode and supported approval flags. For deferred startup (currently Codex), WADE
|
|
97
|
+
handles Crossby's typed ready/submitted events and sends the task exactly once;
|
|
98
|
+
Crossby owns `/plan` and terminal mechanics. The public collected-session API
|
|
99
|
+
remains the fallback for adapters without terminal Plan support. WADE owns explicit file/stdin
|
|
98
100
|
handoff, review receipts bound to current content and frozen skills, validation,
|
|
99
101
|
knowledge handoff, and task persistence; native flags/protocols stay upstream.
|
|
100
102
|
Update the tracked `uv.lock` and Crossby contract tripwire with dependency
|
|
@@ -4,6 +4,18 @@ 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
|
+
## [v1.2.6] — 2026-09-23
|
|
8
|
+
|
|
9
|
+
### Chores
|
|
10
|
+
|
|
11
|
+
- adopt Crossby 0.36 model catalogs and defaults (#517) (cc9ae47)
|
|
12
|
+
|
|
13
|
+
## [v1.2.5] — 2026-09-16
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
- launch Codex native UI with deferred prompt delivery (#514) (8424a77)
|
|
18
|
+
|
|
7
19
|
## [v1.2.4] — 2026-09-16
|
|
8
20
|
|
|
9
21
|
### Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: wade-cli
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.6
|
|
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.37.0,>=0.36.0
|
|
20
20
|
Requires-Dist: httpx<1.0,>=0.27
|
|
21
21
|
Requires-Dist: pydantic-settings>=2.0
|
|
22
22
|
Requires-Dist: pydantic>=2.0
|
|
@@ -280,11 +280,12 @@ Most workflow commands accept `--ai <tool>`, `--model <model>`, `--effort <level
|
|
|
280
280
|
|
|
281
281
|
## Planning & base branches
|
|
282
282
|
|
|
283
|
-
`wade plan` launches **Claude, Cursor, Copilot, OpenCode,
|
|
283
|
+
`wade plan` launches **Claude, Cursor, Copilot, OpenCode, Antigravity CLI, and Codex**
|
|
284
284
|
in their own interactive terminal, with **native Plan mode active before the
|
|
285
285
|
first task turn**. You keep the tool's UI, questions, and conversation. Crossby
|
|
286
|
-
validates native support and translates approval flags
|
|
287
|
-
`/plan
|
|
286
|
+
validates native support and translates approval flags. For Codex, Crossby
|
|
287
|
+
submits `/plan` first and WADE sends the task on its ready event. Native questions
|
|
288
|
+
and subsequent interaction stay in the tool.
|
|
288
289
|
|
|
289
290
|
Use `--permission-mode` (or `--yolo`) for the native approval policy:
|
|
290
291
|
|
|
@@ -295,6 +296,7 @@ Use `--permission-mode` (or `--yolo`) for the native approval policy:
|
|
|
295
296
|
| Copilot | `default`, `accept-edits`, `yolo` |
|
|
296
297
|
| OpenCode | `default`, `yolo` |
|
|
297
298
|
| Antigravity CLI | `default`, `yolo` |
|
|
299
|
+
| Codex CLI | `default`, `accept-edits`, `auto`, `yolo` |
|
|
298
300
|
|
|
299
301
|
Unsupported combinations fail before creating a planning worktree. These are
|
|
300
302
|
native approval settings, not permission to implement the plan. The later
|
|
@@ -319,20 +321,23 @@ including an explicit empty list when appropriate. The parent revalidates the
|
|
|
319
321
|
completed handoff after exit, then creates tasks and draft PRs. Failed or missing
|
|
320
322
|
handoffs retain output and create no tasks.
|
|
321
323
|
|
|
322
|
-
**Codex
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
324
|
+
**Codex requires CLI 0.154.x and a POSIX terminal (macOS/Linux).** Crossby's
|
|
325
|
+
current startup adapter waits for the rendered Plan indicator before WADE sends
|
|
326
|
+
the initial task; unknown versions or an unrecognized startup screen fail
|
|
327
|
+
without retrying the task. This temporary terminal adapter can be replaced by a
|
|
328
|
+
native launch flag when Codex provides one. WADE requires the task-submitted
|
|
329
|
+
event before collecting the explicit reviewed handoff. Codex can submit plan
|
|
330
|
+
Markdown through `--from-stdin`; no native file destination is assumed.
|
|
331
|
+
|
|
332
|
+
All native terminals now use the ordinary sandbox default (off), including Codex;
|
|
333
|
+
use `--sandbox` or `ai.plan.sandbox: true` to retain confinement. The retained
|
|
334
|
+
collector fallback has its own safe default (on). Explicit `--sandbox`, `--network-access` /
|
|
330
335
|
`--no-network-access`, and `--trusted-dir` require support from the selected tool.
|
|
331
336
|
No network flag adds no network grant and does not promise isolation.
|
|
332
337
|
`--approval-policy on-request|untrusted|never` and `--timeout` are collector
|
|
333
338
|
settings; interactive terminals use `--permission-mode` and have no time limit.
|
|
334
|
-
Set `ai.plan.mode` to `interactive` or leave it unset for native terminals
|
|
335
|
-
|
|
339
|
+
Set `ai.plan.mode` to `interactive` or leave it unset for native terminals.
|
|
340
|
+
GUI launchers remain unsupported for planning.
|
|
336
341
|
|
|
337
342
|
Authentication, model availability, and successful handoff are runtime checks.
|
|
338
343
|
Native terminal output is retained for recovery; usage is reported only when
|
|
@@ -244,11 +244,12 @@ Most workflow commands accept `--ai <tool>`, `--model <model>`, `--effort <level
|
|
|
244
244
|
|
|
245
245
|
## Planning & base branches
|
|
246
246
|
|
|
247
|
-
`wade plan` launches **Claude, Cursor, Copilot, OpenCode,
|
|
247
|
+
`wade plan` launches **Claude, Cursor, Copilot, OpenCode, Antigravity CLI, and Codex**
|
|
248
248
|
in their own interactive terminal, with **native Plan mode active before the
|
|
249
249
|
first task turn**. You keep the tool's UI, questions, and conversation. Crossby
|
|
250
|
-
validates native support and translates approval flags
|
|
251
|
-
`/plan
|
|
250
|
+
validates native support and translates approval flags. For Codex, Crossby
|
|
251
|
+
submits `/plan` first and WADE sends the task on its ready event. Native questions
|
|
252
|
+
and subsequent interaction stay in the tool.
|
|
252
253
|
|
|
253
254
|
Use `--permission-mode` (or `--yolo`) for the native approval policy:
|
|
254
255
|
|
|
@@ -259,6 +260,7 @@ Use `--permission-mode` (or `--yolo`) for the native approval policy:
|
|
|
259
260
|
| Copilot | `default`, `accept-edits`, `yolo` |
|
|
260
261
|
| OpenCode | `default`, `yolo` |
|
|
261
262
|
| Antigravity CLI | `default`, `yolo` |
|
|
263
|
+
| Codex CLI | `default`, `accept-edits`, `auto`, `yolo` |
|
|
262
264
|
|
|
263
265
|
Unsupported combinations fail before creating a planning worktree. These are
|
|
264
266
|
native approval settings, not permission to implement the plan. The later
|
|
@@ -283,20 +285,23 @@ including an explicit empty list when appropriate. The parent revalidates the
|
|
|
283
285
|
completed handoff after exit, then creates tasks and draft PRs. Failed or missing
|
|
284
286
|
handoffs retain output and create no tasks.
|
|
285
287
|
|
|
286
|
-
**Codex
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
288
|
+
**Codex requires CLI 0.154.x and a POSIX terminal (macOS/Linux).** Crossby's
|
|
289
|
+
current startup adapter waits for the rendered Plan indicator before WADE sends
|
|
290
|
+
the initial task; unknown versions or an unrecognized startup screen fail
|
|
291
|
+
without retrying the task. This temporary terminal adapter can be replaced by a
|
|
292
|
+
native launch flag when Codex provides one. WADE requires the task-submitted
|
|
293
|
+
event before collecting the explicit reviewed handoff. Codex can submit plan
|
|
294
|
+
Markdown through `--from-stdin`; no native file destination is assumed.
|
|
295
|
+
|
|
296
|
+
All native terminals now use the ordinary sandbox default (off), including Codex;
|
|
297
|
+
use `--sandbox` or `ai.plan.sandbox: true` to retain confinement. The retained
|
|
298
|
+
collector fallback has its own safe default (on). Explicit `--sandbox`, `--network-access` /
|
|
294
299
|
`--no-network-access`, and `--trusted-dir` require support from the selected tool.
|
|
295
300
|
No network flag adds no network grant and does not promise isolation.
|
|
296
301
|
`--approval-policy on-request|untrusted|never` and `--timeout` are collector
|
|
297
302
|
settings; interactive terminals use `--permission-mode` and have no time limit.
|
|
298
|
-
Set `ai.plan.mode` to `interactive` or leave it unset for native terminals
|
|
299
|
-
|
|
303
|
+
Set `ai.plan.mode` to `interactive` or leave it unset for native terminals.
|
|
304
|
+
GUI launchers remain unsupported for planning.
|
|
300
305
|
|
|
301
306
|
Authentication, model availability, and successful handoff are runtime checks.
|
|
302
307
|
Native terminal output is retained for recovery; usage is reported only when
|
|
@@ -197,9 +197,13 @@ Adding support for a new AI tool means contributing an adapter to crossby, not t
|
|
|
197
197
|
`plan_service.plan()` resolves the final confirmed selection before worktree or
|
|
198
198
|
provider mutations. An adapter advertising `supports_plan_mode` uses ordinary
|
|
199
199
|
`launch(plan_mode=True)` after `validate_plan_mode_request()`. Crossby owns
|
|
200
|
-
native flags, version gates, and approval compatibility.
|
|
200
|
+
native flags, version gates, and approval compatibility. For adapters declaring
|
|
201
|
+
`supports_ready_event`, WADE uses the public `on_event` callback: `PLAN_READY`
|
|
202
|
+
submits the task through `session.send_message()` exactly once and
|
|
203
|
+
`MESSAGE_SUBMITTED` confirms delivery before handoff collection. Crossby owns
|
|
204
|
+
Codex's `/plan` activation and PTY; WADE never reads screen text. WADE forwards the
|
|
201
205
|
requested autonomy tier without downgrading unsupported Plan combinations.
|
|
202
|
-
Claude, Cursor, Copilot, OpenCode,
|
|
206
|
+
Claude, Cursor, Copilot, OpenCode, Antigravity CLI, and Codex use this path.
|
|
203
207
|
Questions and the full terminal UI remain native. Explicit unsupported sandbox,
|
|
204
208
|
network, trusted-directory, timeout, or transport settings fail before launch.
|
|
205
209
|
The default sandbox is off, as for ordinary interactive launches.
|
|
@@ -223,7 +227,7 @@ Nonzero exits and absent/stale handoffs retain output without creating tasks.
|
|
|
223
227
|
Native terminal output can supply adapter-parsed usage; the WADE handoff ID is
|
|
224
228
|
never presented as a native CLI session ID.
|
|
225
229
|
|
|
226
|
-
Tools without terminal Plan support
|
|
230
|
+
Tools without terminal Plan support retain the public
|
|
227
231
|
`PlanSessionRequest` → `preflight_plan_session()` → `run_plan_session()` flow.
|
|
228
232
|
`native_plan_service` consumes Crossby's complete-session metadata, required
|
|
229
233
|
`PlanCommandPolicy` (`wade *` plus configured patterns), and supported path policy.
|
|
@@ -1086,7 +1090,7 @@ models: # values below are crossby's claude defaults, not w
|
|
|
1086
1090
|
easy: claude-haiku-4.5
|
|
1087
1091
|
medium: claude-sonnet-5
|
|
1088
1092
|
complex: claude-sonnet-5
|
|
1089
|
-
very_complex: claude-opus-5
|
|
1093
|
+
very_complex: claude-opus-5.5
|
|
1090
1094
|
provider:
|
|
1091
1095
|
name: github
|
|
1092
1096
|
hooks:
|
|
@@ -1273,9 +1277,9 @@ exactly as before #448. See knowledge `cc91cd11` for the generalized principle.
|
|
|
1273
1277
|
|
|
1274
1278
|
The tier values `wade init` writes are **not wade constants** — `init_service/config_io.py::_resolve_models()` seeds them from `crossby.config.defaults.get_defaults(tool)`, so **bumping the crossby pin changes what newly initialized projects get**. The example above shows crossby's `claude` defaults at the currently pinned version; run `get_defaults()` for the authoritative set rather than trusting a doc snapshot, and re-check this block on every crossby bump. A bump does **not** rewrite tiers an existing `.wade.yml` already sets: `wade update` re-resolves the defaults and calls `_patch_config` without `force`, which backfills only *absent* tiers. So a fresh `wade init` picks up the new defaults wholesale, while an existing project changes only where it left a tier unset.
|
|
1275
1279
|
|
|
1276
|
-
**Per-command AI tool and model overrides**: The `ai` section supports `plan`, `deps`, `implement`, `review_plan`, `review_implementation`, `review_batch`, and `review_pr_comments` sub-sections (`AI_COMMAND_NAMES` in `models/config.py`), with optional `tool`, `model`, `mode`, `effort`, `enabled`, `yolo`, `permission_mode`, `sandbox`, and `timeout` keys as applicable. `sandbox` (global `ai.sandbox` or per-command) is the cross-tool AI-runtime sandbox profile resolved by `resolve_sandbox()`: CLI `--sandbox`/`--no-sandbox` > per-command > global > **`False` (unrestricted)** for ordinary launches. Native terminal planning uses that same default;
|
|
1280
|
+
**Per-command AI tool and model overrides**: The `ai` section supports `plan`, `deps`, `implement`, `review_plan`, `review_implementation`, `review_batch`, and `review_pr_comments` sub-sections (`AI_COMMAND_NAMES` in `models/config.py`), with optional `tool`, `model`, `mode`, `effort`, `enabled`, `yolo`, `permission_mode`, `sandbox`, and `timeout` keys as applicable. `sandbox` (global `ai.sandbox` or per-command) is the cross-tool AI-runtime sandbox profile resolved by `resolve_sandbox()`: CLI `--sandbox`/`--no-sandbox` > per-command > global > **`False` (unrestricted)** for ordinary launches. Native terminal planning uses that same default; the collector fallback keeps its safe posture. Both preserve explicit sandbox requirements. Network access is unconditionally on for ordinary non-plan launches; planning exposes an independent default-off request — see the "AI runtime sandbox profile" section above. `timeout` bounds a headless subprocess (seconds). When **unset**, the review/deps services compute the budget with `effective_timeout` (`delegation_service.py`, #366): it scales from **payload bytes + reasoning effort** — `scaled_timeout` starts at a **600s floor** (`TIMEOUT_FLOOR`, covers CLI cold-start + a small high-effort run), adds ~0.0075 s/byte of prompt, multiplies high/xhigh/max effort by 1.5–1.75×, and clamps to a **1500s ceiling** (`TIMEOUT_CEILING`). A headless timeout is **not** discarded: `run` (`utils/process.py`) decodes and reattaches the partial stdout (bytes even under `text=True`), `_delegate_headless` returns it as `feedback` with `DelegationResult.timed_out=True`, and wade **retries once** at a longer budget (`extended_timeout`, 1.5×) — bounding the *sum* of both legs to `TOTAL_TIMEOUT_CAP` (`TIMEOUT_CEILING + TIMEOUT_CEILING * TIMEOUT_RETRY_MULTIPLIER`, ~3750s / 62.5 min) so the worst case is predictable while the retry always gets the full multiplier, never a shorter budget than the attempt that just timed out (#366 review). The pre-launch advisory — now also printed by `deps_service.analyze_deps` before a headless run, not just the review commands (#366 review) — announces that worst-case total. A crash (`CommandError` / non-zero exit) is never retried and never flagged `timed_out`. Setting `ai.<cmd>.timeout` **explicitly** is a deliberate override: it is honored verbatim and **bypasses scaling and the retry math** — the escape hatch for orchestrators with a hard tool-timeout (set it below the harness limit). The fallback chain (tool/model) is: CLI `--ai`/`--model` flag -> command-specific config -> global `default_tool`. This is implemented in `ProjectConfig.get_ai_tool(command)` and `ProjectConfig.get_model(command)`. When `mode` is omitted, `review_plan` and `review_implementation` default to `prompt`, while `review_batch` defaults to `interactive`. `review_pr_comments` (#389) governs the **auto-launched review session** (post-`done` "Wait for reviews" → comments land → `review_service.start`): it resolves that session's tool, model, effort, and autonomy tier under its own key rather than inheriting `ai.implement.*`. The inherited implementation-session `tool` / `model` / `permission_mode` are honored only when the user set them *explicitly* (`--ai` / `--model` / `--permission-mode` / `--yolo`); the implementation flow forwards its already-*resolved* concrete values (never `None`), which would otherwise short-circuit the resolvers and shadow `ai.review_pr_comments` — so a merely config/default-derived value is dropped and the review config (then global `ai.*`) governs.
|
|
1277
1281
|
|
|
1278
|
-
**Permission (autonomy) mode vs. delegation `mode` — two orthogonal axes**: The `mode` key (`DelegationMode`: `prompt`/`interactive`/`headless`, `models/delegation.py`) governs *how* a tool is dispatched. `permission_mode` (`PermissionMode`: `default`/`accept-edits`/`auto`/`yolo`, `models/permission.py`) governs *how much* the tool may do without prompting — the autonomy axis crossby exposes via the `yolo`/`auto`/`accept_edits` launch booleans. Do **not** conflate them: they live in separate modules on purpose. Resolution (`resolve_permission_mode()` in `ai_resolution.py`) follows CLI `--permission-mode` > `--yolo` alias > command config > global config > `default`; `permission_mode` wins over the legacy `yolo` alias at any level, and `get_yolo()`/`resolve_yolo()` are thin shims that derive from the resolved mode so the alias has a single source of truth. WADE forwards only the *requested* tier and does **not** gate on per-tool capability — crossby owns capability-aware downgrades and warnings (`_autonomy_launch_args`), so `auto` on a tool without native auto support can downgrade to `accept-edits` instead of WADE silently disabling it. The headless delegation path always forces `default` (no autonomy grant) regardless of config, since `deps`/`review_plan`/`review_implementation`/`review_batch` are read/analytical; `review_pr_comments` is the exception — it launches an *interactive* session and honors its configured `ai.review_pr_comments.permission_mode`. Native terminal planning forwards the requested tier through Crossby's Plan-mode validator and ordinary launch; unsupported combinations fail instead of downgrading. Codex
|
|
1282
|
+
**Permission (autonomy) mode vs. delegation `mode` — two orthogonal axes**: The `mode` key (`DelegationMode`: `prompt`/`interactive`/`headless`, `models/delegation.py`) governs *how* a tool is dispatched. `permission_mode` (`PermissionMode`: `default`/`accept-edits`/`auto`/`yolo`, `models/permission.py`) governs *how much* the tool may do without prompting — the autonomy axis crossby exposes via the `yolo`/`auto`/`accept_edits` launch booleans. Do **not** conflate them: they live in separate modules on purpose. Resolution (`resolve_permission_mode()` in `ai_resolution.py`) follows CLI `--permission-mode` > `--yolo` alias > command config > global config > `default`; `permission_mode` wins over the legacy `yolo` alias at any level, and `get_yolo()`/`resolve_yolo()` are thin shims that derive from the resolved mode so the alias has a single source of truth. WADE forwards only the *requested* tier and does **not** gate on per-tool capability — crossby owns capability-aware downgrades and warnings (`_autonomy_launch_args`), so `auto` on a tool without native auto support can downgrade to `accept-edits` instead of WADE silently disabling it. The headless delegation path always forces `default` (no autonomy grant) regardless of config, since `deps`/`review_plan`/`review_implementation`/`review_batch` are read/analytical; `review_pr_comments` is the exception — it launches an *interactive* session and honors its configured `ai.review_pr_comments.permission_mode`. Native terminal planning forwards the requested tier through Crossby's Plan-mode validator and ordinary launch; unsupported combinations fail instead of downgrading. Codex uses native terminal startup events and supports all four approval tiers. The retained collector fallback uses parent-only `default`/`yolo` and a separate native approval policy. Ordinary invalid autonomy configuration warns and falls back to `default`. Every ordinary launch command (`implement`, `implement-batch`, `review pr-comments`, `review plan`/`implementation`/`batch`, `task deps`, and the delegation paths) exposes `--yolo`/`--permission-mode` and resolves + forwards the tier; `confirm_ai_selection()` (`ai_resolution.py`) **always displays** the resolved tool/model/effort/permission mode with a per-tier descriptor (`permission.describe_permission_mode`) before its skip guard, so the mode surfaces on every path (TTY, non-TTY, headless, all-flags-explicit) and what is shown always equals what is applied. For the read-only headless paths (`deps`/`review_*` in headless mode), the service computes the *effective* mode as `default` and uses that single value for both display and the `DelegationRequest`, mirroring the `delegation_service` headless force-default rule. In addition, a completed non-zero headless exit preserves trimmed stdout and appends a clearly labeled stderr tail (the final 20 non-empty lines, capped at 4,000 characters, with truncation labeled); only failures with neither stream retain the generic no-output fallback.
|
|
1279
1283
|
|
|
1280
1284
|
**Worktree hooks**: The `hooks` section lets projects run setup automatically when a worktree is created. `post_worktree_create` points to a script that runs in the new worktree (e.g., installing dependencies). `copy_to_worktree` lists files to copy from the project root into the worktree before the hook runs (e.g., `.env`). Hook failures are non-fatal — a warning is logged and the session continues.
|
|
1281
1285
|
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Verified on 2026-09-16 with the published Crossby 0.32.1 wheel. Upstream approval
|
|
4
4
|
support shipped in [Crossby PR #181](https://github.com/ivanviragine/crossby/pull/181).
|
|
5
|
-
Codex
|
|
5
|
+
Codex terminal support subsequently shipped in Crossby 0.33.0 via
|
|
6
|
+
[PR #183](https://github.com/ivanviragine/crossby/pull/183); its WADE verification
|
|
7
|
+
is described below.
|
|
6
8
|
|
|
7
9
|
## Live WADE handoff
|
|
8
10
|
|
|
@@ -19,6 +21,7 @@ or PRs. Every successful run retained the original greeting source unchanged.
|
|
|
19
21
|
| Cursor 2026.09.10-fd3934a | Passed | Native plan file, import, self-review/ack, completion in fallback workspace |
|
|
20
22
|
| OpenCode 1.18.29 | Passed | Native Plan session, explicit handoff, self-review/ack, completion in fallback workspace |
|
|
21
23
|
| Antigravity CLI 1.2.3 | Passed | Native artifact file, import, self-review/ack, completion; fallback and real detached worktree with bootstrap/guards |
|
|
24
|
+
| Codex CLI 0.154.0 | Reviewed handoff verified | Published Crossby 0.33.0; ready-event prompt delivery; sandboxed detached worktree; native questions; stdin import, self-review/ack, completion |
|
|
22
25
|
| Copilot | Authenticated run omitted | Explicit user request after earlier credential failure; published adapter and WADE launch contracts remain tested |
|
|
23
26
|
|
|
24
27
|
Claude's native `plansDirectory` setting selects `.wade/plans/native/`. Cursor
|
|
@@ -46,7 +49,7 @@ used ordinary approvals, not unrestricted YOLO.
|
|
|
46
49
|
later focused regressions cover native policy rejection and incomplete-output
|
|
47
50
|
preservation as well.
|
|
48
51
|
- Explicit host deterministic E2E lane: 109 passed, including the real completion
|
|
49
|
-
command invoked by a fake native CLI and the
|
|
52
|
+
command invoked by a fake native CLI and the explicit collector-compatibility lane.
|
|
50
53
|
- Fresh review fixed stale receipts after failed reviews, unsafe managed review
|
|
51
54
|
sources, missing knowledge handoff at completion, native artifact containment,
|
|
52
55
|
selected-tool bootstrap, and preservation before the first successful import.
|
|
@@ -54,3 +57,31 @@ used ordinary approvals, not unrestricted YOLO.
|
|
|
54
57
|
Use `--worktree` on the probe for real bootstrap/guards. Keep CLI authentication
|
|
55
58
|
local and distinguish native startup, completed authenticated handoff, and
|
|
56
59
|
provider persistence; the live probe intentionally does not exercise the last.
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
## Codex deferred startup and stdin handoff
|
|
63
|
+
|
|
64
|
+
The Codex probe uses `--sandbox --worktree --model gpt-5.6-sol` and ordinary
|
|
65
|
+
native approvals. Crossby alone submits `/plan`; WADE receives `PLAN_READY`,
|
|
66
|
+
sends the rendered workflow prompt once, and requires `MESSAGE_SUBMITTED` before
|
|
67
|
+
accepting the handoff. User questions appear in the native Codex UI.
|
|
68
|
+
|
|
69
|
+
Codex ran readiness, inspected `greeting.py`, obtained native confirmation,
|
|
70
|
+
and piped its plan to `wade plan-session done --from-stdin`. WADE wrote `PLAN.md`
|
|
71
|
+
and rejected completion until review. Codex then ran `wade review plan`, read
|
|
72
|
+
and performed the frozen review method, acknowledged it with
|
|
73
|
+
`--ack-self-review`, and completed `done` while remaining in native Plan mode.
|
|
74
|
+
The parent returned `PASS: received 1 completed, reviewed plan(s)` after normal
|
|
75
|
+
Codex exit. Native session `01a0a7fa-90e6-7450-9a87-c0f12145da32` recorded Plan
|
|
76
|
+
mode throughout and one task message (Codex trims its final newline). The
|
|
77
|
+
completed receipt and exact plan content are checked again by the parent.
|
|
78
|
+
No issues or PRs are created by this probe; the greeting remains unchanged.
|
|
79
|
+
|
|
80
|
+
Published Crossby 0.33.0 wheel contracts: 374 passed, including the terminal PTY
|
|
81
|
+
suite, approval combinations, and collector regressions. WADE startup tests
|
|
82
|
+
reject absent, duplicate, mismatched, and out-of-order events. The older fake
|
|
83
|
+
app-server E2E lane now explicitly selects its collector capability, so it does
|
|
84
|
+
not claim to represent production Codex's new terminal path.
|
|
85
|
+
|
|
86
|
+
WADE adoption checklist: 4,408 tests passed, with lint, formatting, and strict
|
|
87
|
+
types passing. The live probe returned one completed reviewed plan after exit.
|
|
@@ -121,7 +121,9 @@ credentials, or binaries are missing.
|
|
|
121
121
|
Use real public Crossby request/result models in consumer tests, not mocks that
|
|
122
122
|
invent fields. `tests/e2e/test_plan_contract.py` uses a deterministic fake Codex
|
|
123
123
|
app-server with the **published collector** and real WADE CLI/provider handoff;
|
|
124
|
-
|
|
124
|
+
the fixture explicitly selects its collector capability now that production
|
|
125
|
+
Codex prefers the terminal. This is protocol-contract evidence, not genuine
|
|
126
|
+
model inference.
|
|
125
127
|
|
|
126
128
|
For dependency adoption, also run the release's own focused native suites from
|
|
127
129
|
a disposable checkout of its release tag. Install the published wheel in an
|
|
@@ -159,8 +161,11 @@ versions, completed live runs, and their limits.
|
|
|
159
161
|
|
|
160
162
|
`test_interactive_plan_service.py` exercises explicit import, review receipts,
|
|
161
163
|
self-review acknowledgement, revisions, safe file handling, and completion.
|
|
162
|
-
`test_plan_service.py` runs the published adapter builders for
|
|
164
|
+
`test_plan_service.py` runs the published adapter builders for the five flag-based native
|
|
163
165
|
terminals and asserts the Plan selector reaches the real launch boundary.
|
|
166
|
+
`test_plan_startup_events.py` verifies Codex deferred prompt delivery and rejects
|
|
167
|
+
missing, duplicate, mismatched, or out-of-order startup events. Crossby's nested
|
|
168
|
+
PTY suite covers the terminal mechanics against the published wheel.
|
|
164
169
|
The E2E plan contract also launches a fake OpenCode executable that invokes the
|
|
165
170
|
real `wade plan-session done` command and persists through the fake provider.
|
|
166
171
|
|
|
@@ -171,6 +176,7 @@ uv run python scripts/probe_native_plan_handoff.py --tool claude
|
|
|
171
176
|
uv run python scripts/probe_native_plan_handoff.py --tool cursor --model auto
|
|
172
177
|
uv run python scripts/probe_native_plan_handoff.py --tool opencode
|
|
173
178
|
uv run python scripts/probe_native_plan_handoff.py --tool antigravity-cli
|
|
179
|
+
uv run python scripts/probe_native_plan_handoff.py --tool codex --sandbox --worktree --model gpt-5.6-sol
|
|
174
180
|
```
|
|
175
181
|
|
|
176
182
|
The probe uses ordinary native approvals, real workflow/review commands, and no
|
|
@@ -73,7 +73,7 @@ WADE's canonical copies with `review plan`, and finishes the validated handoff
|
|
|
73
73
|
before exit. Review receipts bind to exact content, the frozen bundle, and the
|
|
74
74
|
current run. Prompt review requires actual self-review and `--ack-self-review`.
|
|
75
75
|
Revisions require current receipts. The command loads the REVIEW method; WORK
|
|
76
|
-
does not activate it directly. Tools without terminal Plan support
|
|
76
|
+
does not activate it directly. Tools without terminal Plan support retain
|
|
77
77
|
native artifact collection and parent review, including explicit prompt-review
|
|
78
78
|
acknowledgement. Both paths leave task persistence and implementation decisions
|
|
79
79
|
to the parent. The legacy file-presence Stop hook remains uninstalled.
|
|
@@ -327,7 +327,7 @@ plans, including salvage paths. Managed native terminal sessions additionally
|
|
|
327
327
|
require a completed `plan-session done` handoff and current content/binding review
|
|
328
328
|
receipts. `review plan --ack-self-review` confirms a performed prompt-mode review;
|
|
329
329
|
it cannot acknowledge changed content. Standalone plan review retains its ordinary
|
|
330
|
-
behavior
|
|
330
|
+
behavior; the collector fallback retains parent-side review.
|
|
331
331
|
|
|
332
332
|
## Extension rules
|
|
333
333
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "wade-cli"
|
|
7
|
-
version = "1.2.
|
|
7
|
+
version = "1.2.6"
|
|
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.36.0,<0.37.0",
|
|
28
28
|
"typer>=0.12,<0.26",
|
|
29
29
|
"pydantic>=2.0",
|
|
30
30
|
"pydantic-settings>=2.0",
|
|
@@ -30,9 +30,10 @@ def main() -> int:
|
|
|
30
30
|
parser.add_argument(
|
|
31
31
|
"--tool",
|
|
32
32
|
required=True,
|
|
33
|
-
choices=["claude", "cursor", "opencode", "antigravity-cli", "copilot"],
|
|
33
|
+
choices=["claude", "cursor", "opencode", "antigravity-cli", "copilot", "codex"],
|
|
34
34
|
)
|
|
35
35
|
parser.add_argument("--model")
|
|
36
|
+
parser.add_argument("--sandbox", action="store_true", help="Enable the native runtime sandbox")
|
|
36
37
|
parser.add_argument(
|
|
37
38
|
"--worktree", action="store_true", help="Also exercise actual worktree bootstrap and hooks"
|
|
38
39
|
)
|
|
@@ -76,7 +77,7 @@ def main() -> int:
|
|
|
76
77
|
selected_ai_tool=args.tool,
|
|
77
78
|
session_phase=SessionPhase.PLAN,
|
|
78
79
|
session_kind=SessionKind.PLAN,
|
|
79
|
-
sandbox=
|
|
80
|
+
sandbox=args.sandbox,
|
|
80
81
|
)
|
|
81
82
|
else:
|
|
82
83
|
compose_session(root, root, config, kind=SessionKind.PLAN, task_id=None)
|
|
@@ -93,7 +94,7 @@ def main() -> int:
|
|
|
93
94
|
prompt="Plan handoff probe",
|
|
94
95
|
working_dir=root,
|
|
95
96
|
model=args.model,
|
|
96
|
-
sandbox=
|
|
97
|
+
sandbox=args.sandbox,
|
|
97
98
|
),
|
|
98
99
|
permission_mode=PermissionMode.DEFAULT,
|
|
99
100
|
config=config,
|
|
@@ -19,6 +19,9 @@ from pathlib import Path
|
|
|
19
19
|
import structlog
|
|
20
20
|
from crossby.ai_tools import (
|
|
21
21
|
AbstractAITool,
|
|
22
|
+
InteractiveLaunchEvent,
|
|
23
|
+
InteractiveLaunchEventKind,
|
|
24
|
+
InteractiveSession,
|
|
22
25
|
PlanSessionError,
|
|
23
26
|
preflight_plan_session,
|
|
24
27
|
terminal_interaction_handler,
|
|
@@ -399,11 +402,30 @@ def run_interactive_planning_session(
|
|
|
399
402
|
request.working_dir, ("plans", "native"), ".wade-owned", ""
|
|
400
403
|
):
|
|
401
404
|
raise ValueError("Cannot safely create the native plan directory")
|
|
405
|
+
deferred_input = adapter.capabilities().plan_mode.supports_ready_event
|
|
406
|
+
ready = False
|
|
407
|
+
submitted = False
|
|
408
|
+
|
|
409
|
+
def on_event(event: InteractiveLaunchEvent, session: InteractiveSession) -> None:
|
|
410
|
+
nonlocal ready, submitted
|
|
411
|
+
if event.tool_id != adapter.TOOL_ID:
|
|
412
|
+
raise ValueError("Planning startup event belongs to another AI tool")
|
|
413
|
+
if event.kind is InteractiveLaunchEventKind.PLAN_READY:
|
|
414
|
+
if ready:
|
|
415
|
+
raise ValueError("Planning CLI reported Plan readiness more than once")
|
|
416
|
+
ready = True
|
|
417
|
+
session.send_message(prompt)
|
|
418
|
+
elif event.kind is InteractiveLaunchEventKind.MESSAGE_SUBMITTED:
|
|
419
|
+
if not ready or submitted:
|
|
420
|
+
raise ValueError("Planning CLI reported task submission out of order")
|
|
421
|
+
submitted = True
|
|
422
|
+
|
|
402
423
|
exit_code = adapter.launch(
|
|
403
424
|
request.working_dir,
|
|
404
425
|
model=request.model,
|
|
405
426
|
effort=request.effort,
|
|
406
|
-
prompt=prompt,
|
|
427
|
+
prompt=None if deferred_input else prompt,
|
|
428
|
+
on_event=on_event if deferred_input else None,
|
|
407
429
|
plan_mode=True,
|
|
408
430
|
plan_output_dir=native_dir,
|
|
409
431
|
transcript_path=transcript,
|
|
@@ -415,6 +437,8 @@ def run_interactive_planning_session(
|
|
|
415
437
|
)
|
|
416
438
|
if exit_code != 0:
|
|
417
439
|
raise ValueError(f"Native planning CLI exited with code {exit_code}; output was retained")
|
|
440
|
+
if deferred_input and not submitted:
|
|
441
|
+
raise ValueError("Native Plan task submission was not confirmed; output was retained")
|
|
418
442
|
bundle = interactive_plan.collect(request.working_dir)
|
|
419
443
|
usage = adapter.parse_transcript(transcript) if transcript.is_file() else None
|
|
420
444
|
return bundle, usage
|
|
@@ -16,7 +16,7 @@ Review methodology (loaded only by the bounded review step):
|
|
|
16
16
|
|
|
17
17
|
An interactive terminal session has `.wade/plans/interactive-session.json`.
|
|
18
18
|
It keeps questions, review feedback, and revisions inside the native CLI.
|
|
19
|
-
A session without that file uses native collection and parent review
|
|
19
|
+
A session without that file uses native collection and parent review.
|
|
20
20
|
|
|
21
21
|
## Required steps
|
|
22
22
|
|
|
@@ -79,6 +79,24 @@ for line in sys.stdin:
|
|
|
79
79
|
encoding="utf-8",
|
|
80
80
|
)
|
|
81
81
|
codex_script.chmod(0o755)
|
|
82
|
+
# Keep the collector lane explicit now that production Codex prefers its TUI.
|
|
83
|
+
# Only capability selection is overridden; real CLI, collector, and provider run.
|
|
84
|
+
collector_wade = mock_bin / "wade"
|
|
85
|
+
collector_wade.write_text(
|
|
86
|
+
"""#!/usr/bin/env python3
|
|
87
|
+
from crossby.ai_tools.codex import CodexAdapter
|
|
88
|
+
from crossby.models.ai import PlanModeActivation
|
|
89
|
+
from wade.cli.main import cli_main
|
|
90
|
+
original = CodexAdapter.capabilities
|
|
91
|
+
def collected_capabilities(self):
|
|
92
|
+
caps = original(self)
|
|
93
|
+
return caps.model_copy(update={"plan_mode": caps.plan_mode.model_copy(
|
|
94
|
+
update={"activation": PlanModeActivation.UNSUPPORTED})})
|
|
95
|
+
CodexAdapter.capabilities = collected_capabilities
|
|
96
|
+
cli_main()
|
|
97
|
+
"""
|
|
98
|
+
)
|
|
99
|
+
collector_wade.chmod(0o755)
|
|
82
100
|
|
|
83
101
|
|
|
84
102
|
def _disable_plan_review(repo: Path) -> None:
|
|
@@ -368,7 +368,20 @@ def collected_harness(
|
|
|
368
368
|
Task(id=str(number), title="feat: native test plan") for number in range(1, 10)
|
|
369
369
|
]
|
|
370
370
|
provider.read_task.return_value = Task(id="330", title="feat: existing", body="Original body")
|
|
371
|
+
# Exercise the retained collector path independently of Codex's new TUI capability.
|
|
372
|
+
from crossby.ai_tools.codex import CodexAdapter
|
|
373
|
+
from crossby.models.ai import PlanModeActivation
|
|
374
|
+
|
|
375
|
+
collected_caps = CodexAdapter().capabilities()
|
|
376
|
+
collected_caps = collected_caps.model_copy(
|
|
377
|
+
update={
|
|
378
|
+
"plan_mode": collected_caps.plan_mode.model_copy(
|
|
379
|
+
update={"activation": PlanModeActivation.UNSUPPORTED}
|
|
380
|
+
)
|
|
381
|
+
}
|
|
382
|
+
)
|
|
371
383
|
with (
|
|
384
|
+
patch.object(CodexAdapter, "capabilities", return_value=collected_caps),
|
|
372
385
|
patch("wade.services.plan_service.load_config", return_value=config),
|
|
373
386
|
patch("wade.services.review_delegation_service.load_config", return_value=config),
|
|
374
387
|
patch("wade.services.plan_service.get_provider", return_value=provider),
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""WADE owns task delivery through Crossby's public terminal startup events."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from unittest.mock import MagicMock, patch
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
from crossby.ai_tools import InteractiveLaunchEvent, InteractiveLaunchEventKind, InteractiveSession
|
|
8
|
+
from crossby.models.ai import AIToolID, PlanSessionRequest
|
|
9
|
+
|
|
10
|
+
from wade.models.config import AICommandConfig, AIConfig, ProjectConfig
|
|
11
|
+
from wade.models.permission import PermissionMode
|
|
12
|
+
from wade.models.workflow import SessionKind
|
|
13
|
+
from wade.services import interactive_plan_service as handoff
|
|
14
|
+
from wade.services.plan_service import run_interactive_planning_session
|
|
15
|
+
from wade.services.session_composition_service import compose_session
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.mark.parametrize(
|
|
19
|
+
"events",
|
|
20
|
+
[
|
|
21
|
+
["plan_ready", "message_submitted"],
|
|
22
|
+
[],
|
|
23
|
+
["plan_ready"],
|
|
24
|
+
["message_submitted"],
|
|
25
|
+
["plan_ready", "plan_ready"],
|
|
26
|
+
["plan_ready", "message_submitted", "message_submitted"],
|
|
27
|
+
["wrong_tool"],
|
|
28
|
+
],
|
|
29
|
+
)
|
|
30
|
+
def test_codex_deferred_delivery_and_completion_gate(tmp_path: Path, events: list[str]) -> None:
|
|
31
|
+
config = ProjectConfig(ai=AIConfig(review_plan=AICommandConfig(enabled=False)))
|
|
32
|
+
compose_session(tmp_path, tmp_path, config, kind=SessionKind.PLAN, task_id=None)
|
|
33
|
+
port = MagicMock(spec=InteractiveSession)
|
|
34
|
+
|
|
35
|
+
def native_run(command, working_dir, **kwargs):
|
|
36
|
+
assert working_dir == tmp_path
|
|
37
|
+
assert command[0] == "codex"
|
|
38
|
+
assert "app-server" not in command
|
|
39
|
+
assert "/plan" not in command
|
|
40
|
+
assert kwargs["prompt"] is None
|
|
41
|
+
assert callable(kwargs["on_event"])
|
|
42
|
+
for kind in events:
|
|
43
|
+
kwargs["on_event"](
|
|
44
|
+
InteractiveLaunchEvent(
|
|
45
|
+
kind=InteractiveLaunchEventKind.PLAN_READY
|
|
46
|
+
if kind == "wrong_tool"
|
|
47
|
+
else InteractiveLaunchEventKind(kind),
|
|
48
|
+
tool_id=AIToolID.CLAUDE if kind == "wrong_tool" else AIToolID.CODEX,
|
|
49
|
+
),
|
|
50
|
+
port,
|
|
51
|
+
)
|
|
52
|
+
handoff.import_artifact(tmp_path, "# fix: native Codex plan\n\n## Complexity\neasy\n")
|
|
53
|
+
handoff.complete(tmp_path)
|
|
54
|
+
return 0
|
|
55
|
+
|
|
56
|
+
with (
|
|
57
|
+
patch("crossby.utils.versioning.detect_binary_version", return_value=(0, 154, 0)),
|
|
58
|
+
patch("crossby.ai_tools.codex_terminal.run_terminal_plan", side_effect=native_run),
|
|
59
|
+
):
|
|
60
|
+
arguments = dict(
|
|
61
|
+
request=PlanSessionRequest(prompt="preflight", working_dir=tmp_path),
|
|
62
|
+
permission_mode=PermissionMode.DEFAULT,
|
|
63
|
+
config=config,
|
|
64
|
+
issue_context="# Task\nPlan the greeting change.",
|
|
65
|
+
session_bundle=str(tmp_path / ".wade/session"),
|
|
66
|
+
source_root=str(tmp_path),
|
|
67
|
+
)
|
|
68
|
+
if events == ["plan_ready", "message_submitted"]:
|
|
69
|
+
bundle, _ = run_interactive_planning_session(
|
|
70
|
+
"codex", str(tmp_path / ".wade/plans"), **arguments
|
|
71
|
+
)
|
|
72
|
+
assert len(bundle.plans) == 1
|
|
73
|
+
port.send_message.assert_called_once()
|
|
74
|
+
prompt = port.send_message.call_args.args[0]
|
|
75
|
+
assert prompt == (tmp_path / ".wade/plans/prompt.txt").read_text()
|
|
76
|
+
assert "WORKFLOW.md" in prompt and not prompt.startswith("/plan")
|
|
77
|
+
else:
|
|
78
|
+
with pytest.raises(ValueError):
|
|
79
|
+
run_interactive_planning_session(
|
|
80
|
+
"codex", str(tmp_path / ".wade/plans"), **arguments
|
|
81
|
+
)
|
|
82
|
+
assert port.send_message.call_count <= 1
|
|
@@ -30,7 +30,7 @@ def _skill(root: Path, relative: str, name: str) -> Path:
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def test_crossby_version_and_skill_root_mapping_contract() -> None:
|
|
33
|
-
assert version("crossby") == "0.
|
|
33
|
+
assert version("crossby") == "0.36.0"
|
|
34
34
|
assert SKILLS_DIR == {
|
|
35
35
|
AIToolID.CLAUDE: ".claude/skills",
|
|
36
36
|
AIToolID.CURSOR: ".cursor/skills",
|
|
@@ -115,3 +115,19 @@ def test_crossby_list_skills_is_sorted_and_requires_skill_markdown(
|
|
|
115
115
|
(tmp_path / ".claude/skills/not-a-skill").mkdir()
|
|
116
116
|
|
|
117
117
|
assert list_skills(tmp_path / ".claude/skills") == ["alpha", "zeta"]
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def test_interactive_plan_startup_events_contract() -> None:
|
|
121
|
+
from crossby.ai_tools import InteractiveLaunchEvent, InteractiveLaunchEventKind
|
|
122
|
+
from crossby.models.ai import PlanModeActivation
|
|
123
|
+
|
|
124
|
+
caps = AbstractAITool.get("codex").capabilities()
|
|
125
|
+
assert caps.supports_plan_mode
|
|
126
|
+
assert caps.plan_mode.activation is PlanModeActivation.TERMINAL_INPUT
|
|
127
|
+
assert caps.plan_mode.supports_ready_event
|
|
128
|
+
assert caps.plan_mode.collector_verified_version == "0.153.4"
|
|
129
|
+
assert set(InteractiveLaunchEvent.model_fields) == {"kind", "tool_id"}
|
|
130
|
+
assert {kind.value for kind in InteractiveLaunchEventKind} == {
|
|
131
|
+
"plan_ready",
|
|
132
|
+
"message_submitted",
|
|
133
|
+
}
|