claude-code-conductor 2.22.0__tar.gz → 2.24.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.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/select_tier.py +146 -11
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/CHANGELOG.md +53 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/PKG-INFO +1 -1
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/__init__.py +1 -1
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/cli_tier.py +29 -5
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/db.py +268 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/pricing.py +41 -0
- claude_code_conductor-2.24.0/tests/hooks/test_select_tier.py +1082 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_cli_tier.py +385 -1
- claude_code_conductor-2.24.0/tests/test_db.py +1322 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_pricing.py +46 -1
- claude_code_conductor-2.22.0/tests/hooks/test_select_tier.py +0 -495
- claude_code_conductor-2.22.0/tests/test_db.py +0 -518
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/CLAUDE.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/agents/architect.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/agents/code-reviewer.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/agents/developer.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/agents/doc-writer.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/agents/interviewer.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/agents/planner.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/agents/project-setup.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/agents/security-reviewer.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/agents/systematic-debugger.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/agents/tester.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/agents/wt_developer.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/agents/wt_systematic-debugger.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/agents/wt_tester.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/breaking-changes.txt +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/deletions.txt +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/docs/config-policy.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/docs/parallel-agents-setup.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/docs/platform-adapters.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/docs/settings.json.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/_hook_utils.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/check_agent_invocation.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/consolidate_memory.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/permission_handler.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/permission_handler_toast.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/planner_check.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/post_tool.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/pre_compact.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/pre_tool.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/recall_inject.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/restore_session.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/session_start.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/session_stop.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/session_utils.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/statusline.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/stop.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/hooks/worktree_guard.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/memory/.gitkeep +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/permission_rules.json +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/rules/promoted/index.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/settings.json +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/codex-review/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/dev-workflow/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/dev-workflow/references/code-review-checklist.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/dev-workflow/references/plan-design-guidelines.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/dev-workflow/references/security-review-checklist.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/dev-workflow/scripts/record_review_decision.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/dev-workflow/scripts/record_tier_outcome.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/dev-workflow/scripts/review_hint_inject.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/develop/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/doc/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/extract-lib/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/init-session/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/mcp-config/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/parallel-agents/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/pattern-status/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/promote-pattern/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/recall/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/report-timestamp/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/report-timestamp/scripts/get_timestamp.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/review-phase/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/setup/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/setup/reference.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/setup/templates/coding-standards-template.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/setup/templates/project-conventions-template.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/skills/start/SKILL.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.claude/state/.gitkeep +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/.gitignore +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/LICENSE +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/LICENSES/chroma-hnswlib-LICENSE +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/LICENSES/chroma-hnswlib-NOTICE +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/LICENSES/fastembed-LICENSE +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/LICENSES/fastembed-NOTICE +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/LICENSES/onnxruntime-LICENSE +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/LICENSES/paraphrase-multilingual-MiniLM-L12-v2-LICENSE +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/README.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/hatch_build.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/pyproject.toml +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/__main__.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/_excludes.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/_terminal.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/adapters.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/cli.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/cli_ask.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/cli_doctor.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/cli_init.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/cli_list.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/cli_plan.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/cli_recall.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/cli_update.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/embedding.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/mcp_server.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/migrate.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/migrations/001_initial.sql +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/migrations/002_agent_cost_runs.sql +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/migrations/003_tier_cost.sql +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/migrations/README.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/migrations/__init__.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/paths.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/plan_validator.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/platforms.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/question.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/recall_chunker.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/recall_index.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/src/c3/usage_ingester.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/__init__.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/conftest.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/fixtures/usage/README.md +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/fixtures/usage/mainline.jsonl +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/fixtures/usage/subagents/agent-deadbeef.jsonl +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/fixtures/usage/subagents/agent-deadbeef.meta.json +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/__init__.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_check_agent_invocation.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_consolidate_memory.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_hook_utils.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_permission_handler.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_permission_handler_toast.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_pip_reinstall_reminder.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_planner_check.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_planner_check_dev.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_post_tool.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_pre_tool.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_recall_inject.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_record_review_decision.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_record_tier_outcome.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_restore_session.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_review_hint_inject.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_select_tier_escalation.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_session_start.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_session_stop.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_session_utils.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_settings_local_absolute_paths.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_similarity_boost.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_statusline.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_statusline_template_sync.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_sync_check.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/hooks/test_template_guard.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/skills/__init__.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/skills/_skill_helpers.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/skills/test_dev_workflow_no_task_type.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/skills/test_init_session_no_task_type.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/skills/test_planner_lightweight.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/skills/test_recall_skill.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/skills/test_session_backlog_reconciliation.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/skills/test_setup_templates.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/skills/test_start_skill_bugfix_flow.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/skills/test_start_skill_new_flow.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/skills/test_start_skill_security_audit_phase.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_adapters.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_cli_ask.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_cli_entry.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_cli_init.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_cli_list.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_cli_plan.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_cli_recall.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_cli_update_breaking_changes.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_cli_update_deletions.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_docstring_consistency.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_embedding.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_excludes.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_extract_breaking_changes.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_mcp_server_elicit.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_migrate.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_paths.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_plan_validator.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_pre_compact.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_pre_tool_hook.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_precompact_additional.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_precompact_toctou_fixes.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_recall_chunker.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_recall_index.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_references_migration.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_session_utils_additional.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_skill_no_builtin_conflict.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_statusline.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_stop_additional.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_stop_hook.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_stop_precompact_fixes.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_sync_template_stop.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_template_pre_tool_hook.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_usage_ingester.py +0 -0
- {claude_code_conductor-2.22.0 → claude_code_conductor-2.24.0}/tests/test_worktree_guard.py +0 -0
|
@@ -31,6 +31,7 @@ import os
|
|
|
31
31
|
import random
|
|
32
32
|
import re
|
|
33
33
|
import sys
|
|
34
|
+
from typing import NamedTuple
|
|
34
35
|
from pathlib import Path
|
|
35
36
|
|
|
36
37
|
try:
|
|
@@ -110,6 +111,69 @@ _PROMPT_HISTORY_SCAN_LINES = 1000
|
|
|
110
111
|
|
|
111
112
|
TIERS: tuple[str, ...] = ("haiku", "sonnet", "opus")
|
|
112
113
|
|
|
114
|
+
# cost-aware tie-break の拮抗判定閾値(v2.23.0)。
|
|
115
|
+
# Beta サンプルは 0〜1 スケール。成功率 5pt 以内=実質同等とみなす拮抗判定閾値。
|
|
116
|
+
# 過大は成功率犠牲リスク、過小は無発動。調整可能化は v2.24.0。
|
|
117
|
+
EPSILON: float = 0.05
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class SelectionResult(NamedTuple):
|
|
121
|
+
"""select_tier_detailed の戻り値(NamedTuple = immutable)。
|
|
122
|
+
|
|
123
|
+
tier: 選択された tier 名。
|
|
124
|
+
mode: "uniform" または "thompson"。
|
|
125
|
+
cost_tiebreak: Thompson 分岐で cost tie-break が発動した場合 True。
|
|
126
|
+
contenders: 拮抗判定に入った tier のタプル(observability/デバッグ用)。
|
|
127
|
+
frozen 安全のため list ではなく tuple を使用。
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
tier: str
|
|
131
|
+
mode: str
|
|
132
|
+
cost_tiebreak: bool = False
|
|
133
|
+
contenders: tuple[str, ...] = ()
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _cost_tiebreak(
|
|
137
|
+
samples: dict[str, float],
|
|
138
|
+
cost_map: dict[str, float] | None,
|
|
139
|
+
*,
|
|
140
|
+
epsilon: float = EPSILON,
|
|
141
|
+
) -> tuple[str, bool, tuple[str, ...]]:
|
|
142
|
+
"""Thompson サンプル拮抗群内で min-max 正規化コストが最安の tier を返す。
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
samples: {tier: beta_sample} の dict(Thompson Sampling 結果)。
|
|
146
|
+
cost_map: {tier: cost} の dict。None なら cost を見ず従来挙動。
|
|
147
|
+
cost は実測 rate_usd_per_mtok または静的参照単価(ハイブリッド)。
|
|
148
|
+
v2.24.0 で rate 化(USD/MTok)により実測・静的とも同次元で整合済み。
|
|
149
|
+
``cost_map`` は None、または contenders 全件をキーとして含む dict を
|
|
150
|
+
渡すこと。partial dict を渡すと ``cost_map[t]`` で KeyError が発生する。
|
|
151
|
+
``select_tier_detailed`` 経由では呼び出し側(main)が全 TIERS 分を
|
|
152
|
+
構築して保証する。
|
|
153
|
+
epsilon: 拮抗判定の閾値(デフォルト EPSILON=0.05)。
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
(chosen, did_tiebreak, contenders) のタプル。
|
|
157
|
+
- chosen: 選択された tier 名。
|
|
158
|
+
- did_tiebreak: cost tie-break が発動した場合 True。
|
|
159
|
+
- contenders: 拮抗判定に入った tier のタプル。
|
|
160
|
+
"""
|
|
161
|
+
max_sample = max(samples.values())
|
|
162
|
+
contenders = [t for t in samples if max_sample - samples[t] <= epsilon]
|
|
163
|
+
|
|
164
|
+
if len(contenders) <= 1 or cost_map is None:
|
|
165
|
+
# 従来挙動と完全一致: max(samples, key=lambda t: samples[t]) と同じ式
|
|
166
|
+
chosen = max(samples, key=lambda t: samples[t])
|
|
167
|
+
return chosen, False, tuple(contenders)
|
|
168
|
+
|
|
169
|
+
# 拮抗群内で min-max 正規化コストを計算し最安 tier を選ぶ
|
|
170
|
+
costs = {t: cost_map[t] for t in contenders}
|
|
171
|
+
lo, hi = min(costs.values()), max(costs.values())
|
|
172
|
+
norm = {t: ((costs[t] - lo) / (hi - lo) if hi > lo else 0.0) for t in contenders}
|
|
173
|
+
# 同値安定 tie-break: norm 同値時はサンプル大(=従来選好)を優先 → 決定論
|
|
174
|
+
chosen = min(contenders, key=lambda t: (norm[t], -samples[t]))
|
|
175
|
+
return chosen, True, tuple(contenders)
|
|
176
|
+
|
|
113
177
|
|
|
114
178
|
def _prompt_prefix_and_hash(prompt: str) -> tuple[str, str]:
|
|
115
179
|
"""prompt から (prefix, hash) を抽出する。
|
|
@@ -226,34 +290,67 @@ def estimate_complexity(prompt: str) -> str:
|
|
|
226
290
|
return "medium"
|
|
227
291
|
|
|
228
292
|
|
|
229
|
-
def
|
|
293
|
+
def select_tier_detailed(
|
|
230
294
|
params: dict[str, tuple[float, float, int]],
|
|
231
295
|
*,
|
|
232
296
|
rng: random.Random | None = None,
|
|
233
|
-
|
|
234
|
-
|
|
297
|
+
cost_map: dict[str, float] | None = None,
|
|
298
|
+
) -> SelectionResult:
|
|
299
|
+
"""Beta サンプリングまたは uniform 選択で推奨 Tier を SelectionResult で返す。
|
|
235
300
|
|
|
236
301
|
Args:
|
|
237
302
|
params: ``read_tier_params`` の戻り値。
|
|
238
303
|
``{"haiku": (alpha, beta, trials), ...}``
|
|
239
304
|
rng: テスト用に決定論的にしたい場合は ``random.Random(seed)`` を渡す。
|
|
305
|
+
cost_map: {tier: cost} の dict、または None。
|
|
306
|
+
None(cost を見ない=従来 Thompson)または「params の全 tier キーを
|
|
307
|
+
含む完全な dict」のいずれか。partial dict は渡されない前提
|
|
308
|
+
(呼び出し側が全 TIERS 分を構築して保証する)。
|
|
309
|
+
uniform 分岐では cost_map の有無に関わらず完全無視する(探索保護)。
|
|
240
310
|
|
|
241
311
|
Returns:
|
|
242
|
-
|
|
243
|
-
|
|
312
|
+
SelectionResult(tier, mode, cost_tiebreak, contenders)。
|
|
313
|
+
mode は ``"thompson"`` / ``"uniform"``。
|
|
244
314
|
"""
|
|
245
315
|
rng = rng or random
|
|
246
316
|
total_trials = sum(p[2] for p in params.values())
|
|
247
317
|
if total_trials < LEARNING_THRESHOLD:
|
|
248
|
-
|
|
318
|
+
# uniform: cost を完全無視・従来挙動完全維持
|
|
319
|
+
return SelectionResult(rng.choice(TIERS), "uniform", False, ())
|
|
249
320
|
|
|
250
|
-
#
|
|
321
|
+
# Thompson Sampling: rng の消費順序を従来 select_tier と完全一致させる
|
|
251
322
|
samples = {
|
|
252
323
|
tier: rng.betavariate(p[0], p[1])
|
|
253
324
|
for tier, p in params.items()
|
|
254
325
|
}
|
|
255
|
-
chosen =
|
|
256
|
-
return chosen, "thompson"
|
|
326
|
+
chosen, did_tiebreak, contenders = _cost_tiebreak(samples, cost_map)
|
|
327
|
+
return SelectionResult(chosen, "thompson", did_tiebreak, contenders)
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def select_tier(
|
|
331
|
+
params: dict[str, tuple[float, float, int]],
|
|
332
|
+
*,
|
|
333
|
+
rng: random.Random | None = None,
|
|
334
|
+
cost_map: dict[str, float] | None = None,
|
|
335
|
+
) -> tuple[str, str]:
|
|
336
|
+
"""Beta サンプリングまたは uniform 選択で推奨 Tier を返す。
|
|
337
|
+
|
|
338
|
+
Args:
|
|
339
|
+
params: ``read_tier_params`` の戻り値。
|
|
340
|
+
``{"haiku": (alpha, beta, trials), ...}``
|
|
341
|
+
rng: テスト用に決定論的にしたい場合は ``random.Random(seed)`` を渡す。
|
|
342
|
+
cost_map: {tier: cost} の dict、または None。
|
|
343
|
+
None なら cost を見ず従来の Thompson Sampling と完全一致。
|
|
344
|
+
uniform 分岐では cost_map の有無に関わらず完全無視する。
|
|
345
|
+
詳細は :func:`select_tier_detailed` を参照。
|
|
346
|
+
|
|
347
|
+
Returns:
|
|
348
|
+
``(tier, mode)`` のタプル。``mode`` は ``"thompson"`` / ``"uniform"`` で、
|
|
349
|
+
プロンプトに「学習データ収集中」と表示するかの分岐に使う。
|
|
350
|
+
戻り値型は v2.22.0 以前と完全に不変。
|
|
351
|
+
"""
|
|
352
|
+
result = select_tier_detailed(params, rng=rng, cost_map=cost_map)
|
|
353
|
+
return result.tier, result.mode
|
|
257
354
|
|
|
258
355
|
|
|
259
356
|
# Phase 2-B: 失敗率による昇格マッピング(haiku → sonnet, sonnet → opus)。
|
|
@@ -324,6 +421,7 @@ def write_tier_selection(
|
|
|
324
421
|
prompt_prefix: str | None = None,
|
|
325
422
|
prompt_hash: str | None = None,
|
|
326
423
|
session_id: str | None = None,
|
|
424
|
+
cost_tiebreak: bool = False,
|
|
327
425
|
) -> None:
|
|
328
426
|
"""直近の選択結果を ``tier_selection.json`` に書く。
|
|
329
427
|
|
|
@@ -339,6 +437,10 @@ def write_tier_selection(
|
|
|
339
437
|
|
|
340
438
|
``session_id`` を任意で含める。UserPromptSubmit payload の session UUID。
|
|
341
439
|
None のときは tier_selection.json のキー自体を省略する(後方互換)。
|
|
440
|
+
|
|
441
|
+
``cost_tiebreak`` を任意で含める(v2.23.0)。
|
|
442
|
+
Thompson Sampling の拮抗群内で cost tie-break が発動した場合のみ True。
|
|
443
|
+
False のときはキー自体を省略する(escalated/session_id と同パターン)。
|
|
342
444
|
"""
|
|
343
445
|
os.makedirs(os.path.dirname(TIER_SELECTION_PATH), exist_ok=True)
|
|
344
446
|
payload: dict[str, object] = {
|
|
@@ -360,6 +462,8 @@ def write_tier_selection(
|
|
|
360
462
|
payload["prompt_hash"] = prompt_hash
|
|
361
463
|
if session_id is not None:
|
|
362
464
|
payload["session_id"] = session_id
|
|
465
|
+
if cost_tiebreak:
|
|
466
|
+
payload["cost_tiebreak"] = True
|
|
363
467
|
try:
|
|
364
468
|
with open(TIER_SELECTION_PATH, "w", encoding="utf-8") as f:
|
|
365
469
|
json.dump(payload, f, ensure_ascii=False)
|
|
@@ -376,8 +480,13 @@ def build_additional_context(
|
|
|
376
480
|
*,
|
|
377
481
|
escalation_reason: str | None = None,
|
|
378
482
|
complexity_source: str | None = None,
|
|
483
|
+
cost_tiebreak: bool = False,
|
|
379
484
|
) -> str:
|
|
380
|
-
"""親 Claude に追加注入する文字列を組み立てる。
|
|
485
|
+
"""親 Claude に追加注入する文字列を組み立てる。
|
|
486
|
+
|
|
487
|
+
``cost_tiebreak`` が True のとき、suffix に cost-aware 発動を示す文言を追加する(v2.23.0)。
|
|
488
|
+
False のときは不変(既存文言と完全一致)。
|
|
489
|
+
"""
|
|
381
490
|
trials = sum(p[2] for p in params.values())
|
|
382
491
|
if mode == "uniform":
|
|
383
492
|
confidence = f"学習データ収集中(合計 {trials}/{LEARNING_THRESHOLD} 試行)"
|
|
@@ -390,6 +499,8 @@ def build_additional_context(
|
|
|
390
499
|
suffix += f" [Phase 2-B 昇格: {escalation_reason}]"
|
|
391
500
|
if complexity_source:
|
|
392
501
|
suffix += f" [複雑度判定: {complexity_source}]"
|
|
502
|
+
if cost_tiebreak:
|
|
503
|
+
suffix += " [cost-aware: 成功率拮抗のため低コスト Tier を選択]"
|
|
393
504
|
|
|
394
505
|
return (
|
|
395
506
|
f"[tier-routing 推奨] 複雑度: {complexity} / 推奨 Tier: {tier}({confidence})。"
|
|
@@ -445,7 +556,29 @@ def main() -> int:
|
|
|
445
556
|
else:
|
|
446
557
|
params = c3_db.read_tier_params(complexity)
|
|
447
558
|
|
|
448
|
-
|
|
559
|
+
# v2.24.0: cost_map をハイブリッド解決(実測 rate USD/MTok を主に、欠損 tier は静的単価で補完)。
|
|
560
|
+
# rate 化により measured(実測)と tier_reference_cost(静的)が同次元(USD/MTok)になり単位整合済み。
|
|
561
|
+
# c3_db が None または pricing import 失敗時は cost_map=None で従来 Thompson にデグレード。
|
|
562
|
+
# cost_map=None の場合、select_tier_detailed/_cost_tiebreak は従来 Thompson 挙動と完全一致(引数定義参照)。
|
|
563
|
+
cost_map = None
|
|
564
|
+
if c3_db is not None:
|
|
565
|
+
try:
|
|
566
|
+
from c3 import pricing # type: ignore[import-not-found]
|
|
567
|
+
measured = c3_db.read_tier_cost_rate_for_complexity(complexity) # {tier: rate USD/MTok} 実測>0 のみ
|
|
568
|
+
cost_map = {}
|
|
569
|
+
for tier_name in TIERS:
|
|
570
|
+
if tier_name in measured and measured[tier_name] > 0:
|
|
571
|
+
cost_map[tier_name] = measured[tier_name]
|
|
572
|
+
else:
|
|
573
|
+
# tier_reference_cost は未知 tier に 0.0 を返すが、TIERS と _TIER_REFERENCE_KEY は
|
|
574
|
+
# 同期前提のため現行 3 tier(haiku/sonnet/opus)では 0.0 混入は起きない。
|
|
575
|
+
cost_map[tier_name] = pricing.tier_reference_cost(tier_name) # 静的 fallback
|
|
576
|
+
except ImportError:
|
|
577
|
+
cost_map = None
|
|
578
|
+
|
|
579
|
+
result = select_tier_detailed(params, cost_map=cost_map)
|
|
580
|
+
tier, mode = result.tier, result.mode
|
|
581
|
+
cost_tiebreak = result.cost_tiebreak
|
|
449
582
|
|
|
450
583
|
# Phase 2-B: failure rate に基づく escalation
|
|
451
584
|
effective_tier, escalation_reason = maybe_escalate(complexity, tier)
|
|
@@ -457,12 +590,14 @@ def main() -> int:
|
|
|
457
590
|
prompt_prefix=prompt_prefix,
|
|
458
591
|
prompt_hash=prompt_hash,
|
|
459
592
|
session_id=session_id,
|
|
593
|
+
cost_tiebreak=cost_tiebreak,
|
|
460
594
|
)
|
|
461
595
|
|
|
462
596
|
context_text = build_additional_context(
|
|
463
597
|
complexity, effective_tier, mode, params,
|
|
464
598
|
escalation_reason=escalation_reason,
|
|
465
599
|
complexity_source=complexity_source,
|
|
600
|
+
cost_tiebreak=cost_tiebreak,
|
|
466
601
|
)
|
|
467
602
|
output = {
|
|
468
603
|
"hookSpecificOutput": {
|
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.24.0] - 2026-05-25
|
|
4
|
+
|
|
5
|
+
**tier-routing cost 精度向上**: tie-break が使う cost データを model 一致集計・USD/MTok レート化により信頼できるものにする。新関数 2 つを追加し、`select_tier` の cost_map 源を rate 関数へ切替。既存関数・tie-break ロジックは完全不変。
|
|
6
|
+
|
|
7
|
+
**スコープ注記**:
|
|
8
|
+
- `tier_bandit.total_cost_usd`/`cost_samples` への書き込み・cost-weighted Thompson 本格統合は **v2.25.0+**。
|
|
9
|
+
- migration なし。**破壊的変更なし**(新関数追加・cost_map 値の意味変更のみ・既存関数 docstring 含め完全不変)。
|
|
10
|
+
|
|
11
|
+
### 機能追加
|
|
12
|
+
|
|
13
|
+
- **`src/c3/db.py`: `read_tier_cost_rate_summary(*, db_path=None) -> list[dict]`(新規)**: model 一致集計・(session, tier) 重複排除・USD/MTok レート化を行う精度向上版の cost 集計関数。`agent_cost_runs` を `agent_type <> 'mainline'` で読み、Python 側で `pricing.resolve_tier(model)` により tier 振り分け。`(session_id, tier)` 粒度で集約後、`tier_recent_outcomes` と突合して `(complexity, tier)` 別に集計。`rate_usd_per_mtok = total_cost_usd / (billable_tokens / 1_000_000)`(`billable_tokens = input_tokens + output_tokens`)で `tier_reference_cost`(USD/MTok)と同次元にする。`billable_tokens == 0` の (complexity,tier) は除外。未知 model 行はスキップ。戻り値 dict キー: `complexity / tier / sessions / total_cost_usd / billable_tokens / rate_usd_per_mtok`。内部畳み込み部は DB 非依存の純関数 `_compute_tier_cost_rate_summary` に分離。
|
|
14
|
+
|
|
15
|
+
- **`src/c3/db.py`: `read_tier_cost_rate_for_complexity(complexity, *, db_path=None) -> dict[str, float]`(新規)**: `read_tier_cost_rate_summary` を complexity 一致 & `rate_usd_per_mtok > 0` でフィルタし `{tier: rate_usd_per_mtok}` を返す薄いラッパー(v2.23.0 の `read_tier_cost_for_complexity` と対称)。データ/DB 不在で `{}`。
|
|
16
|
+
|
|
17
|
+
### 変更
|
|
18
|
+
|
|
19
|
+
- **`.claude/hooks/select_tier.py`**: `main()` の cost_map 構築で `read_tier_cost_for_complexity` → `read_tier_cost_rate_for_complexity` に切替。tie-break ロジック不変・cost_map の値の意味が絶対 USD → USD/MTok レートに変化し、静的 `tier_reference_cost` と単位整合。コメント更新(「混在スケール・厳密化は v2.24.0」→「v2.24.0 で rate 化により整合済み」)。
|
|
20
|
+
|
|
21
|
+
- **`src/c3/cli_tier.py`**: `c3 tier stats` に「Tier 別 USD/MTok レート(model 一致・tie-break が使用)」セクションを追加(complexity/tier/sessions/rate_usd_per_mtok 表示・データなしで「(rate データ未収集)」)。既存 session 合計 USD セクションも維持。「精度向上は v2.24.0」注記を「(粗い概算・session 合計 USD)」に更新。`--json` 出力に `tier_cost_rate` キー自動反映。DB 由来テキストへ `sanitize_terminal_text` 適用。
|
|
22
|
+
|
|
23
|
+
- **`src/c3/__init__.py`**: `__version__` を `"2.23.0"` から `"2.24.0"` に更新。
|
|
24
|
+
|
|
25
|
+
### 後方互換
|
|
26
|
+
|
|
27
|
+
- 既存 `read_tier_cost_summary` / `read_tier_cost_for_complexity` は docstring 含め完全不変。
|
|
28
|
+
- migration なし(`agent_cost_runs` の token 4 列 + model 列は v2.21.0 (002 migration) で既存)。
|
|
29
|
+
|
|
30
|
+
## [2.23.0] - 2026-05-25
|
|
31
|
+
|
|
32
|
+
**tier-routing cost-aware tie-break**: `select_tier` の Thompson Sampling 分岐に「拮抗 tier 群内コスト tie-break」を追加する。サンプル最大から ε(=0.05) 以内の拮抗 tier が複数ある場合のみ、min-max 正規化コストが最安の tier を選ぶ。単独最大なら従来通り(挙動不変)。成功率を犠牲にしない最小スコープの cost 統合。
|
|
33
|
+
|
|
34
|
+
**スコープ注記**:
|
|
35
|
+
- **最小スコープ=tie-break のみ**。精度向上(model 一致集計・agent_id 単位紐づけ)と `tier_bandit.total_cost_usd`/`cost_samples` への書き込みは **v2.24.0**。
|
|
36
|
+
- cost は**ハイブリッド源**(実測 avg_cost を主・欠損 tier は静的参照単価で補完)。実測 USD と静的 per-MTok の混在スケールは min-max 正規化で**拮抗群内の概算順位**に畳む(厳密な単位整合は v2.24.0)。
|
|
37
|
+
- LEARNING_THRESHOLD(30) 未満は cost 完全無視(uniform のまま・探索保護)。escalation は不変。
|
|
38
|
+
- migration なし(読み出しのみ・書き込みなし)。**破壊的変更なし**(optional kw-only 引数追加・None/False 時従来動作・出力キー条件付き追加のみ)。
|
|
39
|
+
|
|
40
|
+
### 機能追加
|
|
41
|
+
|
|
42
|
+
- **`src/c3/pricing.py`: `tier_reference_cost(tier) -> float`(新規)**: tier 名から input+output 静的参照単価和を返す純関数。haiku < sonnet < opus の単調性を保証。未知 tier は 0.0 を返す。`_TIER_REFERENCE_KEY` 定数で TIERS との同期チェックを明示。
|
|
43
|
+
|
|
44
|
+
- **`src/c3/db.py`: `read_tier_cost_for_complexity(complexity, *, db_path=None) -> dict[str, float]`(新規)**: `read_tier_cost_summary` を complexity 一致・avg_cost_usd > 0 でフィルタし `{tier: avg_cost_usd}` を返す薄いラッパー。テーブル不在・データ不在・DB 不在で `{}`。
|
|
45
|
+
|
|
46
|
+
- **`.claude/hooks/select_tier.py`**: `EPSILON=0.05` 定数 / `SelectionResult`(NamedTuple: tier/mode/cost_tiebreak/contenders)/ `_cost_tiebreak`(拮抗群 min-max 最安・同値はサンプル大優先で決定論)/ `select_tier_detailed(params, *, rng, cost_map)`(2 層 API の詳細版)を追加。
|
|
47
|
+
|
|
48
|
+
### 変更
|
|
49
|
+
|
|
50
|
+
- **`.claude/hooks/select_tier.py`**: `select_tier` に kw-only `cost_map=None` を追加し `select_tier_detailed` への委譲に変更(**戻り値型 (tier, mode) 不変**)。`write_tier_selection`/`build_additional_context` に `cost_tiebreak: bool = False` を追加(True 時のみ json キー追加 / context suffix「[cost-aware: 成功率拮抗のため低コスト Tier を選択]」追記)。`main()` で cost_map をハイブリッド解決し `select_tier_detailed` を使用(c3_db/pricing import 失敗時は cost_map=None で従来 Thompson にデグレード)。
|
|
51
|
+
|
|
52
|
+
- **`src/c3/__init__.py`**: `__version__` を `"2.22.0"` から `"2.23.0"` に更新。
|
|
53
|
+
|
|
54
|
+
- **注記更新**: `c3 tier stats` の「精度向上は v2.23.0」を「精度向上は v2.24.0」へ、「cost-aware routing 本体は v2.23.0 予定」を「cost-aware routing 本体(tie-break)実装済み。精度向上は v2.24.0 予定」へ更新。
|
|
55
|
+
|
|
3
56
|
## [2.22.0] - 2026-05-25
|
|
4
57
|
|
|
5
58
|
**tier-routing cost 紐づけデータ蓄積**: tier_recent_outcomes に session_id 列を追加し、agent_cost_runs と JOIN できるデータ基盤を整備する。`c3 tier stats` に complexity×tier 別の平均コストセクションを追加する。cost-aware routing 本体は v2.23.0。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-code-conductor
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.24.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
|
|
@@ -22,6 +22,7 @@ import sys
|
|
|
22
22
|
from typing import Any
|
|
23
23
|
|
|
24
24
|
from c3 import db as c3_db
|
|
25
|
+
from c3._terminal import sanitize_terminal_text
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
logger = logging.getLogger(__name__)
|
|
@@ -118,6 +119,8 @@ def _collect_snapshot(db_path, recent_limit: int) -> dict[str, Any]:
|
|
|
118
119
|
|
|
119
120
|
tier_cost: list[dict[str, Any]] = c3_db.read_tier_cost_summary(db_path=db_path)
|
|
120
121
|
|
|
122
|
+
tier_cost_rate: list[dict[str, Any]] = c3_db.read_tier_cost_rate_summary(db_path=db_path)
|
|
123
|
+
|
|
121
124
|
if total_trials < _LEARNING_THRESHOLD:
|
|
122
125
|
mode = "uniform"
|
|
123
126
|
else:
|
|
@@ -133,6 +136,7 @@ def _collect_snapshot(db_path, recent_limit: int) -> dict[str, Any]:
|
|
|
133
136
|
"recent_outcomes": recent_outcomes,
|
|
134
137
|
"agent_cost": agent_cost,
|
|
135
138
|
"tier_cost": tier_cost,
|
|
139
|
+
"tier_cost_rate": tier_cost_rate,
|
|
136
140
|
}
|
|
137
141
|
|
|
138
142
|
|
|
@@ -184,9 +188,10 @@ def _render_human(snapshot: dict[str, Any]) -> None:
|
|
|
184
188
|
f"{'in_tok':>9} {'out_tok':>9} {'cache_r':>9} {'cache_w':>9}"
|
|
185
189
|
)
|
|
186
190
|
for row in agent_cost:
|
|
187
|
-
|
|
191
|
+
agent_type_safe = sanitize_terminal_text(str(row["agent_type"]))
|
|
192
|
+
note = " (マクロ集計・tier 学習対象外)" if agent_type_safe == "mainline" else ""
|
|
188
193
|
print(
|
|
189
|
-
f"{
|
|
194
|
+
f"{agent_type_safe:<16} {row['runs']:>5} "
|
|
190
195
|
f"${row['total_cost_usd']:>9.4f} "
|
|
191
196
|
f"{row['input_tokens']:>9} {row['output_tokens']:>9} "
|
|
192
197
|
f"{row['cache_read_tokens']:>9} {row['cache_create_tokens']:>9}"
|
|
@@ -194,18 +199,37 @@ def _render_human(snapshot: dict[str, Any]) -> None:
|
|
|
194
199
|
)
|
|
195
200
|
print()
|
|
196
201
|
|
|
197
|
-
print("== Tier
|
|
202
|
+
print("== Tier 別平均コスト(粗い概算・session 合計 USD) ==")
|
|
198
203
|
tier_cost = snapshot.get("tier_cost", [])
|
|
199
204
|
if not tier_cost:
|
|
200
205
|
print("(cost 紐づけデータ未収集)")
|
|
201
206
|
else:
|
|
202
207
|
print(f"{'complexity':<12} {'tier':<8} {'sessions':>8} {'avg_usd':>10} {'total_usd':>10}")
|
|
203
208
|
for row in tier_cost:
|
|
209
|
+
complexity_safe = sanitize_terminal_text(str(row["complexity"]))
|
|
210
|
+
tier_safe = sanitize_terminal_text(str(row["tier"]))
|
|
204
211
|
print(
|
|
205
|
-
f"{
|
|
212
|
+
f"{complexity_safe:<12} {tier_safe:<8} "
|
|
206
213
|
f"{row['sessions']:>8} "
|
|
207
214
|
f"${row['avg_cost_usd']:>9.4f} "
|
|
208
215
|
f"${row['total_cost_usd']:>9.4f}"
|
|
209
216
|
)
|
|
210
217
|
print()
|
|
211
|
-
print("(注:
|
|
218
|
+
print("(注: 粗い概算・session 合計 USD。v2.24.0 より rate セクション追加済み)")
|
|
219
|
+
print()
|
|
220
|
+
|
|
221
|
+
print("== Tier 別 USD/MTok レート(model 一致・tie-break が使用) ==")
|
|
222
|
+
tier_cost_rate = snapshot.get("tier_cost_rate", [])
|
|
223
|
+
if not tier_cost_rate:
|
|
224
|
+
print("(rate データ未収集)")
|
|
225
|
+
else:
|
|
226
|
+
print(f"{'complexity':<12} {'tier':<8} {'sessions':>8} {'rate_usd_per_mtok':>18}")
|
|
227
|
+
for row in tier_cost_rate:
|
|
228
|
+
complexity_safe = sanitize_terminal_text(str(row["complexity"]))
|
|
229
|
+
tier_safe = sanitize_terminal_text(str(row["tier"]))
|
|
230
|
+
print(
|
|
231
|
+
f"{complexity_safe:<12} {tier_safe:<8} "
|
|
232
|
+
f"{row['sessions']:>8} "
|
|
233
|
+
f"{row['rate_usd_per_mtok']:>18.4f}"
|
|
234
|
+
)
|
|
235
|
+
print()
|