claude-code-conductor 2.60.0__tar.gz → 2.60.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/CHANGELOG.md +21 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/PKG-INFO +1 -1
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/__init__.py +1 -1
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/cli_update.py +86 -51
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_cli_update_deletions.py +259 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_init_only_patterns.py +55 -4
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/.gitignore +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/CLAUDE.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/architect.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/code-reviewer.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/design-critic.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/developer.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/doc-writer.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/interviewer.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/planner.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/project-setup.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/security-reviewer.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/systematic-debugger.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/tester.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/wt_developer.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/wt_systematic-debugger.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/wt_tester.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/breaking-changes.txt +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/deletions.txt +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/docs/autonomous-mode-onboarding.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/docs/config-policy.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/docs/nul-boundary.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/docs/parallel-agents-setup.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/docs/platform-adapters.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/docs/settings.json.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/_hook_utils.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/check_agent_invocation.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/consolidate_memory.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/patterns_guard.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/permission_handler.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/permission_handler_toast.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/planner_check.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/post_tool.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/pre_compact.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/pre_tool.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/recall_autorebuild.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/recall_inject.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/report_contract_check.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/restore_session.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/select_tier.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/session_mode_watch.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/session_start.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/session_stop.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/session_utils.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/statusline.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/stop.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/tier_autoapply.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/tier_gap_check.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/worktree_guard.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/memory/.gitkeep +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/permission_rules.json +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/rules/promoted/index.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/settings.json +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/autonomous-mode/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/autonomous-mode/scripts/mode_line.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/brainstorm/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/codex-review/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/dev-workflow/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/dev-workflow/references/code-review-checklist.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/dev-workflow/references/design-critic-rubric.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/dev-workflow/references/design-rubric.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/dev-workflow/references/interview-rubric.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/dev-workflow/references/plan-design-guidelines.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/dev-workflow/references/security-review-checklist.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/dev-workflow/scripts/record_agent_outcome.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/dev-workflow/scripts/record_review_decision.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/dev-workflow/scripts/review_hint_inject.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/develop/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/doc/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/extract-lib/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/init-session/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/init-session/scripts/session_guard.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/mcp-config/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/parallel-agents/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/pattern-status/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/promote-pattern/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/recall/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/report-timestamp/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/report-timestamp/scripts/get_timestamp.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/review-phase/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/setup/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/setup/reference.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/setup/templates/coding-standards-template.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/setup/templates/project-conventions-template.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/skills/start/SKILL.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/state/.gitkeep +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.gitignore +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/ARCHITECTURE.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/LICENSE +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/LICENSES/fastembed-LICENSE +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/LICENSES/fastembed-NOTICE +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/LICENSES/numpy-LICENSE +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/LICENSES/onnxruntime-LICENSE +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/LICENSES/paraphrase-multilingual-MiniLM-L12-v2-LICENSE +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/README.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/hatch_build.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/pyproject.toml +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/__main__.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/_db_params.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/_excludes.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/_terminal.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/adapters.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/cli.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/cli_ask.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/cli_doctor.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/cli_init.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/cli_list.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/cli_metrics.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/cli_plan.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/cli_recall.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/cli_run.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/cli_tier.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/db.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/embedding.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/gitutil.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/mcp_server.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/migrate.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/migrations/001_initial.sql +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/migrations/002_agent_cost_runs.sql +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/migrations/003_tier_cost.sql +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/migrations/004_agent_outcomes.sql +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/migrations/005_drop_agent_tier_bandit.sql +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/migrations/006_review_decisions_severity.sql +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/migrations/README.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/migrations/__init__.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/paths.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/plan_validator.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/platforms.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/pricing.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/question.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/recall_chunker.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/recall_index.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/src/c3/usage_ingester.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/__init__.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/_pre_compact_helpers.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/conftest.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/fixtures/usage/README.md +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/fixtures/usage/mainline.jsonl +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/fixtures/usage/subagents/agent-deadbeef.jsonl +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/fixtures/usage/subagents/agent-deadbeef.meta.json +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/__init__.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_check_agent_invocation.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_consolidate_memory.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_hook_utils.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_permission_handler.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_permission_handler_toast.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_pip_reinstall_reminder.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_planner_check.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_planner_check_dev.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_post_tool.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_pre_tool.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_recall_autorebuild.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_recall_inject.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_record_agent_outcome.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_record_review_decision.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_restore_session.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_review_hint_inject.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_select_tier.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_select_tier_escalation.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_session_start.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_session_stop.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_session_utils.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_settings_local_absolute_paths.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_settings_tier_autoapply_registration.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_similarity_boost.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_statusline.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_statusline_template_sync.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_sync_check.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_template_guard.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_tier_autoapply.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_tier_gap_check.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/hooks/test_tier_security_fixes.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/skills/__init__.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/skills/_skill_helpers.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/skills/test_dev_workflow_no_task_type.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/skills/test_init_session_no_task_type.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/skills/test_marker_compliance.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/skills/test_parallel_agents_skill_tier.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/skills/test_planner_lightweight.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/skills/test_recall_skill.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/skills/test_session_backlog_reconciliation.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/skills/test_session_guard.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/skills/test_setup_templates.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/skills/test_start_skill_bugfix_flow.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/skills/test_start_skill_new_flow.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/skills/test_start_skill_security_audit_phase.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_adapters.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_check_deletions.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_claude_gitignore.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_cli_ask.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_cli_doctor.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_cli_doctor_launcher.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_cli_entry.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_cli_init.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_cli_list.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_cli_metrics.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_cli_plan.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_cli_recall.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_cli_run.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_cli_tier.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_cli_update_breaking_changes.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_db.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_docstring_consistency.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_embedding.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_excludes.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_extract_breaking_changes.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_gitutil.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_hooks_stdin_idiom.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_mcp_server_elicit.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_migrate.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_mode_line.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_no_bare_python_launcher.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_nul_boundary_lint.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_paths.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_patterns_guard.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_plan_validator.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_pre_compact.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_pre_tool_hook.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_precompact_additional.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_precompact_toctou_fixes.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_pricing.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_recall_chunker.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_recall_index.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_references_migration.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_report_contract_check.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_scripts_stdout_encoding.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_session_mode_watch.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_session_utils_additional.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_settings_hooks_registration.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_skill_no_builtin_conflict.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_statusline.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_stop_additional.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_stop_agent_memory_warn.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_stop_hook.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_stop_precompact_fixes.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_sync_template_stop.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_template_pre_tool_hook.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_usage_ingester.py +0 -0
- {claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_worktree_guard.py +0 -0
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.60.1] - 2026-08-01
|
|
4
|
+
|
|
5
|
+
### 修正
|
|
6
|
+
|
|
7
|
+
- `c3 update` の削除処理で、セーフガードが弾いた理由(warnings)や不在ファイル一覧が
|
|
8
|
+
画面に出ないケースがあったのを修正した。従来は「削除を実行した」場合にしか詳細を出しておらず、
|
|
9
|
+
(a) 削除候補が 0 件のとき (b) 削除プロンプトで n を選んだとき の 2 状態で握り潰されていた。
|
|
10
|
+
影響は init-only 保護に限らず `deletions.txt` のパース警告を含むセーフガード全体に及んでいた
|
|
11
|
+
- 真因(詳細の出力コードが dry-run 経路と通常実行経路に二重化し、通常実行側では状態分岐に
|
|
12
|
+
埋もれていた)を除去し、詳細の出力を単一・無条件の経路へ統合した
|
|
13
|
+
- 詳細行の本文に **C0 制御文字・ESC の除去**を適用した(表示する状態が増えたことに対する予防)。
|
|
14
|
+
**bidi 制御文字(U+202E 等)は除去対象外**(既知・許容)
|
|
15
|
+
|
|
16
|
+
### 変更
|
|
17
|
+
|
|
18
|
+
- 削除実行時の詳細セクションの見出し書式が `--dry-run` 側に統一された。
|
|
19
|
+
` absent:` / ` warnings:` の入れ子見出しは `deletions: N already absent:` /
|
|
20
|
+
`deletions: N warning(s):` に変わり、一覧のインデントが 4 スペースから 2 スペースになる
|
|
21
|
+
- `deletions: nothing to delete` は削除・不在・エラー・警告のいずれも無く、
|
|
22
|
+
かつキャンセルされていないときにのみ表示する
|
|
23
|
+
|
|
3
24
|
## [2.60.0] - 2026-08-01
|
|
4
25
|
|
|
5
26
|
### 破壊的変更
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-code-conductor
|
|
3
|
-
Version: 2.60.
|
|
3
|
+
Version: 2.60.1
|
|
4
4
|
Summary: Multi-agent orchestration framework for Claude Code with Codex/Cursor adapters (C3)
|
|
5
5
|
Project-URL: Homepage, https://github.com/satoh-y-0323/claude-code-conductor
|
|
6
6
|
Project-URL: Repository, https://github.com/satoh-y-0323/claude-code-conductor
|
|
@@ -653,7 +653,7 @@ def _validate_deletion_path(rel: str, claude_root: Path) -> tuple[Path | None, s
|
|
|
653
653
|
Returns:
|
|
654
654
|
(resolved_path, warning):
|
|
655
655
|
resolved_path: 安全に削除可能と判定された絶対 Path。不正・対象外なら None
|
|
656
|
-
warning:
|
|
656
|
+
warning: 不正検出時の理由メッセージ(人間可読、削除レポートの一部として stdout 出力用)。
|
|
657
657
|
正常時は None。「ファイル不在(=既に削除済み)」は warning ではなく
|
|
658
658
|
呼び出し側で「skipped (already absent)」として処理する
|
|
659
659
|
|
|
@@ -864,6 +864,62 @@ def _apply_deletions(
|
|
|
864
864
|
return result
|
|
865
865
|
|
|
866
866
|
|
|
867
|
+
def _format_deletion_details(result: dict[str, Any]) -> list[str]:
|
|
868
|
+
"""absent / errors / warnings の詳細行を組み立てる(唯一の出力経路)。
|
|
869
|
+
|
|
870
|
+
dry-run・通常実行の別を引数に取らない。状態による出し分けを持たないことが
|
|
871
|
+
この関数の契約であり、呼び出し側は結果を無条件に連結する。
|
|
872
|
+
各要素の本文は sanitize_terminal_text を通す(ADR-8)。
|
|
873
|
+
"""
|
|
874
|
+
lines: list[str] = []
|
|
875
|
+
|
|
876
|
+
absent = result["absent"]
|
|
877
|
+
errors = result["errors"]
|
|
878
|
+
warnings = result["warnings"]
|
|
879
|
+
|
|
880
|
+
if absent:
|
|
881
|
+
lines.append(f"deletions: {len(absent)} already absent:")
|
|
882
|
+
for rel in absent:
|
|
883
|
+
lines.append(f" - {sanitize_terminal_text(rel)}")
|
|
884
|
+
if errors:
|
|
885
|
+
lines.append(_color(f"deletions: {len(errors)} error(s):", "\033[31m"))
|
|
886
|
+
for e in errors:
|
|
887
|
+
lines.append(f" - {sanitize_terminal_text(e)}")
|
|
888
|
+
if warnings:
|
|
889
|
+
lines.append(_color(f"deletions: {len(warnings)} warning(s):", "\033[33m"))
|
|
890
|
+
for w in warnings:
|
|
891
|
+
lines.append(f" - {sanitize_terminal_text(w)}")
|
|
892
|
+
|
|
893
|
+
return lines
|
|
894
|
+
|
|
895
|
+
|
|
896
|
+
def _format_deletion_summary(result: dict[str, Any]) -> str:
|
|
897
|
+
"""通常実行の状態行に出すサマリ 1 行を組み立てる。
|
|
898
|
+
|
|
899
|
+
`_format_deletion_report` の行数を抑えるための抽出であり、文言・色・書式は
|
|
900
|
+
抽出前と同一。件数のみを見るため詳細一覧は組み立てない(詳細は
|
|
901
|
+
`_format_deletion_details` の担当)。
|
|
902
|
+
"""
|
|
903
|
+
deleted_count = _color(f"{len(result['deleted'])} deleted", "\033[32m")
|
|
904
|
+
error_count = len(result["errors"])
|
|
905
|
+
error_str = (
|
|
906
|
+
_color(f"{error_count} error(s)", "\033[31m")
|
|
907
|
+
if error_count > 0
|
|
908
|
+
else f"{error_count} errors"
|
|
909
|
+
)
|
|
910
|
+
absent_count = len(result["absent"])
|
|
911
|
+
warn_count = len(result["warnings"])
|
|
912
|
+
warn_str = (
|
|
913
|
+
_color(f"{warn_count} warning(s)", "\033[33m")
|
|
914
|
+
if warn_count > 0
|
|
915
|
+
else f"{warn_count} warning(s)"
|
|
916
|
+
)
|
|
917
|
+
return (
|
|
918
|
+
f"deletions: {deleted_count}, {absent_count} absent,"
|
|
919
|
+
f" {error_str}, {warn_str}"
|
|
920
|
+
)
|
|
921
|
+
|
|
922
|
+
|
|
867
923
|
def _format_deletion_report(result: dict[str, Any], *, dry_run: bool, assume_yes: bool = False) -> str:
|
|
868
924
|
"""`_apply_deletions()` の戻り値を人間可読な stdout テキストに整形する。
|
|
869
925
|
|
|
@@ -871,6 +927,17 @@ def _format_deletion_report(result: dict[str, Any], *, dry_run: bool, assume_yes
|
|
|
871
927
|
result: `_apply_deletions()` の戻り値 dict
|
|
872
928
|
dry_run: True なら dry-run 出力フォーマット
|
|
873
929
|
assume_yes: True かつ通常実行の場合、`(--yes: skipping prompt)` を出力
|
|
930
|
+
|
|
931
|
+
構成は 3 段((1) 状態行 / (2) 詳細 / (3) 締め)に固定する。前提は以下:
|
|
932
|
+
|
|
933
|
+
- サマリ行の条件は `any_info`(to_delete / deleted / absent / errors / warnings の
|
|
934
|
+
5 要素すべてを見る)であるため、「`deleted` が非空なら `to_delete` も非空」といった
|
|
935
|
+
`_apply_deletions` 側の不変則に依存しない
|
|
936
|
+
- 状態行の条件と締めの条件は相補的であり、通常実行では必ず状態行が 1 本出る。
|
|
937
|
+
締めの `not cancelled` が `cancelled` 行との同時出力を構造的に排除する
|
|
938
|
+
- 詳細(absent / errors / warnings)は `_format_deletion_details` が
|
|
939
|
+
唯一の出力経路である。ここでは分岐を持たせず無条件に連結する。
|
|
940
|
+
状態分岐の中で詳細を出す実装を再び足してはならない(本欠陥の再発経路)
|
|
874
941
|
"""
|
|
875
942
|
lines: list[str] = []
|
|
876
943
|
|
|
@@ -881,8 +948,10 @@ def _format_deletion_report(result: dict[str, Any], *, dry_run: bool, assume_yes
|
|
|
881
948
|
warnings = result["warnings"]
|
|
882
949
|
cancelled = result["cancelled"]
|
|
883
950
|
|
|
951
|
+
any_info = bool(to_delete or deleted or absent or errors or warnings)
|
|
952
|
+
|
|
953
|
+
# --- (1) 状態行 ─ 経路・状態ごとに異なるのはここだけ ---
|
|
884
954
|
if dry_run:
|
|
885
|
-
# --- dry_run 出力 ---
|
|
886
955
|
if to_delete:
|
|
887
956
|
header = _color(
|
|
888
957
|
f"deletions: {len(to_delete)} file(s) would be removed:",
|
|
@@ -890,22 +959,11 @@ def _format_deletion_report(result: dict[str, Any], *, dry_run: bool, assume_yes
|
|
|
890
959
|
)
|
|
891
960
|
lines.append(header)
|
|
892
961
|
for rel in to_delete:
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
lines.append(f" - {rel}")
|
|
898
|
-
if warnings:
|
|
899
|
-
warn_header = _color(f"deletions: {len(warnings)} warning(s):", "\033[33m")
|
|
900
|
-
lines.append(warn_header)
|
|
901
|
-
for w in warnings:
|
|
902
|
-
lines.append(f" - {w}")
|
|
903
|
-
if not to_delete and not absent and not warnings:
|
|
904
|
-
lines.append("deletions: nothing to delete")
|
|
905
|
-
else:
|
|
906
|
-
lines.append("(dry-run: no files were modified)")
|
|
962
|
+
# rel は deletions.txt 由来の外部文字列。_validate_deletion_path は
|
|
963
|
+
# パスの安全性しか検査せず、_load_deletions の ANSI 検査も CSI 形式
|
|
964
|
+
# のみを弾くため、OSC / bare ESC / BS / BEL は生き残り得る(ADR-8 改訂 6)。
|
|
965
|
+
lines.append(f" - {sanitize_terminal_text(rel)}")
|
|
907
966
|
else:
|
|
908
|
-
# --- 通常実行出力 ---
|
|
909
967
|
# 候補一覧は _apply_deletions() 内でプロンプト前に表示済み。
|
|
910
968
|
# assume_yes の場合はプロンプトスキップを明示する。
|
|
911
969
|
# NOTE: assume_yes=True のとき _apply_deletions は input() を呼ばないため
|
|
@@ -916,40 +974,17 @@ def _format_deletion_report(result: dict[str, Any], *, dry_run: bool, assume_yes
|
|
|
916
974
|
|
|
917
975
|
if cancelled:
|
|
918
976
|
lines.append("deletions: cancelled by user (no files removed)")
|
|
919
|
-
elif
|
|
920
|
-
lines.append(
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
absent_count = len(absent)
|
|
931
|
-
warn_count = len(warnings)
|
|
932
|
-
warn_str = (
|
|
933
|
-
_color(f"{warn_count} warning(s)", "\033[33m")
|
|
934
|
-
if warn_count > 0
|
|
935
|
-
else f"{warn_count} warning(s)"
|
|
936
|
-
)
|
|
937
|
-
lines.append(
|
|
938
|
-
f"deletions: {deleted_count}, {absent_count} absent,"
|
|
939
|
-
f" {error_str}, {warn_str}"
|
|
940
|
-
)
|
|
941
|
-
if absent:
|
|
942
|
-
lines.append(f" absent:")
|
|
943
|
-
for rel in absent:
|
|
944
|
-
lines.append(f" - {rel}")
|
|
945
|
-
if errors:
|
|
946
|
-
lines.append(" errors:")
|
|
947
|
-
for e in errors:
|
|
948
|
-
lines.append(f" - {e}")
|
|
949
|
-
if warnings:
|
|
950
|
-
lines.append(" warnings:")
|
|
951
|
-
for w in warnings:
|
|
952
|
-
lines.append(f" - {w}")
|
|
977
|
+
elif any_info:
|
|
978
|
+
lines.append(_format_deletion_summary(result))
|
|
979
|
+
|
|
980
|
+
# --- (2) 詳細 ─ 単一・無条件。分岐を持たない ---
|
|
981
|
+
lines.extend(_format_deletion_details(result))
|
|
982
|
+
|
|
983
|
+
# --- (3) 締め ---
|
|
984
|
+
if not any_info and not cancelled:
|
|
985
|
+
lines.append("deletions: nothing to delete")
|
|
986
|
+
elif dry_run:
|
|
987
|
+
lines.append("(dry-run: no files were modified)")
|
|
953
988
|
|
|
954
989
|
return "\n".join(lines) # nul-boundary: allow(c3 update のサマリ表示テキスト。表示専用で再パースしない)
|
|
955
990
|
|
{claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_cli_update_deletions.py
RENAMED
|
@@ -5,10 +5,12 @@ A: _validate_deletion_path ユニット (13)
|
|
|
5
5
|
B: _apply_deletions 結合 (8)
|
|
6
6
|
C: パストラバーサル / symlink / 範囲外 攻撃 (9)
|
|
7
7
|
D: CLI 統合 (4)
|
|
8
|
+
E: _format_deletion_report 不変則 (I-1 プロパティ・I-2 シグネチャ・状態行 7 件)
|
|
8
9
|
"""
|
|
9
10
|
from __future__ import annotations
|
|
10
11
|
|
|
11
12
|
import argparse
|
|
13
|
+
import itertools
|
|
12
14
|
import os
|
|
13
15
|
import sys
|
|
14
16
|
from pathlib import Path
|
|
@@ -16,6 +18,7 @@ from unittest.mock import patch
|
|
|
16
18
|
|
|
17
19
|
import pytest
|
|
18
20
|
|
|
21
|
+
from c3._terminal import strip_ansi
|
|
19
22
|
from c3.cli_update import (
|
|
20
23
|
_apply_deletions,
|
|
21
24
|
_format_deletion_report,
|
|
@@ -536,3 +539,259 @@ class TestCLIIntegration:
|
|
|
536
539
|
args = self._make_args(tmp_path, dry_run=False, yes=False)
|
|
537
540
|
ret = handle(args)
|
|
538
541
|
assert ret == 0
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
# ---------------------------------------------------------------------------
|
|
545
|
+
# E: _format_deletion_report 不変則テスト
|
|
546
|
+
# architecture-report-20260801-015843.md(改訂 5・確定版)ADR-5' 準拠。
|
|
547
|
+
# I-1 直積 128 ケースは Red 群と回帰ガード群が混在する(plan-report §C-2)。
|
|
548
|
+
# `.claude/agents/tester.md:49`(最初から Pass するテストは修正する)は
|
|
549
|
+
# 本タスクには適用しない(plan-report §C-2 の明文の適用除外)。
|
|
550
|
+
# ---------------------------------------------------------------------------
|
|
551
|
+
|
|
552
|
+
def _make_result(
|
|
553
|
+
*,
|
|
554
|
+
to_delete=(),
|
|
555
|
+
deleted=(),
|
|
556
|
+
absent=(),
|
|
557
|
+
errors=(),
|
|
558
|
+
warnings=(),
|
|
559
|
+
cancelled=False,
|
|
560
|
+
):
|
|
561
|
+
"""テスト内で `_apply_deletions` の戻り値と同じ 6 キーを直接組み立てるヘルパー。"""
|
|
562
|
+
return {
|
|
563
|
+
"to_delete": list(to_delete),
|
|
564
|
+
"deleted": list(deleted),
|
|
565
|
+
"absent": list(absent),
|
|
566
|
+
"errors": list(errors),
|
|
567
|
+
"warnings": list(warnings),
|
|
568
|
+
"cancelled": cancelled,
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
# I-1 直積: dry_run × cancelled × assume_yes × to_delete有無 × absent有無 ×
|
|
573
|
+
# errors有無 × warnings有無(各2値 = 128ケース)。plan-report §A-1 の逐語指定。
|
|
574
|
+
_I1_TO_DELETE_VALUES = ([], ["agents/a.md"])
|
|
575
|
+
_I1_ABSENT_VALUES = ([], ["agents/b.md"])
|
|
576
|
+
_I1_ERRORS_VALUES = ([], ["agents/c.md: permission denied"])
|
|
577
|
+
_I1_WARNINGS_VALUES = ([], ["agents/d.md: init-only guard"])
|
|
578
|
+
|
|
579
|
+
_I1_CASES = list(
|
|
580
|
+
itertools.product(
|
|
581
|
+
(True, False), # dry_run
|
|
582
|
+
(True, False), # cancelled
|
|
583
|
+
(True, False), # assume_yes
|
|
584
|
+
_I1_TO_DELETE_VALUES,
|
|
585
|
+
_I1_ABSENT_VALUES,
|
|
586
|
+
_I1_ERRORS_VALUES,
|
|
587
|
+
_I1_WARNINGS_VALUES,
|
|
588
|
+
)
|
|
589
|
+
)
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
class TestFormatDeletionReportInvariants:
|
|
593
|
+
"""不変則 I-1(プロパティ)・I-2(シグネチャ)のテスト。"""
|
|
594
|
+
|
|
595
|
+
@pytest.mark.parametrize(
|
|
596
|
+
"dry_run,cancelled,assume_yes,to_delete,absent,errors,warnings",
|
|
597
|
+
_I1_CASES,
|
|
598
|
+
)
|
|
599
|
+
def test_i1_non_empty_detail_fields_always_appear_in_output(
|
|
600
|
+
self, dry_run, cancelled, assume_yes, to_delete, absent, errors, warnings
|
|
601
|
+
):
|
|
602
|
+
"""不変則 I-1: absent / errors / warnings の非空要素は、あらゆる組み合わせで
|
|
603
|
+
出力文字列に含まれる(一般則を 1 つの assert で検証・ケースごとの期待文字列は
|
|
604
|
+
ハードコードしない)。
|
|
605
|
+
"""
|
|
606
|
+
# deleted は to_delete 非空かつ cancelled=False かつ dry_run=False のとき同値、
|
|
607
|
+
# それ以外は空(plan-report §A-1 の逐語指定)。
|
|
608
|
+
deleted = list(to_delete) if (to_delete and not cancelled and not dry_run) else []
|
|
609
|
+
result = _make_result(
|
|
610
|
+
to_delete=to_delete,
|
|
611
|
+
deleted=deleted,
|
|
612
|
+
absent=absent,
|
|
613
|
+
errors=errors,
|
|
614
|
+
warnings=warnings,
|
|
615
|
+
cancelled=cancelled,
|
|
616
|
+
)
|
|
617
|
+
output = _format_deletion_report(result, dry_run=dry_run, assume_yes=assume_yes)
|
|
618
|
+
|
|
619
|
+
for element in absent:
|
|
620
|
+
assert element in output, (
|
|
621
|
+
f"absent 要素が出力に無い: {element!r} / output={output!r} / "
|
|
622
|
+
f"dry_run={dry_run} cancelled={cancelled} assume_yes={assume_yes}"
|
|
623
|
+
)
|
|
624
|
+
for element in errors:
|
|
625
|
+
assert element in output, (
|
|
626
|
+
f"errors 要素が出力に無い: {element!r} / output={output!r} / "
|
|
627
|
+
f"dry_run={dry_run} cancelled={cancelled} assume_yes={assume_yes}"
|
|
628
|
+
)
|
|
629
|
+
for element in warnings:
|
|
630
|
+
assert element in output, (
|
|
631
|
+
f"warnings 要素が出力に無い: {element!r} / output={output!r} / "
|
|
632
|
+
f"dry_run={dry_run} cancelled={cancelled} assume_yes={assume_yes}"
|
|
633
|
+
)
|
|
634
|
+
|
|
635
|
+
def test_i2_format_deletion_details_signature_is_result_only(self):
|
|
636
|
+
"""不変則 I-2: `_format_deletion_details` のシグネチャは `result` のみ。
|
|
637
|
+
|
|
638
|
+
モジュールトップレベルでは import しない(未実装の名前をトップに足すと
|
|
639
|
+
ファイル全体が collection error になり既存テストが全滅するため・
|
|
640
|
+
plan-report §A-2)。
|
|
641
|
+
"""
|
|
642
|
+
import inspect
|
|
643
|
+
|
|
644
|
+
import c3.cli_update as m
|
|
645
|
+
|
|
646
|
+
assert hasattr(m, "_format_deletion_details"), (
|
|
647
|
+
"_format_deletion_details が未実装(Red フェーズでは想定内の失敗)"
|
|
648
|
+
)
|
|
649
|
+
sig = inspect.signature(m._format_deletion_details)
|
|
650
|
+
params = list(sig.parameters.keys())
|
|
651
|
+
assert params == ["result"], f"シグネチャが result のみでない: {params!r}"
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
class TestFormatDeletionReportStateLines:
|
|
655
|
+
"""状態行の個別テスト(3-1〜3-7・plan-report §A-3 の逐語入力)。
|
|
656
|
+
|
|
657
|
+
3-2 / 3-4 / 3-5 / 3-6 / 3-7 は是正前から緑になる回帰ガード(plan-report §C-1)。
|
|
658
|
+
アサーションの反転・削除は禁止(同 §C-2 の適用除外)。
|
|
659
|
+
"""
|
|
660
|
+
|
|
661
|
+
def test_3_1_cancelled_line_present_and_excludes_nothing_to_delete(self):
|
|
662
|
+
result = _make_result(to_delete=["agents/a.md"], cancelled=True)
|
|
663
|
+
output = _format_deletion_report(result, dry_run=False, assume_yes=False)
|
|
664
|
+
assert "deletions: cancelled by user (no files removed)" in output
|
|
665
|
+
assert "nothing to delete" not in output
|
|
666
|
+
|
|
667
|
+
def test_3_2_all_five_fields_empty_shows_nothing_to_delete(self):
|
|
668
|
+
result = _make_result()
|
|
669
|
+
output = _format_deletion_report(result, dry_run=False, assume_yes=False)
|
|
670
|
+
assert "deletions: nothing to delete" in output
|
|
671
|
+
|
|
672
|
+
def test_3_3_warnings_only_excludes_nothing_to_delete(self):
|
|
673
|
+
result = _make_result(warnings=["agents/d.md: init-only guard"])
|
|
674
|
+
output = _format_deletion_report(result, dry_run=False, assume_yes=False)
|
|
675
|
+
assert "nothing to delete" not in output
|
|
676
|
+
|
|
677
|
+
def test_3_4_assume_yes_shows_skipping_prompt_line(self):
|
|
678
|
+
result = _make_result(to_delete=["agents/a.md"])
|
|
679
|
+
output = _format_deletion_report(result, dry_run=False, assume_yes=True)
|
|
680
|
+
assert "(--yes: skipping prompt)" in output
|
|
681
|
+
|
|
682
|
+
def test_3_5_summary_line_contains_deleted_and_absent_after_strip_ansi(self):
|
|
683
|
+
result = _make_result(to_delete=["agents/a.md"], deleted=["agents/a.md"])
|
|
684
|
+
output = _format_deletion_report(result, dry_run=False, assume_yes=False)
|
|
685
|
+
stripped = strip_ansi(output)
|
|
686
|
+
assert "deleted," in stripped
|
|
687
|
+
assert " absent," in stripped
|
|
688
|
+
|
|
689
|
+
def test_3_6_dry_run_absent_only_shows_no_files_modified(self):
|
|
690
|
+
result = _make_result(absent=["agents/b.md"])
|
|
691
|
+
output = _format_deletion_report(result, dry_run=True, assume_yes=False)
|
|
692
|
+
assert "(dry-run: no files were modified)" in output
|
|
693
|
+
|
|
694
|
+
def test_3_7_normal_execution_output_is_not_empty(self):
|
|
695
|
+
result = _make_result(to_delete=["agents/a.md"])
|
|
696
|
+
output = _format_deletion_report(result, dry_run=False, assume_yes=False)
|
|
697
|
+
assert output != ""
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
# ---------------------------------------------------------------------------
|
|
701
|
+
# F: 不変則 I-3(サニタイズ適用の回帰ガード)
|
|
702
|
+
# security-review-report-20260801-025354.md の [SR-NEW](Low)対応。
|
|
703
|
+
# plan-report-20260801-030043.md(改訂 7)task test-sanitize-regression 準拠。
|
|
704
|
+
# ---------------------------------------------------------------------------
|
|
705
|
+
|
|
706
|
+
from c3._terminal import _DISALLOWED_CONTROL_RE # noqa: E402
|
|
707
|
+
|
|
708
|
+
_I3_CONTROL_PATTERNS = {
|
|
709
|
+
"bs": "\x08",
|
|
710
|
+
"esc": "\x1b",
|
|
711
|
+
"bel": "\x07",
|
|
712
|
+
"osc": "\x1b]0;X\x07",
|
|
713
|
+
"csi": "\x1b[31m",
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
# to_delete は dry-run 状態行の経路(_format_deletion_report 内、to_delete
|
|
717
|
+
# ループ)でのみ要素本文が出力される。dry_run=False では to_delete の要素は
|
|
718
|
+
# _format_deletion_report のどこにも描画されない(cancelled / assume_yes の
|
|
719
|
+
# 判定材料として真偽値でのみ参照される)ため、("to_delete", False) は
|
|
720
|
+
# 「描画されない=漏れない」ことを確認する vacuous case(意図的に含む)。
|
|
721
|
+
# サニタイズ除去に対する実質的な回帰検知力は ("to_delete", True) が担う。
|
|
722
|
+
_I3_FIELD_DRY_RUN_CASES = [
|
|
723
|
+
("to_delete", True),
|
|
724
|
+
("to_delete", False),
|
|
725
|
+
("absent", True),
|
|
726
|
+
("absent", False),
|
|
727
|
+
("errors", True),
|
|
728
|
+
("errors", False),
|
|
729
|
+
("warnings", True),
|
|
730
|
+
("warnings", False),
|
|
731
|
+
]
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
class TestFormatDeletionReportSanitizeRegression:
|
|
735
|
+
"""不変則 I-3: `_format_deletion_report` の出力には、入力に含まれていた
|
|
736
|
+
C0 制御文字(`sanitize_terminal_text` の除去対象)が一切現れない。
|
|
737
|
+
|
|
738
|
+
security-review-report-20260801-025354.md [SR-NEW](Low)への対応。
|
|
739
|
+
to_delete(dry-run 状態行の経路)/ absent / errors / warnings
|
|
740
|
+
(`_format_deletion_details` の経路)の 4 経路すべてを対象とする。
|
|
741
|
+
"""
|
|
742
|
+
|
|
743
|
+
@pytest.mark.parametrize(
|
|
744
|
+
"control_name,control_char", list(_I3_CONTROL_PATTERNS.items())
|
|
745
|
+
)
|
|
746
|
+
@pytest.mark.parametrize("field,dry_run", _I3_FIELD_DRY_RUN_CASES)
|
|
747
|
+
def test_i3_control_characters_never_reach_output(
|
|
748
|
+
self,
|
|
749
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
750
|
+
field: str,
|
|
751
|
+
dry_run: bool,
|
|
752
|
+
control_name: str,
|
|
753
|
+
control_char: str,
|
|
754
|
+
):
|
|
755
|
+
"""除去対象の文字集合に対する一般則として判定する(個別文字を列挙しない)。"""
|
|
756
|
+
# supports_color() は sys.stdout.isatty() に依存し環境依存になるため、
|
|
757
|
+
# False に固定して _color() が正規の ANSI(\x1b[...m)を混入させない
|
|
758
|
+
# ようにする。これにより「出力全体に除去対象文字が 1 つも無い」という
|
|
759
|
+
# 一般則の判定を、実行環境(TTY か否か)に左右されずに行える。
|
|
760
|
+
monkeypatch.setattr("c3.cli_update.supports_color", lambda: False)
|
|
761
|
+
|
|
762
|
+
injected = f"agents/evil{control_char}payload.md"
|
|
763
|
+
result = _make_result(**{field: [injected]})
|
|
764
|
+
output = _format_deletion_report(result, dry_run=dry_run, assume_yes=False)
|
|
765
|
+
|
|
766
|
+
assert _DISALLOWED_CONTROL_RE.search(output) is None, (
|
|
767
|
+
f"サニタイズ対象の制御文字が出力に残存: field={field!r} "
|
|
768
|
+
f"dry_run={dry_run} control={control_name!r} output={output!r}"
|
|
769
|
+
)
|
|
770
|
+
|
|
771
|
+
def test_i3_normal_paths_unaffected_by_sanitization(
|
|
772
|
+
self, monkeypatch: pytest.MonkeyPatch
|
|
773
|
+
):
|
|
774
|
+
"""回帰の防波堤: 制御文字を含まない通常のパス・理由文は変化しない
|
|
775
|
+
(サニタイズが過剰に効いていないことの担保)。
|
|
776
|
+
"""
|
|
777
|
+
monkeypatch.setattr("c3.cli_update.supports_color", lambda: False)
|
|
778
|
+
|
|
779
|
+
to_delete = ["agents/normal-path.md"]
|
|
780
|
+
absent = ["skills/removed-skill.md"]
|
|
781
|
+
errors = ["commands/broken.md: permission denied"]
|
|
782
|
+
warnings = ["commands/init-only.md: init-only guard"]
|
|
783
|
+
result = _make_result(
|
|
784
|
+
to_delete=to_delete, absent=absent, errors=errors, warnings=warnings,
|
|
785
|
+
)
|
|
786
|
+
|
|
787
|
+
for dry_run in (True, False):
|
|
788
|
+
output = _format_deletion_report(result, dry_run=dry_run, assume_yes=False)
|
|
789
|
+
if dry_run:
|
|
790
|
+
for rel in to_delete:
|
|
791
|
+
assert f" - {rel}" in output
|
|
792
|
+
for rel in absent:
|
|
793
|
+
assert f" - {rel}" in output
|
|
794
|
+
for e in errors:
|
|
795
|
+
assert f" - {e}" in output
|
|
796
|
+
for w in warnings:
|
|
797
|
+
assert f" - {w}" in output
|
{claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/tests/test_init_only_patterns.py
RENAMED
|
@@ -312,10 +312,10 @@ class TestDeletionsRespectInitOnly:
|
|
|
312
312
|
):
|
|
313
313
|
"""`c3 update` 入口(handle)を通しても INIT_ONLY が消えず、利用者が気づけること.
|
|
314
314
|
|
|
315
|
-
通常ファイル 1
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
315
|
+
通常ファイル 1 件の削除を混ぜているのは、INIT_ONLY 単独ではなく
|
|
316
|
+
混在ケースでも「弾いた事実が画面に出る」ことを回帰確認するため。
|
|
317
|
+
INIT_ONLY 単独ケース(`to_delete` が空になるケース)は
|
|
318
|
+
`test_handle_shows_warning_for_init_only_single_entry` を参照。
|
|
319
319
|
"""
|
|
320
320
|
from c3.cli_update import handle
|
|
321
321
|
|
|
@@ -362,6 +362,57 @@ class TestDeletionsRespectInitOnly:
|
|
|
362
362
|
)
|
|
363
363
|
assert self.GITIGNORE_REL in combined
|
|
364
364
|
|
|
365
|
+
def test_handle_shows_warning_for_init_only_single_entry(
|
|
366
|
+
self, tmp_path, monkeypatch, capsys
|
|
367
|
+
):
|
|
368
|
+
"""INIT_ONLY 単独ケース(`to_delete` が空になるケース)でも警告本文が画面に出ること.
|
|
369
|
+
|
|
370
|
+
`test_handle_does_not_delete_init_only_files` は通常ファイルを混ぜて
|
|
371
|
+
`to_delete` を非空にすることで既存実装でも warning が出るようにしている。
|
|
372
|
+
本テストは INIT_ONLY のみを deletions.txt に書き、`to_delete` が空になる
|
|
373
|
+
単独ケースを直接検証する(plan-report §B-1)。是正前の実装は `to_delete` が
|
|
374
|
+
空だと `deletions: nothing to delete` に畳んで warning 本文を出さなかったため、
|
|
375
|
+
本テストは是正前は赤だった(それが正しい)。
|
|
376
|
+
"""
|
|
377
|
+
from c3.cli_update import handle
|
|
378
|
+
|
|
379
|
+
claude_dir = tmp_path / ".claude"
|
|
380
|
+
template_dir = tmp_path / "fake_template"
|
|
381
|
+
for base in (claude_dir, template_dir):
|
|
382
|
+
base.mkdir(parents=True, exist_ok=True)
|
|
383
|
+
|
|
384
|
+
# 利用先に「育った」INIT_ONLY ファイルのみを置く(通常ファイルは混ぜない)
|
|
385
|
+
(claude_dir / "rules" / "promoted").mkdir(parents=True)
|
|
386
|
+
(claude_dir / self.PROMOTED_REL).write_text(self.PROMOTED_BODY, encoding="utf-8")
|
|
387
|
+
|
|
388
|
+
# 配布元が誤って INIT_ONLY を deletions.txt に追記してしまった状況
|
|
389
|
+
(template_dir / "deletions.txt").write_text(
|
|
390
|
+
f"{self.PROMOTED_REL}\n", encoding="utf-8"
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
monkeypatch.setattr("c3.cli_update.templates_dir", lambda: template_dir)
|
|
394
|
+
monkeypatch.setattr("c3.__version__", "2.58.0")
|
|
395
|
+
monkeypatch.setattr(
|
|
396
|
+
"builtins.input",
|
|
397
|
+
lambda _: (_ for _ in ()).throw(AssertionError("prompt must not fire with --yes")),
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
args = argparse.Namespace(
|
|
401
|
+
target=tmp_path, dry_run=False, platform="claude", yes=True
|
|
402
|
+
)
|
|
403
|
+
ret = handle(args)
|
|
404
|
+
assert ret == 0
|
|
405
|
+
|
|
406
|
+
# (a) 当該ファイルが消えていない
|
|
407
|
+
assert (claude_dir / self.PROMOTED_REL).read_text(encoding="utf-8") == self.PROMOTED_BODY
|
|
408
|
+
|
|
409
|
+
# (b) stdout に弾いた理由(warning 本文)が出る
|
|
410
|
+
captured = capsys.readouterr()
|
|
411
|
+
assert self.PROMOTED_REL in captured.out, (
|
|
412
|
+
"INIT_ONLY 単独ケースで弾いた理由が stdout に出ていない: "
|
|
413
|
+
f"out={captured.out!r} err={captured.err!r}"
|
|
414
|
+
)
|
|
415
|
+
|
|
365
416
|
|
|
366
417
|
class TestHandleUpdateIntegrationInitOnly:
|
|
367
418
|
"""`c3 update` 入口(handle)を通した e2e(code-review [CR-T-001]).
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/code-reviewer.md
RENAMED
|
File without changes
|
{claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/design-critic.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/project-setup.md
RENAMED
|
File without changes
|
{claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/security-reviewer.md
RENAMED
|
File without changes
|
{claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/systematic-debugger.md
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/agents/wt_developer.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/docs/parallel-agents-setup.md
RENAMED
|
File without changes
|
{claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/docs/platform-adapters.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/consolidate_memory.py
RENAMED
|
File without changes
|
{claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/patterns_guard.py
RENAMED
|
File without changes
|
{claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/permission_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_conductor-2.60.0 → claude_code_conductor-2.60.1}/.claude/hooks/planner_check.py
RENAMED
|
File without changes
|
|
File without changes
|