claude-code-conductor 2.47.0__tar.gz → 2.48.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/tier_autoapply.py +24 -1
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/dev-workflow/scripts/record_agent_outcome.py +94 -19
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/parallel-agents/SKILL.md +17 -11
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/CHANGELOG.md +17 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/PKG-INFO +1 -1
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/__init__.py +1 -1
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_record_agent_outcome.py +535 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_tier_autoapply.py +150 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_tier_gap_check.py +57 -0
- claude_code_conductor-2.48.0/tests/skills/test_parallel_agents_skill_tier.py +209 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/CLAUDE.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/agents/architect.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/agents/code-reviewer.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/agents/design-critic.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/agents/developer.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/agents/doc-writer.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/agents/interviewer.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/agents/planner.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/agents/project-setup.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/agents/security-reviewer.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/agents/systematic-debugger.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/agents/tester.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/agents/wt_developer.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/agents/wt_systematic-debugger.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/agents/wt_tester.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/breaking-changes.txt +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/deletions.txt +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/docs/config-policy.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/docs/parallel-agents-setup.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/docs/platform-adapters.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/docs/settings.json.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/_hook_utils.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/check_agent_invocation.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/consolidate_memory.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/permission_handler.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/permission_handler_toast.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/planner_check.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/post_tool.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/pre_compact.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/pre_tool.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/recall_autorebuild.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/recall_inject.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/restore_session.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/select_tier.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/session_start.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/session_stop.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/session_utils.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/statusline.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/stop.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/tier_gap_check.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/worktree_guard.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/memory/.gitkeep +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/permission_rules.json +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/rules/promoted/index.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/settings.json +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/brainstorm/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/codex-review/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/dev-workflow/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/dev-workflow/references/code-review-checklist.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/dev-workflow/references/design-critic-rubric.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/dev-workflow/references/design-rubric.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/dev-workflow/references/interview-rubric.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/dev-workflow/references/plan-design-guidelines.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/dev-workflow/references/security-review-checklist.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/dev-workflow/scripts/record_review_decision.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/dev-workflow/scripts/review_hint_inject.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/develop/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/doc/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/extract-lib/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/init-session/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/init-session/scripts/session_guard.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/mcp-config/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/pattern-status/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/promote-pattern/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/recall/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/report-timestamp/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/report-timestamp/scripts/get_timestamp.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/review-phase/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/setup/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/setup/reference.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/setup/templates/coding-standards-template.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/setup/templates/project-conventions-template.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/skills/start/SKILL.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/state/.gitkeep +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.gitignore +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/ARCHITECTURE.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/LICENSE +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/LICENSES/fastembed-LICENSE +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/LICENSES/fastembed-NOTICE +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/LICENSES/numpy-LICENSE +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/LICENSES/onnxruntime-LICENSE +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/LICENSES/paraphrase-multilingual-MiniLM-L12-v2-LICENSE +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/README.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/hatch_build.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/pyproject.toml +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/__main__.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/_db_params.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/_excludes.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/_terminal.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/adapters.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/cli.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/cli_ask.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/cli_doctor.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/cli_init.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/cli_list.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/cli_metrics.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/cli_plan.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/cli_recall.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/cli_tier.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/cli_update.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/db.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/embedding.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/gitutil.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/mcp_server.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/migrate.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/migrations/001_initial.sql +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/migrations/002_agent_cost_runs.sql +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/migrations/003_tier_cost.sql +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/migrations/004_agent_outcomes.sql +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/migrations/005_drop_agent_tier_bandit.sql +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/migrations/006_review_decisions_severity.sql +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/migrations/README.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/migrations/__init__.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/paths.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/plan_validator.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/platforms.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/pricing.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/question.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/recall_chunker.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/recall_index.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/src/c3/usage_ingester.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/__init__.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/_pre_compact_helpers.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/conftest.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/fixtures/usage/README.md +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/fixtures/usage/mainline.jsonl +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/fixtures/usage/subagents/agent-deadbeef.jsonl +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/fixtures/usage/subagents/agent-deadbeef.meta.json +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/__init__.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_check_agent_invocation.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_consolidate_memory.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_hook_utils.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_permission_handler.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_permission_handler_toast.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_pip_reinstall_reminder.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_planner_check.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_planner_check_dev.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_post_tool.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_pre_tool.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_recall_autorebuild.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_recall_inject.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_record_review_decision.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_restore_session.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_review_hint_inject.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_select_tier.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_select_tier_escalation.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_session_start.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_session_stop.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_session_utils.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_settings_local_absolute_paths.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_settings_tier_autoapply_registration.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_similarity_boost.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_statusline.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_statusline_template_sync.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_sync_check.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_template_guard.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/hooks/test_tier_security_fixes.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/skills/__init__.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/skills/_skill_helpers.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/skills/test_dev_workflow_no_task_type.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/skills/test_init_session_no_task_type.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/skills/test_planner_lightweight.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/skills/test_recall_skill.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/skills/test_session_backlog_reconciliation.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/skills/test_session_guard.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/skills/test_setup_templates.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/skills/test_start_skill_bugfix_flow.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/skills/test_start_skill_new_flow.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/skills/test_start_skill_security_audit_phase.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_adapters.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_check_deletions.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_cli_ask.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_cli_doctor.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_cli_entry.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_cli_init.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_cli_list.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_cli_metrics.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_cli_plan.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_cli_recall.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_cli_tier.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_cli_update_breaking_changes.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_cli_update_deletions.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_db.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_docstring_consistency.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_embedding.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_excludes.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_extract_breaking_changes.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_gitutil.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_mcp_server_elicit.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_migrate.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_paths.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_plan_validator.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_pre_compact.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_pre_tool_hook.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_precompact_additional.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_precompact_toctou_fixes.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_pricing.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_recall_chunker.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_recall_index.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_references_migration.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_session_utils_additional.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_skill_no_builtin_conflict.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_statusline.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_stop_additional.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_stop_hook.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_stop_precompact_fixes.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_sync_template_stop.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_template_pre_tool_hook.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_usage_ingester.py +0 -0
- {claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/tests/test_worktree_guard.py +0 -0
{claude_code_conductor-2.47.0 → claude_code_conductor-2.48.0}/.claude/hooks/tier_autoapply.py
RENAMED
|
@@ -18,6 +18,8 @@ check_agent は reviewer 系のみ)のため実行順序に依存しない(
|
|
|
18
18
|
- `LAUNCH_LOG_ROLES = {developer, wt_developer, tester, wt_tester}` は
|
|
19
19
|
注入有無に関わらず applied-state(tier_autoapply.jsonl)へ 1 行追記した。
|
|
20
20
|
reviewer 系・その他 role は記録も注入もしない(exit 0 素通り)。
|
|
21
|
+
- 起動プロンプト先頭の `C3_TASK_ID:` マーカーを抽出し jsonl の `task_id` に
|
|
22
|
+
載せた(T8・並列経路の record 突合キー)。
|
|
21
23
|
|
|
22
24
|
## 安全弁
|
|
23
25
|
|
|
@@ -97,6 +99,10 @@ _ROTATE_TAIL_LINES = 500
|
|
|
97
99
|
|
|
98
100
|
_PROMPT_PREFIX_MAX_CHARS = 200
|
|
99
101
|
|
|
102
|
+
# T8: 起動プロンプト先頭の C3_TASK_ID マーカー抽出用(§3-1)。行頭アンカー +
|
|
103
|
+
# allowlist + 上限200字で誤抽出・秘密混入を構造排除する(record MAX_TASK_LEN=200 と整合)。
|
|
104
|
+
_TASK_ID_MARKER_RE = re.compile(r'^C3_TASK_ID:[ ]([A-Za-z0-9._\-]{1,200})[ ]*$', re.MULTILINE)
|
|
105
|
+
|
|
100
106
|
|
|
101
107
|
def _load_pricing_module():
|
|
102
108
|
"""c3.pricing モジュールを返した(import 失敗時は None)。"""
|
|
@@ -167,6 +173,21 @@ def _clean_prompt_prefix(prompt: object) -> str:
|
|
|
167
173
|
return "".join(out)[:_PROMPT_PREFIX_MAX_CHARS]
|
|
168
174
|
|
|
169
175
|
|
|
176
|
+
def _extract_task_id(prompt: object) -> str | None:
|
|
177
|
+
"""起動プロンプトから C3_TASK_ID マーカー(最初の 1 個)を抽出した(§3)。
|
|
178
|
+
|
|
179
|
+
許容文字集合 [A-Za-z0-9._-]・行頭アンカー・上限200字で誤抽出と秘密混入を防ぐ。
|
|
180
|
+
prompt_prefix の mask→truncate パイプラインとは独立(正規表現自体がサニタイザ・§3-3)。
|
|
181
|
+
非文字列・不一致は None(→ jsonl は task_id: null で従来挙動・逐次経路も None)。
|
|
182
|
+
"""
|
|
183
|
+
if not isinstance(prompt, str):
|
|
184
|
+
return None
|
|
185
|
+
m = _TASK_ID_MARKER_RE.search(prompt)
|
|
186
|
+
if m is None:
|
|
187
|
+
return None
|
|
188
|
+
return m.group(1)
|
|
189
|
+
|
|
190
|
+
|
|
170
191
|
def _read_selection() -> dict | None:
|
|
171
192
|
"""tier_selection.json を読んだ(無い/壊れていれば None)。"""
|
|
172
193
|
if not os.path.isfile(TIER_SELECTION_PATH):
|
|
@@ -351,6 +372,7 @@ def main() -> None:
|
|
|
351
372
|
source = "frontmatter-default"
|
|
352
373
|
model_applied = None
|
|
353
374
|
|
|
375
|
+
prompt = tool_input.get("prompt")
|
|
354
376
|
row = {
|
|
355
377
|
"ts": datetime.now(timezone.utc).isoformat(timespec="seconds"),
|
|
356
378
|
"session_id": session_id,
|
|
@@ -358,7 +380,8 @@ def main() -> None:
|
|
|
358
380
|
"role_recorded": role_recorded,
|
|
359
381
|
"model_applied": model_applied,
|
|
360
382
|
"source": source,
|
|
361
|
-
"prompt_prefix": _clean_prompt_prefix(
|
|
383
|
+
"prompt_prefix": _clean_prompt_prefix(prompt),
|
|
384
|
+
"task_id": _extract_task_id(prompt),
|
|
362
385
|
}
|
|
363
386
|
_append_applied_state(row)
|
|
364
387
|
|
|
@@ -20,12 +20,22 @@ Usage:
|
|
|
20
20
|
|
|
21
21
|
| 優先 | ソース | 対象 |
|
|
22
22
|
|----|--------------------------------------------------|-------------------------------|
|
|
23
|
-
| 1 | --tier(明示・TIERS 検証) | 全 role
|
|
24
|
-
|
|
|
23
|
+
| 1 | --tier(明示・TIERS 検証) | 全 role(escape hatch・優先1 存続) |
|
|
24
|
+
| 2a | applied-state(session_id + role + task_id 全一致の最新行) | _SOFT_APPLY_ROLES(developer)かつ --task 指定時(T8・並列経路の task 突合) |
|
|
25
|
+
| 2b | applied-state(session_id + role 一致の最新行) | 同上・2a が 0 件 or --task 未指定時(現行の優先2=呼称のみ細分化) |
|
|
25
26
|
| 3 | tier_selection.json の tier→suggested_model | 同上・優先2 不成立時(フォールバック A 互換) |
|
|
26
27
|
| 4 | agents/{role}.md frontmatter model: | developer 以外、および 2・3 が不成立の developer |
|
|
27
28
|
| 5 | 解決不能 | 記録スキップ(stderr 警告 + exit 0) |
|
|
28
29
|
|
|
30
|
+
T8(architecture §5): 並列経路(wt_developer→developer)は起動プロンプトの
|
|
31
|
+
``C3_TASK_ID:`` マーカーを tier_autoapply.py が jsonl の task_id に載せ、record は
|
|
32
|
+
``--task`` 値と (session_id, role, task_id) 突合で実適用 tier を機械解決する(優先2a)。
|
|
33
|
+
これにより同一 session_id の複数 wt_developer を task 単位で一意分離し `--tier` 明示を
|
|
34
|
+
不要化した(ADR-AS-4 解消)。逐次経路は ``--task`` を渡すがマーカー未注入で全行
|
|
35
|
+
task_id=null のため優先2b で従来どおり解決する(挙動不変)。task 突合 0 件かつ当該
|
|
36
|
+
session/role に task_id 非 null 行が存在するとき(マーカー運用中の突合失敗)は record が
|
|
37
|
+
stderr へ 1 行警告する(§5-7・戻り値/exit code 不変の「警告のみ」)。
|
|
38
|
+
|
|
29
39
|
--execution=subagent かつ role が _SOFT_APPLY_ROLES に含まれる場合(現状
|
|
30
40
|
developer のみ)、--tier 省略時はまず applied-state を読む(優先2)。
|
|
31
41
|
フェーズ3で PreToolUse hook(tier_autoapply.py)が Agent 起動時の実適用
|
|
@@ -42,9 +52,9 @@ Usage:
|
|
|
42
52
|
推奨 Tier と異なる場合は必ず --tier に実際の tier を付す運用を dev-workflow
|
|
43
53
|
SKILL.md 側が担う(本スクリプトは優先 1 で受けるのみでコード変更は無い)。
|
|
44
54
|
並列(worktree isolation)経路は wt_developer→developer の記録を親 Claude
|
|
45
|
-
が main
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
が main リポジトリで実行するが、T8 以降は --tier を明示せず C3_TASK_ID:
|
|
56
|
+
マーカー由来の task_id を --task と (session_id, role, task_id) 突合して
|
|
57
|
+
優先2a で機械解決する(上記 L27-37 の新記述に一本化。ADR-AS-4 解消済み)。
|
|
48
58
|
--execution=persona は --tier 省略時、frontmatter へも tier_selection.json
|
|
49
59
|
へも fallback せず常に tier="unknown" 固定でイベントログのみ記録する
|
|
50
60
|
(frontmatter/tier_selection は subagent の実使用 tier であり、persona の
|
|
@@ -379,27 +389,49 @@ def _iter_applied_state_capped_lines(path: str):
|
|
|
379
389
|
yield raw.decode("utf-8", errors="replace")
|
|
380
390
|
|
|
381
391
|
|
|
382
|
-
def _read_applied_tier(
|
|
383
|
-
|
|
392
|
+
def _read_applied_tier(
|
|
393
|
+
session_id: str | None, role: str, c3_pricing, task: str | None = None
|
|
394
|
+
) -> str | None:
|
|
395
|
+
"""applied-state(tier_autoapply.jsonl)から実適用 tier を解決する(優先2・§5)。
|
|
384
396
|
|
|
385
397
|
フェーズ3で PreToolUse hook(tier_autoapply.py)が Agent 起動時の実適用値を
|
|
386
398
|
session_id・role_recorded 付きで JSONL 追記する。record はこれを session_id
|
|
387
399
|
一致で読むことで「適用者=記録 SSOT」を成立させる(tier_selection.json の
|
|
388
400
|
推奨値を読む優先3 より優先する)。
|
|
389
401
|
|
|
402
|
+
優先2 の内部細分(T8・architecture §5-4。優先1/3/4 の体系は不変):
|
|
403
|
+
- 優先2a(task-exact): ``task`` 指定時、(session_id, role_recorded, task_id)
|
|
404
|
+
全一致の最新行を優先する。並列 wave(parallel-agents)で同一 session_id の
|
|
405
|
+
複数 wt_developer を task_id で一意分離し、`--tier` 明示なしに実適用 tier を
|
|
406
|
+
機械解決する(ADR-AS-4 解消)。task_id は起動プロンプトの ``C3_TASK_ID:``
|
|
407
|
+
マーカーを tier_autoapply.py が抽出して jsonl に載せた値。
|
|
408
|
+
- 優先2b(session-latest): 優先2a が 0 件、または ``task`` 未指定(task=None)の
|
|
409
|
+
とき、(session_id, role_recorded) 一致の最新行(現行ロジックそのもの)を採用する。
|
|
410
|
+
- 後方互換: ``task=None`` では優先2a 候補が常に None のまま → 現行と bit 一致。
|
|
411
|
+
逐次経路は ``--task {plan タスクID}`` を渡すが ``C3_TASK_ID:`` マーカーを注入
|
|
412
|
+
しないため jsonl 全行が task_id=null で、優先2b で従来どおり解決される(挙動不変)。
|
|
413
|
+
|
|
390
414
|
突合規則(_read_selection() と同じ防御思想):
|
|
391
415
|
- APPLIED_STATE_PATH 不在なら None。
|
|
392
416
|
- session_id が None なら None(突合不能・§0-4 の NULL 制約。session_id
|
|
393
417
|
NULL の行同士を突き合わせない)。
|
|
394
418
|
- 行単位で json.loads し、壊れ行は skip(try/except continue)。
|
|
395
|
-
- session_id 一致 かつ role_recorded == role
|
|
396
|
-
|
|
419
|
+
- session_id 一致 かつ role_recorded == role の行を 1 パスで走査し、優先2b
|
|
420
|
+
候補(session+role 最新)と優先2a 候補(task 一致の最新)を同時収集する。
|
|
397
421
|
- model_applied 非文字列(int/list/dict 等)は skip(resolve_tier の
|
|
398
422
|
内部 .lower() による AttributeError 防止。soft-apply 側 L566-574 と同理由)。
|
|
399
423
|
source=frontmatter-default(model_applied=null)の行は tier を持たない
|
|
400
424
|
ため自然に skip される。
|
|
401
425
|
- resolve_tier で正規化し _VALID_TIERS に含まれれば返す。
|
|
402
426
|
|
|
427
|
+
§5-7 additive 警告ガード(ADR-T8-9・C-3 R2 反映: DC-T8-AS-003):
|
|
428
|
+
- ``task`` 指定・優先2a 0 件・かつ当該 (session_id, role) に task_id 非 null 行が
|
|
429
|
+
1 件以上存在する(``saw_task_id_row`` 真=マーカー運用中)ときのみ、stderr へ
|
|
430
|
+
1 行の英語警告を出す(マーカー未注入 or task 表記ゆれ or tier 未注入による真の
|
|
431
|
+
突合失敗の可視化)。全行 task_id=null(=マーカー未運用の純逐次)や task=None
|
|
432
|
+
では発火しない(逐次 crying-wolf 回避)。
|
|
433
|
+
- 警告のみで戻り値・exit code・chosen の決定式は一切変えない(fail-safe 不変)。
|
|
434
|
+
|
|
403
435
|
Returns:
|
|
404
436
|
解決できた正規化 tier 文字列、または解決不能なら None。
|
|
405
437
|
"""
|
|
@@ -414,8 +446,12 @@ def _read_applied_tier(session_id: str | None, role: str, c3_pricing) -> str | N
|
|
|
414
446
|
or os.path.islink(APPLIED_STATE_PATH)
|
|
415
447
|
):
|
|
416
448
|
return None
|
|
417
|
-
|
|
418
|
-
|
|
449
|
+
# 1 パス 2 候補収集(architecture §5-2・GP-003: 既存ループを土台に候補を 2 本化)。
|
|
450
|
+
latest_session_model: str | None = None # 優先2b(session+role 最新・現行ロジック)
|
|
451
|
+
latest_session_ts: str | None = None
|
|
452
|
+
latest_task_model: str | None = None # 優先2a(session+role+task 全一致の最新)
|
|
453
|
+
latest_task_ts: str | None = None
|
|
454
|
+
saw_task_id_row = False # 当該 (session_id, role) に task_id 非 null 行が存在するか(§5-7)
|
|
419
455
|
try:
|
|
420
456
|
# item5(SR-NEW): 末尾優先で最大 5MB のみ走査する(_iter_applied_state_capped_lines)。
|
|
421
457
|
for line in _iter_applied_state_capped_lines(APPLIED_STATE_PATH):
|
|
@@ -432,6 +468,11 @@ def _read_applied_tier(session_id: str | None, role: str, c3_pricing) -> str | N
|
|
|
432
468
|
continue
|
|
433
469
|
if row.get("role_recorded") != role:
|
|
434
470
|
continue
|
|
471
|
+
# §5-7: マーカー運用中の検出。model_applied 非文字列ガードより前に判定
|
|
472
|
+
# する(frontmatter-default 行〈model_applied=null〉でも task_id が
|
|
473
|
+
# 非 null なら運用中と見なす。追加走査コストゼロ)。
|
|
474
|
+
if row.get("task_id") is not None:
|
|
475
|
+
saw_task_id_row = True
|
|
435
476
|
model_applied = row.get("model_applied")
|
|
436
477
|
if not isinstance(model_applied, str):
|
|
437
478
|
continue
|
|
@@ -440,18 +481,48 @@ def _read_applied_tier(session_id: str | None, role: str, c3_pricing) -> str | N
|
|
|
440
481
|
# 最新(ts 最大)を採用。ts 同値/欠落時は後勝ち(末尾側)で
|
|
441
482
|
# 上書きするため >= で比較する。ts プロファイルは
|
|
442
483
|
# tier_autoapply.py と同一 UTC 秒精度 ISO8601(辞書順=時系列)。
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
484
|
+
# 優先2b 候補(session+role 最新)=現行ロジックそのもの。
|
|
485
|
+
if latest_session_ts is None or ts_key >= latest_session_ts:
|
|
486
|
+
latest_session_ts = ts_key
|
|
487
|
+
latest_session_model = model_applied
|
|
488
|
+
# 優先2a 候補(task 指定時のみ・session+role+task 全一致の最新)。
|
|
489
|
+
if task is not None and row.get("task_id") == task:
|
|
490
|
+
if latest_task_ts is None or ts_key >= latest_task_ts:
|
|
491
|
+
latest_task_ts = ts_key
|
|
492
|
+
latest_task_model = model_applied
|
|
446
493
|
except OSError as exc:
|
|
447
494
|
print(
|
|
448
495
|
f"[record_agent_outcome] failed to read applied-state: {exc}",
|
|
449
496
|
file=sys.stderr,
|
|
450
497
|
)
|
|
451
498
|
return None
|
|
452
|
-
|
|
499
|
+
# 決定: task-exact(優先2a)を優先し、0 件なら session-latest(優先2b)へ。
|
|
500
|
+
chosen = latest_task_model if latest_task_model is not None else latest_session_model
|
|
501
|
+
# §5-7 additive 警告: task 指定・優先2a 0 件・かつマーカー運用中(saw_task_id_row 真)
|
|
502
|
+
# のときのみ 1 行警告する(戻り値/exit code/chosen は不変・fail-safe 不変)。
|
|
503
|
+
# 安全性根拠(SR-K-003 解消): --task 値(task 変数)自体は allowlist 検証を受けない。
|
|
504
|
+
# allowlist([A-Za-z0-9._\-])が適用されるのは tier_autoapply.py の task_id 抽出
|
|
505
|
+
# 経路のみで、--task CLI 引数経路には存在しない(_truncate は文字数/バイト数の
|
|
506
|
+
# 切り詰めのみで文字種検証はしない)。この警告文の安全性は下記の二段で担保する:
|
|
507
|
+
# (1) _mask_secrets(task) で既知の秘密パターン(token=/api_key=/Bearer/PEM 等)を
|
|
508
|
+
# *** に潰す(allowlist 非検証の --task に秘密様文字列が混入しても stderr へ
|
|
509
|
+
# 生の秘密を出さない・display-only)。
|
|
510
|
+
# (2) その結果を {...!r} で repr エスケープする(制御文字・改行・引用符混入時も
|
|
511
|
+
# 1 行維持・インジェクション不成立)。
|
|
512
|
+
# マスクは警告表示だけに閉じる(chosen 決定・突合・DB note は生の task を使う)。
|
|
513
|
+
# 将来 !r を !s 等へ変更する/_mask_secrets 適用を外すリファクタが入るとこの前提
|
|
514
|
+
# (二段防御)が崩れるため、_mask_secrets(task) + !r 依存であることに留意する。
|
|
515
|
+
if task is not None and latest_task_model is None and saw_task_id_row:
|
|
516
|
+
print(
|
|
517
|
+
f"[record_agent_outcome] --task {_mask_secrets(task)!r} specified but no matching "
|
|
518
|
+
"(session,role,task) row in applied-state though task_id rows exist "
|
|
519
|
+
"for this session/role; falling back to session-latest (priority 2b). "
|
|
520
|
+
"marker not injected or task mismatch?",
|
|
521
|
+
file=sys.stderr,
|
|
522
|
+
)
|
|
523
|
+
if chosen is None:
|
|
453
524
|
return None
|
|
454
|
-
resolved = c3_pricing.resolve_tier(
|
|
525
|
+
resolved = c3_pricing.resolve_tier(chosen)
|
|
455
526
|
if resolved in _VALID_TIERS:
|
|
456
527
|
return resolved
|
|
457
528
|
return None
|
|
@@ -698,14 +769,18 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
698
769
|
# 一致で読む。role が soft-apply 対象のときのみ突合する(tester 等は
|
|
699
770
|
# _SOFT_APPLY_ROLES 外なので applied-state を読まない・role gating)。
|
|
700
771
|
if role in _SOFT_APPLY_ROLES:
|
|
701
|
-
|
|
772
|
+
# T8: 切り詰め済み task を突合キーとして配線(優先2a)。task=None の
|
|
773
|
+
# 従来呼び出し・逐次経路(マーカー未注入)は優先2b で従来どおり解決。
|
|
774
|
+
tier = _read_applied_tier(session_id, role, c3_pricing, task=task)
|
|
702
775
|
# 優先 3(降格・旧優先2): role が soft-apply 対象(_SOFT_APPLY_ROLES)なら
|
|
703
776
|
# tier_selection.json の tier(無ければ suggested_model)を
|
|
704
777
|
# resolve_tier で正規化し、_VALID_TIERS に含まれれば採用する。
|
|
705
778
|
# 優先2(applied-state)が不成立のとき(applied-state 不在/session_id
|
|
706
779
|
# 不一致/kill-switch で jsonl に行が無い等)のフォールバック A 互換。
|
|
707
|
-
# 逐次経路(worktree
|
|
708
|
-
# --tier
|
|
780
|
+
# 逐次経路(worktree なし)はマーカー未注入で優先2b により解決される。
|
|
781
|
+
# 並列(worktree)経路は T8 以降 --tier を渡さないため、task_id 突合
|
|
782
|
+
# (優先2a/2b)が不成立の場合はこの優先3フォールバックに到達しうる
|
|
783
|
+
# (ADR-AS-4 解消後は「ここには来ない」という言い切りは成立しない)。
|
|
709
784
|
if tier is None and role in _SOFT_APPLY_ROLES and selection is not None:
|
|
710
785
|
soft_apply_raw = selection.get("tier") or selection.get("suggested_model")
|
|
711
786
|
# 非文字列ガード: resolve_tier() は内部で無条件に model.lower() を
|
|
@@ -164,6 +164,14 @@ plan-report 承認時点で全タスク・agent・writes・prompt が確認済
|
|
|
164
164
|
Bash でまず以下を実行: `export PO_WORKTREE_GUARD=1`(worktree_guard.py PreToolUse が worktree 外書き込みをブロックする条件)
|
|
165
165
|
```
|
|
166
166
|
worktree_guard.py はこの env 未設定時 `sys.exit(0)` で完全無効化されるため、wt_* agent 起動プロンプトの先頭で必ず設定すること。
|
|
167
|
+
- **全 `read_only: false` タスク(wt_developer / wt_tester): プロンプト先頭付近(PO_WORKTREE_GUARD の Bash 行の直後・タスク本文の前)に機械可読マーカー行を必須で 1 行含める**:
|
|
168
|
+
```
|
|
169
|
+
C3_TASK_ID: {task_id}
|
|
170
|
+
```
|
|
171
|
+
- `{task_id}` は `description`(タスク id)および record の `--task` に渡す値と**完全一致**させる(英数と `.` `_` `-` のみ・200 字以内)。
|
|
172
|
+
- この行を PreToolUse hook(`tier_autoapply.py`)が抽出し applied-state(`tier_autoapply.jsonl`)の `task_id` に記録する。record が `--task` と突合して適用 tier を機械解決するための入力キー。
|
|
173
|
+
- **三者一致の責務は親 Claude が負う**: マーカー値 `C3_TASK_ID: {task_id}`・`description`(タスク id)・record `--task {task_id}` の三者は、**親 Claude が同一の `task_id` 変数から 3 箇所(description / C3_TASK_ID マーカー / record `--task`)へ転記**し、大小・末尾空白・省略の表記ゆれを生じさせない(by convention の保証者を明文化)。転記ミス時の静かな優先2b フォールバックは record 側の stderr 警告で検知する二段構え。
|
|
174
|
+
- **不均質 wave ではマーカー注入が必須**: escape hatch として一部タスクに `model:` を明示し wave 内で tier が不均質になる場合、マーカー欠落で優先2b に落ちると 2b は task を無視して session+role 最新の 1 行を拾うため、**別タスクの tier を誤帰属しうる**。均質 wave では顕在化しないが、`model:` 明示混在の**不均質 wave ではマーカー欠落=誤帰属リスクのためマーカー注入を必須**とする。
|
|
167
175
|
- タスクの `prompt` 本文
|
|
168
176
|
- 「**禁止事項: git add / git commit / git push を実行しないこと**。コミットは親 Claude がユーザー承認後に行う」
|
|
169
177
|
- 「**返り値フォーマット厳守**:
|
|
@@ -215,19 +223,18 @@ worktree path は Agent ツール返り値の `<worktree><worktreePath>...</work
|
|
|
215
223
|
|
|
216
224
|
**tier-routing 結果記録(失敗タスク)**: 選択肢に関わらず、この wave で失敗した各タスクのうち `wt_developer`/`wt_tester` で起動したものについて、1 タスク = 1 記録で failure を記録する(`wt_developer`→`--role developer`、`wt_tester`→`--role tester`。`--execution subagent`)。`code-reviewer`/`security-reviewer`/`wt_systematic-debugger` のタスクは記録対象外。この記録は親 Claude が **main リポジトリ(2-F-0 の `cd <ROOT>` 後)で実行**する。**「スキップして次の wave へ」を選んだ場合も、次の wave に進む前に必ずこの記録を済ませること**(`--complexity` は dev-workflow 開始時の `[tier-routing 推奨]` 表示の複雑度をそのまま渡す。「リトライ」を選び再実行が成功した場合は 1 タスク 1 記録の原則により 2-F-4 で改めて success を記録する=リトライ結果は新たな別記録になる)。
|
|
217
225
|
|
|
218
|
-
|
|
219
|
-
- `wt_developer`→`developer` の記録は **`--tier
|
|
226
|
+
**tier 記録ルール(ADR-AS-4 解消・applied-state task_id 突合)**:
|
|
227
|
+
- `wt_developer`→`developer` の記録は **`--tier` を付けない**。起動時に PreToolUse hook(`tier_autoapply`)が applied-state(`tier_autoapply.jsonl`)に記録した実適用 tier を、record が `(session_id, role, task_id)` 突合で機械解決する(優先2a)。**`--task {task_id}` は突合キーとして必須**であり、2-C のマーカー `C3_TASK_ID: {task_id}` と完全一致させる。**従来 `--task` は dedupe 専用の任意引数だったが、T8 で突合の必須キーへ役割が変わる**(未注入だと優先2b フォールバック=session_id 一致だけの曖昧解決に戻り、並列で誤 tier 帰属リスクが残る)。applied-state の `task_id` 突合により、並列 wave 内の複数 wt_developer が同一 session_id でも task 単位で**一意**に実適用 tier を解決できる(ADR-AS-4 解消・T8)。hook の書き込み先が main の `.claude/state/` であること(cwd リーク下でも `__file__` 基準で不変)は T4 E2E で実測確認済み(2026-07-07・並列 wt_developer×2 で worktree 側 jsonl 0 件・main 側 2 行・record が `--tier` なしで正解 tier を機械解決)。
|
|
220
228
|
- `wt_tester`→`tester` の記録は **`--tier` を付けない**(frontmatter 解決のまま不変。tester は機械適用対象外)。
|
|
221
229
|
|
|
222
230
|
```bash
|
|
223
|
-
# wt_developer→developer
|
|
231
|
+
# wt_developer→developer(tier フラグは付けない・applied-state task 突合で機械解決)
|
|
224
232
|
python .claude/skills/dev-workflow/scripts/record_agent_outcome.py \
|
|
225
233
|
--role developer --outcome failure --gate 2-E \
|
|
226
234
|
--execution subagent --complexity {セッションファイルの tier-routing複雑度: 行の値} \
|
|
227
|
-
--
|
|
228
|
-
--task {task_id}
|
|
235
|
+
--task {task_id} # ← 2-C の C3_TASK_ID マーカーと完全一致・突合の必須キー
|
|
229
236
|
|
|
230
|
-
# wt_tester→tester
|
|
237
|
+
# wt_tester→tester(tier フラグは付けない・frontmatter 解決)
|
|
231
238
|
python .claude/skills/dev-workflow/scripts/record_agent_outcome.py \
|
|
232
239
|
--role tester --outcome failure --gate 2-E \
|
|
233
240
|
--execution subagent --complexity {セッションファイルの tier-routing複雑度: 行の値} \
|
|
@@ -320,17 +327,16 @@ git branch -D worktree-agent-{id}
|
|
|
320
327
|
|
|
321
328
|
**tier-routing 結果記録(成功タスクのみ)**: この wave で成功した各タスクのうち `wt_developer`/`wt_tester` で起動したものについて、1 タスク = 1 記録で success を記録する(`wt_developer`→`--role developer`、`wt_tester`→`--role tester`。`--execution subagent`)。`code-reviewer`/`security-reviewer`/`wt_systematic-debugger` のタスクは記録対象外(`--complexity` は dev-workflow 開始時の `[tier-routing 推奨]` 表示の複雑度をそのまま渡す)。この記録は親 Claude が **main リポジトリ(2-F-0 の `cd <ROOT>` 後)で実行**する。
|
|
322
329
|
|
|
323
|
-
|
|
330
|
+
**tier 記録ルール(ADR-AS-4 解消・2-E と同一)**: `wt_developer`→`developer` は **`--tier` を付けない**。起動時に hook(`tier_autoapply`)が applied-state(`tier_autoapply.jsonl`)に記録した実適用 tier を、record が `(session_id, role, task_id)` 突合で機械解決する(優先2a)。**`--task {task_id}` は突合キーとして必須**であり、2-C のマーカー `C3_TASK_ID: {task_id}` と完全一致させる(従来 `--task` は dedupe 専用の任意引数だったが、T8 で突合の必須キーへ役割が変わる)。applied-state の `task_id` 突合により、同一 session_id の複数 wt_developer を task 単位で**一意**に分離できる(ADR-AS-4 解消・T8)。hook の書き込み先が main の `.claude/state/` であること(cwd リーク下でも `__file__` 基準で不変)は T4 E2E で実測確認済み(2026-07-07・並列 wt_developer×2 で worktree 側 jsonl 0 件・main 側 2 行・record が `--tier` なしで正解 tier を機械解決)。 `wt_tester`→`tester` は **`--tier` を付けない**(frontmatter 解決のまま不変・機械適用対象外)。
|
|
324
331
|
|
|
325
332
|
```bash
|
|
326
|
-
# wt_developer→developer
|
|
333
|
+
# wt_developer→developer(tier フラグは付けない・applied-state task 突合で機械解決)
|
|
327
334
|
python .claude/skills/dev-workflow/scripts/record_agent_outcome.py \
|
|
328
335
|
--role developer --outcome success --gate 2-D \
|
|
329
336
|
--execution subagent --complexity {セッションファイルの tier-routing複雑度: 行の値} \
|
|
330
|
-
--
|
|
331
|
-
--task {task_id}
|
|
337
|
+
--task {task_id} # ← 2-C の C3_TASK_ID マーカーと完全一致・突合の必須キー
|
|
332
338
|
|
|
333
|
-
# wt_tester→tester
|
|
339
|
+
# wt_tester→tester(tier フラグは付けない・frontmatter 解決)
|
|
334
340
|
python .claude/skills/dev-workflow/scripts/record_agent_outcome.py \
|
|
335
341
|
--role tester --outcome success --gate 2-D \
|
|
336
342
|
--execution subagent --complexity {セッションファイルの tier-routing複雑度: 行の値} \
|
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.48.0] - 2026-07-07
|
|
4
|
+
|
|
5
|
+
### 追加
|
|
6
|
+
|
|
7
|
+
- **並列経路の record `--tier` 明示を不要化(T8・ADR-AS-4 解消)**: applied-state(`.claude/state/tier_autoapply.jsonl`)に `task_id` フィールドを追加し、`record_agent_outcome.py` が `(session_id, role, task_id)` の全一致で実適用 tier を一意解決できるようにした(優先2a)。並列 wave 内の複数 wt_developer が同一 session_id でも task 単位で分離される。task 一致行が 0 件なら従来の「session 最新行」(優先2b)へフォールバックし後方互換(task 未指定の逐次経路は挙動 bit 一致)。`--tier` 明示は優先1 の escape hatch として存続
|
|
8
|
+
- **`C3_TASK_ID:` マーカー**: parallel-agents skill の起動プロンプトに機械可読マーカー行(`C3_TASK_ID: {task_id}`)を必須注入し、`tier_autoapply.py` が行頭アンカー+厳格書式(`[A-Za-z0-9._-]{1,200}`・first-match)で抽出して jsonl に記録する。allowlist が制御文字・秘密情報パターンを構造的に排除(誤抽出・秘密混入・ReDoS 耐性を security-review で確認済み)。マーカー不在(逐次経路等)は `task_id: null` で従来挙動
|
|
9
|
+
- **2b フォールバック警告(additive)**: record が `--task` 指定かつ task 一致 0 件かつ当該 session/role に task_id 非 null 行が存在する場合のみ、stderr に 1 行警告(マーカー運用中の真の突合失敗に限定・純逐次 0 回・並列正常 0 回の発火設計・警告のみで戻り値/exit code 不変・task 値は `_mask_secrets`+repr の二段防御で表示)
|
|
10
|
+
|
|
11
|
+
### 変更
|
|
12
|
+
|
|
13
|
+
- parallel-agents SKILL.md: 2-E / 2-F-4 の wt_developer 向け `--tier` 付与ルールと bash 例を撤去し「applied-state task 突合で機械解決・`--task` は突合の必須キー」に一本化。2-C にマーカー注入手順(三者一致責務: 親 Claude が同一 task_id 変数から description / マーカー / `--task` へ転記)と不均質 wave でのマーカー必須性を明記。wt_tester の「`--tier` を付けない」は不変
|
|
14
|
+
- 旧 ADR-AS-4 注記(「worktree state 分離で session_id 一致でも読めないことがある」)は E2E 実測(並列 wt_developer×2)で反証し解消形に更新: hook の書き込み先は cwd リーク下でも `__file__` 基準で常に main の `.claude/state/`(worktree 側 jsonl 0 件を実測確認)
|
|
15
|
+
|
|
16
|
+
### 後方互換
|
|
17
|
+
|
|
18
|
+
- 全て additive(jsonl はキー追加のみ・既存 7 フィールド不変・読者 `tier_gap_check.py` は無改修で耐性確認済み・record は task 未指定経路が bit 一致・DB migration なし)。既存 fail-safe(kill-switch `C3_TIER_AUTOAPPLY_DISABLE`・全例外 exit 0・壊れ行 skip・5MB 上限・symlink 防御)は不変。**破壊的変更なし**
|
|
19
|
+
|
|
3
20
|
## [2.47.0] - 2026-07-07
|
|
4
21
|
|
|
5
22
|
### 追加
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-code-conductor
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.48.0
|
|
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
|