claude-code-conductor 2.23.0__tar.gz → 2.25.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.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/select_tier.py +54 -10
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/session_stop.py +2 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/CHANGELOG.md +50 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/PKG-INFO +2 -1
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/README.md +1 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/__init__.py +1 -1
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/cli_tier.py +46 -8
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/db.py +362 -7
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_select_tier.py +310 -4
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_session_stop.py +55 -0
- claude_code_conductor-2.25.0/tests/test_cli_tier.py +1037 -0
- claude_code_conductor-2.25.0/tests/test_db.py +1723 -0
- claude_code_conductor-2.23.0/tests/test_cli_tier.py +0 -507
- claude_code_conductor-2.23.0/tests/test_db.py +0 -664
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/CLAUDE.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/agents/architect.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/agents/code-reviewer.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/agents/developer.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/agents/doc-writer.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/agents/interviewer.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/agents/planner.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/agents/project-setup.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/agents/security-reviewer.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/agents/systematic-debugger.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/agents/tester.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/agents/wt_developer.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/agents/wt_systematic-debugger.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/agents/wt_tester.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/breaking-changes.txt +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/deletions.txt +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/docs/config-policy.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/docs/parallel-agents-setup.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/docs/platform-adapters.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/docs/settings.json.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/_hook_utils.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/check_agent_invocation.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/consolidate_memory.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/permission_handler.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/permission_handler_toast.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/planner_check.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/post_tool.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/pre_compact.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/pre_tool.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/recall_inject.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/restore_session.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/session_start.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/session_utils.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/statusline.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/stop.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/hooks/worktree_guard.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/memory/.gitkeep +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/permission_rules.json +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/rules/promoted/index.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/settings.json +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/codex-review/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/dev-workflow/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/dev-workflow/references/code-review-checklist.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/dev-workflow/references/plan-design-guidelines.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/dev-workflow/references/security-review-checklist.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/dev-workflow/scripts/record_review_decision.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/dev-workflow/scripts/record_tier_outcome.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/dev-workflow/scripts/review_hint_inject.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/develop/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/doc/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/extract-lib/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/init-session/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/mcp-config/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/parallel-agents/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/pattern-status/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/promote-pattern/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/recall/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/report-timestamp/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/report-timestamp/scripts/get_timestamp.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/review-phase/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/setup/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/setup/reference.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/setup/templates/coding-standards-template.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/setup/templates/project-conventions-template.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/skills/start/SKILL.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.claude/state/.gitkeep +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/.gitignore +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/LICENSE +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/LICENSES/chroma-hnswlib-LICENSE +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/LICENSES/chroma-hnswlib-NOTICE +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/LICENSES/fastembed-LICENSE +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/LICENSES/fastembed-NOTICE +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/LICENSES/onnxruntime-LICENSE +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/LICENSES/paraphrase-multilingual-MiniLM-L12-v2-LICENSE +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/hatch_build.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/pyproject.toml +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/__main__.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/_excludes.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/_terminal.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/adapters.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/cli.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/cli_ask.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/cli_doctor.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/cli_init.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/cli_list.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/cli_plan.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/cli_recall.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/cli_update.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/embedding.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/mcp_server.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/migrate.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/migrations/001_initial.sql +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/migrations/002_agent_cost_runs.sql +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/migrations/003_tier_cost.sql +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/migrations/README.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/migrations/__init__.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/paths.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/plan_validator.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/platforms.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/pricing.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/question.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/recall_chunker.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/recall_index.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/src/c3/usage_ingester.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/__init__.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/conftest.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/fixtures/usage/README.md +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/fixtures/usage/mainline.jsonl +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/fixtures/usage/subagents/agent-deadbeef.jsonl +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/fixtures/usage/subagents/agent-deadbeef.meta.json +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/__init__.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_check_agent_invocation.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_consolidate_memory.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_hook_utils.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_permission_handler.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_permission_handler_toast.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_pip_reinstall_reminder.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_planner_check.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_planner_check_dev.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_post_tool.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_pre_tool.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_recall_inject.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_record_review_decision.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_record_tier_outcome.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_restore_session.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_review_hint_inject.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_select_tier_escalation.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_session_start.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_session_utils.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_settings_local_absolute_paths.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_similarity_boost.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_statusline.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_statusline_template_sync.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_sync_check.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/hooks/test_template_guard.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/skills/__init__.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/skills/_skill_helpers.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/skills/test_dev_workflow_no_task_type.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/skills/test_init_session_no_task_type.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/skills/test_planner_lightweight.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/skills/test_recall_skill.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/skills/test_session_backlog_reconciliation.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/skills/test_setup_templates.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/skills/test_start_skill_bugfix_flow.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/skills/test_start_skill_new_flow.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/skills/test_start_skill_security_audit_phase.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_adapters.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_cli_ask.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_cli_entry.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_cli_init.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_cli_list.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_cli_plan.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_cli_recall.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_cli_update_breaking_changes.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_cli_update_deletions.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_docstring_consistency.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_embedding.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_excludes.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_extract_breaking_changes.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_mcp_server_elicit.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_migrate.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_paths.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_plan_validator.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_pre_compact.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_pre_tool_hook.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_precompact_additional.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_precompact_toctou_fixes.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_pricing.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_recall_chunker.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_recall_index.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_references_migration.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_session_utils_additional.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_skill_no_builtin_conflict.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_statusline.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_stop_additional.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_stop_hook.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_stop_precompact_fixes.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_sync_template_stop.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_template_pre_tool_hook.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_usage_ingester.py +0 -0
- {claude_code_conductor-2.23.0 → claude_code_conductor-2.25.0}/tests/test_worktree_guard.py +0 -0
|
@@ -27,6 +27,7 @@ import collections
|
|
|
27
27
|
import difflib
|
|
28
28
|
import hashlib
|
|
29
29
|
import json
|
|
30
|
+
import math
|
|
30
31
|
import os
|
|
31
32
|
import random
|
|
32
33
|
import re
|
|
@@ -47,8 +48,10 @@ except AttributeError:
|
|
|
47
48
|
try:
|
|
48
49
|
from c3 import db as _c3_db_const # type: ignore[import-not-found]
|
|
49
50
|
LEARNING_THRESHOLD: int = _c3_db_const.LEARNING_THRESHOLD
|
|
51
|
+
EPSILON: float = _c3_db_const.EPSILON_TIEBREAK
|
|
50
52
|
except ImportError:
|
|
51
53
|
LEARNING_THRESHOLD = 30
|
|
54
|
+
EPSILON = 0.05
|
|
52
55
|
|
|
53
56
|
# 複雑度推定のキーワード
|
|
54
57
|
SIMPLE_KEYWORDS = frozenset({
|
|
@@ -111,10 +114,9 @@ _PROMPT_HISTORY_SCAN_LINES = 1000
|
|
|
111
114
|
|
|
112
115
|
TIERS: tuple[str, ...] = ("haiku", "sonnet", "opus")
|
|
113
116
|
|
|
114
|
-
# cost-aware tie-break の拮抗判定閾値(v2.23.0)。
|
|
117
|
+
# cost-aware tie-break の拮抗判定閾値(v2.23.0・SSOT は db.EPSILON_TIEBREAK)。
|
|
115
118
|
# Beta サンプルは 0〜1 スケール。成功率 5pt 以内=実質同等とみなす拮抗判定閾値。
|
|
116
|
-
#
|
|
117
|
-
EPSILON: float = 0.05
|
|
119
|
+
# 過大は成功率犠牲リスク、過小は無発動。C3_TIER_EPSILON env で上書き可(v2.25.0)。
|
|
118
120
|
|
|
119
121
|
|
|
120
122
|
class SelectionResult(NamedTuple):
|
|
@@ -144,8 +146,8 @@ def _cost_tiebreak(
|
|
|
144
146
|
Args:
|
|
145
147
|
samples: {tier: beta_sample} の dict(Thompson Sampling 結果)。
|
|
146
148
|
cost_map: {tier: cost} の dict。None なら cost を見ず従来挙動。
|
|
147
|
-
cost は実測
|
|
148
|
-
|
|
149
|
+
cost は実測 rate_usd_per_mtok または静的参照単価(ハイブリッド)。
|
|
150
|
+
v2.24.0 で rate 化(USD/MTok)により実測・静的とも同次元で整合済み。
|
|
149
151
|
``cost_map`` は None、または contenders 全件をキーとして含む dict を
|
|
150
152
|
渡すこと。partial dict を渡すと ``cost_map[t]`` で KeyError が発生する。
|
|
151
153
|
``select_tier_detailed`` 経由では呼び出し側(main)が全 TIERS 分を
|
|
@@ -295,6 +297,7 @@ def select_tier_detailed(
|
|
|
295
297
|
*,
|
|
296
298
|
rng: random.Random | None = None,
|
|
297
299
|
cost_map: dict[str, float] | None = None,
|
|
300
|
+
epsilon: float | None = None,
|
|
298
301
|
) -> SelectionResult:
|
|
299
302
|
"""Beta サンプリングまたは uniform 選択で推奨 Tier を SelectionResult で返す。
|
|
300
303
|
|
|
@@ -307,6 +310,7 @@ def select_tier_detailed(
|
|
|
307
310
|
含む完全な dict」のいずれか。partial dict は渡されない前提
|
|
308
311
|
(呼び出し側が全 TIERS 分を構築して保証する)。
|
|
309
312
|
uniform 分岐では cost_map の有無に関わらず完全無視する(探索保護)。
|
|
313
|
+
epsilon: 拮抗判定閾値。None なら module 定数 EPSILON を使う(C3_TIER_EPSILON で上書き可)。
|
|
310
314
|
|
|
311
315
|
Returns:
|
|
312
316
|
SelectionResult(tier, mode, cost_tiebreak, contenders)。
|
|
@@ -323,7 +327,8 @@ def select_tier_detailed(
|
|
|
323
327
|
tier: rng.betavariate(p[0], p[1])
|
|
324
328
|
for tier, p in params.items()
|
|
325
329
|
}
|
|
326
|
-
|
|
330
|
+
eff_epsilon = epsilon if epsilon is not None else EPSILON
|
|
331
|
+
chosen, did_tiebreak, contenders = _cost_tiebreak(samples, cost_map, epsilon=eff_epsilon)
|
|
327
332
|
return SelectionResult(chosen, "thompson", did_tiebreak, contenders)
|
|
328
333
|
|
|
329
334
|
|
|
@@ -332,6 +337,7 @@ def select_tier(
|
|
|
332
337
|
*,
|
|
333
338
|
rng: random.Random | None = None,
|
|
334
339
|
cost_map: dict[str, float] | None = None,
|
|
340
|
+
epsilon: float | None = None,
|
|
335
341
|
) -> tuple[str, str]:
|
|
336
342
|
"""Beta サンプリングまたは uniform 選択で推奨 Tier を返す。
|
|
337
343
|
|
|
@@ -343,13 +349,14 @@ def select_tier(
|
|
|
343
349
|
None なら cost を見ず従来の Thompson Sampling と完全一致。
|
|
344
350
|
uniform 分岐では cost_map の有無に関わらず完全無視する。
|
|
345
351
|
詳細は :func:`select_tier_detailed` を参照。
|
|
352
|
+
epsilon: 拮抗判定閾値。None なら module 定数 EPSILON を使う。
|
|
346
353
|
|
|
347
354
|
Returns:
|
|
348
355
|
``(tier, mode)`` のタプル。``mode`` は ``"thompson"`` / ``"uniform"`` で、
|
|
349
356
|
プロンプトに「学習データ収集中」と表示するかの分岐に使う。
|
|
350
357
|
戻り値型は v2.22.0 以前と完全に不変。
|
|
351
358
|
"""
|
|
352
|
-
result = select_tier_detailed(params, rng=rng, cost_map=cost_map)
|
|
359
|
+
result = select_tier_detailed(params, rng=rng, cost_map=cost_map, epsilon=epsilon)
|
|
353
360
|
return result.tier, result.mode
|
|
354
361
|
|
|
355
362
|
|
|
@@ -522,6 +529,41 @@ def _load_c3_db_module():
|
|
|
522
529
|
return None
|
|
523
530
|
|
|
524
531
|
|
|
532
|
+
def _resolve_epsilon() -> float:
|
|
533
|
+
"""``C3_TIER_EPSILON`` を安全に解決する。
|
|
534
|
+
|
|
535
|
+
不正値(非数値 / 0 以下 / 1 超 / NaN)は受け付けず、stderr 警告 + デフォルト(EPSILON)に戻す。
|
|
536
|
+
未設定 / 空文字は無警告でデフォルトを返す([SR-V-001])。
|
|
537
|
+
"""
|
|
538
|
+
raw = os.environ.get("C3_TIER_EPSILON")
|
|
539
|
+
if raw is None or raw == "":
|
|
540
|
+
return EPSILON
|
|
541
|
+
try:
|
|
542
|
+
x = float(raw)
|
|
543
|
+
except ValueError:
|
|
544
|
+
print(
|
|
545
|
+
f"[select_tier:epsilon] invalid C3_TIER_EPSILON={raw!r}, "
|
|
546
|
+
f"using default {EPSILON}",
|
|
547
|
+
file=sys.stderr,
|
|
548
|
+
)
|
|
549
|
+
return EPSILON
|
|
550
|
+
if math.isnan(x):
|
|
551
|
+
print(
|
|
552
|
+
f"[select_tier:epsilon] C3_TIER_EPSILON={raw!r} is NaN, "
|
|
553
|
+
f"using default {EPSILON}",
|
|
554
|
+
file=sys.stderr,
|
|
555
|
+
)
|
|
556
|
+
return EPSILON
|
|
557
|
+
if x <= 0 or x > 1:
|
|
558
|
+
print(
|
|
559
|
+
f"[select_tier:epsilon] C3_TIER_EPSILON={x} out of range (0, 1], "
|
|
560
|
+
f"using default {EPSILON}",
|
|
561
|
+
file=sys.stderr,
|
|
562
|
+
)
|
|
563
|
+
return EPSILON
|
|
564
|
+
return x
|
|
565
|
+
|
|
566
|
+
|
|
525
567
|
def main() -> int:
|
|
526
568
|
try:
|
|
527
569
|
payload = json.loads(sys.stdin.read())
|
|
@@ -556,14 +598,15 @@ def main() -> int:
|
|
|
556
598
|
else:
|
|
557
599
|
params = c3_db.read_tier_params(complexity)
|
|
558
600
|
|
|
559
|
-
# v2.
|
|
601
|
+
# v2.24.0: cost_map をハイブリッド解決(実測 rate USD/MTok を主に、欠損 tier は静的単価で補完)。
|
|
602
|
+
# rate 化により measured(実測)と tier_reference_cost(静的)が同次元(USD/MTok)になり単位整合済み。
|
|
560
603
|
# c3_db が None または pricing import 失敗時は cost_map=None で従来 Thompson にデグレード。
|
|
561
604
|
# cost_map=None の場合、select_tier_detailed/_cost_tiebreak は従来 Thompson 挙動と完全一致(引数定義参照)。
|
|
562
605
|
cost_map = None
|
|
563
606
|
if c3_db is not None:
|
|
564
607
|
try:
|
|
565
608
|
from c3 import pricing # type: ignore[import-not-found]
|
|
566
|
-
measured = c3_db.
|
|
609
|
+
measured = c3_db.read_tier_cost_rate_for_complexity(complexity) # {tier: rate USD/MTok} 実測>0 のみ
|
|
567
610
|
cost_map = {}
|
|
568
611
|
for tier_name in TIERS:
|
|
569
612
|
if tier_name in measured and measured[tier_name] > 0:
|
|
@@ -575,7 +618,8 @@ def main() -> int:
|
|
|
575
618
|
except ImportError:
|
|
576
619
|
cost_map = None
|
|
577
620
|
|
|
578
|
-
|
|
621
|
+
eps = _resolve_epsilon()
|
|
622
|
+
result = select_tier_detailed(params, cost_map=cost_map, epsilon=eps)
|
|
579
623
|
tier, mode = result.tier, result.mode
|
|
580
624
|
cost_tiebreak = result.cost_tiebreak
|
|
581
625
|
|
|
@@ -103,6 +103,8 @@ def main() -> int:
|
|
|
103
103
|
from c3.usage_ingester import ingest_session # noqa: PLC0415
|
|
104
104
|
project_dir = _Path(transcript_path).parent
|
|
105
105
|
ingest_session(session_id=session_id, project_dir=project_dir)
|
|
106
|
+
from c3.db import sync_tier_bandit_cost # noqa: PLC0415
|
|
107
|
+
sync_tier_bandit_cost()
|
|
106
108
|
except Exception as e:
|
|
107
109
|
print(f"[session_stop:usage_ingester] failed: {type(e).__name__}", file=sys.stderr)
|
|
108
110
|
|
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.25.0] - 2026-05-26
|
|
4
|
+
|
|
5
|
+
**tier_bandit cost 蓄積・EPSILON 調整可能化・例外ログ統一**: v2.22.0 で列確保済みの `tier_bandit.total_cost_usd`/`cost_samples` へ実測値を materialize する同期関数を追加。cost-aware tie-break の拮抗判定閾値を定数 SSOT 化し環境変数で上書き可能にする。db.py 既存 6 関数の例外ログを型名統一(SR-R-001)。routing 挙動は不変。cost-weighted Thompson 本格統合は v2.26.0。
|
|
6
|
+
|
|
7
|
+
### 機能追加
|
|
8
|
+
|
|
9
|
+
- **`src/c3/db.py`: `sync_tier_bandit_cost(*, db_path=None) -> None`(新規)**: `read_tier_cost_rate_summary` 由来の model 一致集計値を `tier_bandit` テーブルへ materialize する冪等な同期関数。「全クリア(total_cost_usd=0, cost_samples=0) → 集計 SET」の UPDATE-only 実装(INSERT なし)。session_stop の usage ingest 直後に実行。tier_bandit 行が存在しない複合キー (complexity, tier) は無視(INSERT は行わない)。
|
|
10
|
+
|
|
11
|
+
- **`.claude/hooks/select_tier.py`: `db.EPSILON_TIEBREAK`(0.05)定数 SSOT 化・環境変数 `C3_TIER_EPSILON` 対応**: 従来 `EPSILON=0.05` をモジュールローカルで持っていた値を `c3.db.EPSILON_TIEBREAK` に移し Single Source of Truth 化。`select_tier.py` は `db.EPSILON_TIEBREAK` を参照するよう変更。環境変数 `C3_TIER_EPSILON` に数値が設定されている場合は実行時にその値で上書き可能。NaN・範囲外(0 < x <= 1 の外)・非数値は default 値(0.05)に fallback。env 未設定時の routing 挙動は v2.24.0 と完全一致。
|
|
12
|
+
|
|
13
|
+
### 変更
|
|
14
|
+
|
|
15
|
+
- **`src/c3/cli_tier.py`**: `c3 tier stats` の tier_bandit セクションに `total_cost_usd`(合計コスト USD)および `cost_samples`(計上セッション数)列を追加。値は `sync_tier_bandit_cost` 蓄積値を表示。データ未蓄積(0/0)時はセルを「-」表示。
|
|
16
|
+
|
|
17
|
+
- **`src/c3/db.py`: 例外ログ型名統一(SR-R-001)**: 既存 6 関数 7 箇所の `except Exception as exc` ログを `logger.warning("...: %s", exc)` から `logger.warning("...: %s", type(exc).__name__)` に統一。生 exc message(外部 path・SQL 文・行データ等)の意図しない流出を防止。関数シグネチャ・戻り値・呼び出し元への影響なし。
|
|
18
|
+
|
|
19
|
+
### 後方互換
|
|
20
|
+
|
|
21
|
+
- 既存関数シグネチャ不変(`read_tier_params`・`read_tier_cost_rate_summary` 等)。
|
|
22
|
+
- `select_tier_detailed`/`select_tier` の `epsilon` は optional kwarg(省略時 `db.EPSILON_TIEBREAK` を参照)。
|
|
23
|
+
- migration 不要(`tier_bandit` の cost 列は v2.22.0 の 003 migration で確保済み)。
|
|
24
|
+
- **破壊的変更なし**。
|
|
25
|
+
|
|
26
|
+
## [2.24.0] - 2026-05-25
|
|
27
|
+
|
|
28
|
+
**tier-routing cost 精度向上**: tie-break が使う cost データを model 一致集計・USD/MTok レート化により信頼できるものにする。新関数 2 つを追加し、`select_tier` の cost_map 源を rate 関数へ切替。既存関数・tie-break ロジックは完全不変。
|
|
29
|
+
|
|
30
|
+
**スコープ注記**:
|
|
31
|
+
- `tier_bandit.total_cost_usd`/`cost_samples` への書き込み・cost-weighted Thompson 本格統合は **v2.25.0+**。
|
|
32
|
+
- migration なし。**破壊的変更なし**(新関数追加・cost_map 値の意味変更のみ・既存関数 docstring 含め完全不変)。
|
|
33
|
+
|
|
34
|
+
### 機能追加
|
|
35
|
+
|
|
36
|
+
- **`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` に分離。
|
|
37
|
+
|
|
38
|
+
- **`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 不在で `{}`。
|
|
39
|
+
|
|
40
|
+
### 変更
|
|
41
|
+
|
|
42
|
+
- **`.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 化により整合済み」)。
|
|
43
|
+
|
|
44
|
+
- **`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` 適用。
|
|
45
|
+
|
|
46
|
+
- **`src/c3/__init__.py`**: `__version__` を `"2.23.0"` から `"2.24.0"` に更新。
|
|
47
|
+
|
|
48
|
+
### 後方互換
|
|
49
|
+
|
|
50
|
+
- 既存 `read_tier_cost_summary` / `read_tier_cost_for_complexity` は docstring 含め完全不変。
|
|
51
|
+
- migration なし(`agent_cost_runs` の token 4 列 + model 列は v2.21.0 (002 migration) で既存)。
|
|
52
|
+
|
|
3
53
|
## [2.23.0] - 2026-05-25
|
|
4
54
|
|
|
5
55
|
**tier-routing cost-aware tie-break**: `select_tier` の Thompson Sampling 分岐に「拮抗 tier 群内コスト tie-break」を追加する。サンプル最大から ε(=0.05) 以内の拮抗 tier が複数ある場合のみ、min-max 正規化コストが最安の tier を選ぶ。単独最大なら従来通り(挙動不変)。成功率を犠牲にしない最小スコープの cost 統合。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-code-conductor
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.25.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
|
|
@@ -201,6 +201,7 @@ C3 のスラッシュコマンドはすべてスキル(`skills/{name}/SKILL.md
|
|
|
201
201
|
| `c3 recall search "<query>"` または `c3 recall "<query>"` | `.claude/memory/sessions/` 等から類似チャンクを意味検索 |
|
|
202
202
|
| `c3 recall rebuild [--force]` | HNSW インデックスを再構築(初回は fastembed が ~220MB のモデルを取得) |
|
|
203
203
|
| `c3 recall stats` | チャンク数・モデル名・最終 rebuild 日時を表示 |
|
|
204
|
+
| `c3 tier stats` | tier-routing(複雑度に応じた Tier 自動ルーティング)の学習データ・Tier 別コストを表形式で表示(`--json` で機械可読出力・`--recent N` で直近 outcome 件数指定) |
|
|
204
205
|
|
|
205
206
|
### 基本的な使い方
|
|
206
207
|
|
|
@@ -154,6 +154,7 @@ C3 のスラッシュコマンドはすべてスキル(`skills/{name}/SKILL.md
|
|
|
154
154
|
| `c3 recall search "<query>"` または `c3 recall "<query>"` | `.claude/memory/sessions/` 等から類似チャンクを意味検索 |
|
|
155
155
|
| `c3 recall rebuild [--force]` | HNSW インデックスを再構築(初回は fastembed が ~220MB のモデルを取得) |
|
|
156
156
|
| `c3 recall stats` | チャンク数・モデル名・最終 rebuild 日時を表示 |
|
|
157
|
+
| `c3 tier stats` | tier-routing(複雑度に応じた Tier 自動ルーティング)の学習データ・Tier 別コストを表形式で表示(`--json` で機械可読出力・`--recent N` で直近 outcome 件数指定) |
|
|
157
158
|
|
|
158
159
|
### 基本的な使い方
|
|
159
160
|
|
|
@@ -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__)
|
|
@@ -93,6 +94,11 @@ def _collect_snapshot(db_path, recent_limit: int) -> dict[str, Any]:
|
|
|
93
94
|
bandit_rows: list[dict[str, Any]] = []
|
|
94
95
|
total_trials = 0
|
|
95
96
|
|
|
97
|
+
# cost 列は別 SELECT(read_tier_params は alpha/beta/trials 専用を維持)
|
|
98
|
+
bandit_cost: dict[tuple[str, str], tuple[float, int]] = c3_db.read_tier_bandit_cost(
|
|
99
|
+
db_path=db_path,
|
|
100
|
+
)
|
|
101
|
+
|
|
96
102
|
for complexity in _COMPLEXITIES:
|
|
97
103
|
params = c3_db.read_tier_params(complexity, db_path=db_path)
|
|
98
104
|
for tier in _TIERS:
|
|
@@ -100,6 +106,7 @@ def _collect_snapshot(db_path, recent_limit: int) -> dict[str, Any]:
|
|
|
100
106
|
total_trials += trials
|
|
101
107
|
denom = alpha + beta
|
|
102
108
|
expected = alpha / denom if denom > 0 else 0.5
|
|
109
|
+
cost_usd, cost_samples = bandit_cost.get((complexity, tier), (0.0, 0))
|
|
103
110
|
bandit_rows.append({
|
|
104
111
|
"complexity": complexity,
|
|
105
112
|
"tier": tier,
|
|
@@ -107,6 +114,8 @@ def _collect_snapshot(db_path, recent_limit: int) -> dict[str, Any]:
|
|
|
107
114
|
"beta": beta,
|
|
108
115
|
"trials": trials,
|
|
109
116
|
"expected_success_rate": expected,
|
|
117
|
+
"total_cost_usd": cost_usd,
|
|
118
|
+
"cost_samples": cost_samples,
|
|
110
119
|
})
|
|
111
120
|
|
|
112
121
|
recent_outcomes: list[dict[str, Any]] = c3_db.read_recent_outcomes(
|
|
@@ -118,6 +127,8 @@ def _collect_snapshot(db_path, recent_limit: int) -> dict[str, Any]:
|
|
|
118
127
|
|
|
119
128
|
tier_cost: list[dict[str, Any]] = c3_db.read_tier_cost_summary(db_path=db_path)
|
|
120
129
|
|
|
130
|
+
tier_cost_rate: list[dict[str, Any]] = c3_db.read_tier_cost_rate_summary(db_path=db_path)
|
|
131
|
+
|
|
121
132
|
if total_trials < _LEARNING_THRESHOLD:
|
|
122
133
|
mode = "uniform"
|
|
123
134
|
else:
|
|
@@ -133,6 +144,7 @@ def _collect_snapshot(db_path, recent_limit: int) -> dict[str, Any]:
|
|
|
133
144
|
"recent_outcomes": recent_outcomes,
|
|
134
145
|
"agent_cost": agent_cost,
|
|
135
146
|
"tier_cost": tier_cost,
|
|
147
|
+
"tier_cost_rate": tier_cost_rate,
|
|
136
148
|
}
|
|
137
149
|
|
|
138
150
|
|
|
@@ -150,12 +162,18 @@ def _render_human(snapshot: dict[str, Any]) -> None:
|
|
|
150
162
|
print()
|
|
151
163
|
|
|
152
164
|
print("== Tier 別累積(tier_bandit) ==")
|
|
153
|
-
print(
|
|
165
|
+
print(
|
|
166
|
+
f"{'complexity':<12} {'tier':<8} {'trials':>6} {'alpha':>5} {'beta':>5} "
|
|
167
|
+
f"{'期待成功率':>10} {'cost_usd':>10} {'cost_samples':>12}"
|
|
168
|
+
)
|
|
154
169
|
for row in snapshot["tier_bandit"]:
|
|
170
|
+
complexity_safe = sanitize_terminal_text(str(row["complexity"]))
|
|
171
|
+
tier_safe = sanitize_terminal_text(str(row["tier"]))
|
|
155
172
|
print(
|
|
156
|
-
f"{
|
|
173
|
+
f"{complexity_safe:<12} {tier_safe:<8} "
|
|
157
174
|
f"{row['trials']:>6} {row['alpha']:>5.2f} {row['beta']:>5.2f} "
|
|
158
|
-
f"{row['expected_success_rate'] * 100:>9.2f}%"
|
|
175
|
+
f"{row['expected_success_rate'] * 100:>9.2f}% "
|
|
176
|
+
f"${row['total_cost_usd']:>9.4f} {row['cost_samples']:>12}"
|
|
159
177
|
)
|
|
160
178
|
print()
|
|
161
179
|
|
|
@@ -184,9 +202,10 @@ def _render_human(snapshot: dict[str, Any]) -> None:
|
|
|
184
202
|
f"{'in_tok':>9} {'out_tok':>9} {'cache_r':>9} {'cache_w':>9}"
|
|
185
203
|
)
|
|
186
204
|
for row in agent_cost:
|
|
187
|
-
|
|
205
|
+
agent_type_safe = sanitize_terminal_text(str(row["agent_type"]))
|
|
206
|
+
note = " (マクロ集計・tier 学習対象外)" if agent_type_safe == "mainline" else ""
|
|
188
207
|
print(
|
|
189
|
-
f"{
|
|
208
|
+
f"{agent_type_safe:<16} {row['runs']:>5} "
|
|
190
209
|
f"${row['total_cost_usd']:>9.4f} "
|
|
191
210
|
f"{row['input_tokens']:>9} {row['output_tokens']:>9} "
|
|
192
211
|
f"{row['cache_read_tokens']:>9} {row['cache_create_tokens']:>9}"
|
|
@@ -194,18 +213,37 @@ def _render_human(snapshot: dict[str, Any]) -> None:
|
|
|
194
213
|
)
|
|
195
214
|
print()
|
|
196
215
|
|
|
197
|
-
print("== Tier
|
|
216
|
+
print("== Tier 別平均コスト(粗い概算・session 合計 USD) ==")
|
|
198
217
|
tier_cost = snapshot.get("tier_cost", [])
|
|
199
218
|
if not tier_cost:
|
|
200
219
|
print("(cost 紐づけデータ未収集)")
|
|
201
220
|
else:
|
|
202
221
|
print(f"{'complexity':<12} {'tier':<8} {'sessions':>8} {'avg_usd':>10} {'total_usd':>10}")
|
|
203
222
|
for row in tier_cost:
|
|
223
|
+
complexity_safe = sanitize_terminal_text(str(row["complexity"]))
|
|
224
|
+
tier_safe = sanitize_terminal_text(str(row["tier"]))
|
|
204
225
|
print(
|
|
205
|
-
f"{
|
|
226
|
+
f"{complexity_safe:<12} {tier_safe:<8} "
|
|
206
227
|
f"{row['sessions']:>8} "
|
|
207
228
|
f"${row['avg_cost_usd']:>9.4f} "
|
|
208
229
|
f"${row['total_cost_usd']:>9.4f}"
|
|
209
230
|
)
|
|
210
231
|
print()
|
|
211
|
-
print("(注:
|
|
232
|
+
print("(注: 粗い概算・session 合計 USD。v2.24.0 より rate セクション追加済み)")
|
|
233
|
+
print()
|
|
234
|
+
|
|
235
|
+
print("== Tier 別 USD/MTok レート(model 一致・tie-break が使用) ==")
|
|
236
|
+
tier_cost_rate = snapshot.get("tier_cost_rate", [])
|
|
237
|
+
if not tier_cost_rate:
|
|
238
|
+
print("(rate データ未収集)")
|
|
239
|
+
else:
|
|
240
|
+
print(f"{'complexity':<12} {'tier':<8} {'sessions':>8} {'rate_usd_per_mtok':>18}")
|
|
241
|
+
for row in tier_cost_rate:
|
|
242
|
+
complexity_safe = sanitize_terminal_text(str(row["complexity"]))
|
|
243
|
+
tier_safe = sanitize_terminal_text(str(row["tier"]))
|
|
244
|
+
print(
|
|
245
|
+
f"{complexity_safe:<12} {tier_safe:<8} "
|
|
246
|
+
f"{row['sessions']:>8} "
|
|
247
|
+
f"{row['rate_usd_per_mtok']:>18.4f}"
|
|
248
|
+
)
|
|
249
|
+
print()
|