claude-code-conductor 2.29.3__tar.gz → 2.30.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.29.3 → claude_code_conductor-2.30.0}/.claude/CLAUDE.md +6 -6
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/code-reviewer.md +1 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/developer.md +1 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/security-reviewer.md +1 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/wt_developer.md +1 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/docs/platform-adapters.md +28 -15
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/ARCHITECTURE.md +2 -1
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/CHANGELOG.md +36 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/PKG-INFO +7 -6
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/README.md +6 -5
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/__init__.py +1 -1
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/adapters.py +303 -1
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/cli_doctor.py +21 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/platforms.py +1 -1
- claude_code_conductor-2.30.0/tests/test_adapters.py +807 -0
- claude_code_conductor-2.30.0/tests/test_cli_doctor.py +183 -0
- claude_code_conductor-2.29.3/tests/test_adapters.py +0 -276
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/architect.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/doc-writer.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/interviewer.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/planner.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/project-setup.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/systematic-debugger.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/tester.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/wt_systematic-debugger.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/wt_tester.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/breaking-changes.txt +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/deletions.txt +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/docs/config-policy.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/docs/parallel-agents-setup.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/docs/settings.json.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/_hook_utils.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/check_agent_invocation.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/consolidate_memory.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/permission_handler.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/permission_handler_toast.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/planner_check.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/post_tool.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/pre_compact.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/pre_tool.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/recall_inject.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/restore_session.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/select_tier.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/session_start.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/session_stop.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/session_utils.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/statusline.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/stop.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/hooks/worktree_guard.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/memory/.gitkeep +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/permission_rules.json +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/rules/promoted/index.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/settings.json +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/brainstorm/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/codex-review/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/dev-workflow/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/dev-workflow/references/code-review-checklist.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/dev-workflow/references/plan-design-guidelines.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/dev-workflow/references/security-review-checklist.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/dev-workflow/scripts/record_review_decision.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/dev-workflow/scripts/record_tier_outcome.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/dev-workflow/scripts/review_hint_inject.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/develop/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/doc/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/extract-lib/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/init-session/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/mcp-config/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/parallel-agents/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/pattern-status/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/promote-pattern/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/recall/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/report-timestamp/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/report-timestamp/scripts/get_timestamp.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/review-phase/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/setup/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/setup/reference.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/setup/templates/coding-standards-template.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/setup/templates/project-conventions-template.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/skills/start/SKILL.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/state/.gitkeep +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.gitignore +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/LICENSE +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/LICENSES/chroma-hnswlib-LICENSE +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/LICENSES/chroma-hnswlib-NOTICE +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/LICENSES/fastembed-LICENSE +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/LICENSES/fastembed-NOTICE +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/LICENSES/onnxruntime-LICENSE +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/LICENSES/paraphrase-multilingual-MiniLM-L12-v2-LICENSE +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/hatch_build.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/pyproject.toml +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/__main__.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/_db_params.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/_excludes.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/_terminal.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/cli.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/cli_ask.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/cli_init.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/cli_list.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/cli_plan.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/cli_recall.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/cli_tier.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/cli_update.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/db.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/embedding.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/mcp_server.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/migrate.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/migrations/001_initial.sql +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/migrations/002_agent_cost_runs.sql +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/migrations/003_tier_cost.sql +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/migrations/README.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/migrations/__init__.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/paths.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/plan_validator.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/pricing.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/question.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/recall_chunker.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/recall_index.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/src/c3/usage_ingester.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/__init__.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/conftest.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/fixtures/usage/README.md +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/fixtures/usage/mainline.jsonl +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/fixtures/usage/subagents/agent-deadbeef.jsonl +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/fixtures/usage/subagents/agent-deadbeef.meta.json +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/__init__.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_check_agent_invocation.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_consolidate_memory.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_hook_utils.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_permission_handler.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_permission_handler_toast.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_pip_reinstall_reminder.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_planner_check.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_planner_check_dev.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_post_tool.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_pre_tool.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_recall_inject.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_record_review_decision.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_record_tier_outcome.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_restore_session.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_review_hint_inject.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_select_tier.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_select_tier_escalation.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_session_start.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_session_stop.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_session_utils.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_settings_local_absolute_paths.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_similarity_boost.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_statusline.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_statusline_template_sync.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_sync_check.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/hooks/test_template_guard.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/skills/__init__.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/skills/_skill_helpers.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/skills/test_dev_workflow_no_task_type.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/skills/test_init_session_no_task_type.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/skills/test_planner_lightweight.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/skills/test_recall_skill.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/skills/test_session_backlog_reconciliation.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/skills/test_setup_templates.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/skills/test_start_skill_bugfix_flow.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/skills/test_start_skill_new_flow.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/skills/test_start_skill_security_audit_phase.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_check_deletions.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_cli_ask.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_cli_entry.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_cli_init.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_cli_list.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_cli_plan.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_cli_recall.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_cli_tier.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_cli_update_breaking_changes.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_cli_update_deletions.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_db.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_docstring_consistency.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_embedding.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_excludes.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_extract_breaking_changes.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_mcp_server_elicit.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_migrate.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_paths.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_plan_validator.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_pre_compact.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_pre_tool_hook.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_precompact_additional.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_precompact_toctou_fixes.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_pricing.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_recall_chunker.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_recall_index.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_references_migration.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_session_utils_additional.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_skill_no_builtin_conflict.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_statusline.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_stop_additional.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_stop_hook.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_stop_precompact_fixes.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_sync_template_stop.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_template_pre_tool_hook.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_usage_ingester.py +0 -0
- {claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/tests/test_worktree_guard.py +0 -0
|
@@ -53,15 +53,15 @@
|
|
|
53
53
|
|
|
54
54
|
## Platform Compatibility
|
|
55
55
|
|
|
56
|
-
このファイルは Claude Code / Codex / Cursor から canonical source として読まれる。
|
|
56
|
+
このファイルは Claude Code / Codex / Cursor / OpenCode から canonical source として読まれる。
|
|
57
57
|
他プラットフォームでの動作差分は以下の通り:
|
|
58
58
|
|
|
59
|
-
- **`AskUserQuestion`** への参照は、Codex/Cursor では MCP tool `c3_ask_user_question` に読み替える(MCP elicitation 非対応時の fallback は `c3 ask --file <json
|
|
60
|
-
- **`Agent` ツール** の参照は、Codex では `.codex/agents/<name>.toml` 経由のサブエージェント、Cursor では現行 runtime のサブエージェント機構(無い場合は同一 agent
|
|
61
|
-
- **`Skill` ツール / `/<skill>`** の参照は、Codex では `.agents/skills/<name>/SKILL.md`、Cursor では `.claude/skills/<name>/SKILL.md`
|
|
62
|
-
- **`isolation: worktree`** / **`permissionMode`** / **`tools` 制限** など agent フロントマターの一部キーは Claude Code 仕様。adapter
|
|
59
|
+
- **`AskUserQuestion`** への参照は、Codex/Cursor では MCP tool `c3_ask_user_question` に読み替える(MCP elicitation 非対応時の fallback は `c3 ask --file <json>`)。OpenCode では MCP を生成しないため、`AGENTS.md` の指示に従ってユーザーへ直接確認する(`multiSelect: true` は複数選択の質問として維持)
|
|
60
|
+
- **`Agent` ツール** の参照は、Codex では `.codex/agents/<name>.toml` 経由のサブエージェント、Cursor では現行 runtime のサブエージェント機構(無い場合は同一 agent 内でフェーズ実行しレポート契約のみ維持)、OpenCode では `.opencode/agents/c3-<name>.md` を `@mention` で起動するサブエージェントに読み替える
|
|
61
|
+
- **`Skill` ツール / `/<skill>`** の参照は、Codex では `.agents/skills/<name>/SKILL.md`、Cursor では `.claude/skills/<name>/SKILL.md` を直接読み込む。OpenCode では `.opencode/agents/c3-skill-<name>.md`(`.claude/skills/<name>/SKILL.md` を本文に埋め込み済み)を `@mention` で起動する(スラッシュコマンド自動展開は Claude Code 専用機能)
|
|
62
|
+
- **`isolation: worktree`** / **`permissionMode`** / **`tools` 制限** など agent フロントマターの一部キーは Claude Code 仕様。adapter 側では読み替え不能なものは無視される(OpenCode adapter は全 agent に `bash/read/edit/write/websearch` を一律付与する)
|
|
63
63
|
|
|
64
|
-
レポート(`.claude/reports/`)・state(`.claude/state/`)・memory(`.claude/agent-memory/`)のファイル名と書き込み先は全プラットフォーム共通。adapter 生成物の詳細は `c3 init --platform codex|cursor` で出力される `AGENTS.md` / `.cursor/rules/c3-core.mdc` を参照。
|
|
64
|
+
レポート(`.claude/reports/`)・state(`.claude/state/`)・memory(`.claude/agent-memory/`)のファイル名と書き込み先は全プラットフォーム共通。adapter 生成物の詳細は `c3 init --platform codex|cursor|opencode` で出力される `AGENTS.md` / `.cursor/rules/c3-core.mdc` / `.opencode/agents/` を参照。
|
|
65
65
|
|
|
66
66
|
---
|
|
67
67
|
|
{claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/code-reviewer.md
RENAMED
|
@@ -48,6 +48,7 @@ tools:
|
|
|
48
48
|
|
|
49
49
|
**During:**
|
|
50
50
|
- 指摘は重大度(High / Medium / Low)で分類する
|
|
51
|
+
- この段階の役割は**網羅(coverage)であり取捨選択ではない**。確信度が低い指摘・Low 重大度の指摘も握り潰さず report する(MEMORY.md の許容例外として合意済みの観点は除く)。各指摘に確信度を併記し、重要度・確信度による最終的な絞り込みは下流(planner → ユーザー承認)に委ねる
|
|
51
52
|
- **指摘ごとに該当する checklist_id を `[CR-XX-NNN]` 形式で併記する**(`.claude/skills/dev-workflow/references/code-review-checklist.md` の各項目に付与済み)。review-hint(レビュー判断ヒント機能)の照合キーになるため、必須とする。複数該当する場合は最も近いものを 1 つ選ぶ
|
|
52
53
|
- **該当 ID がない場合は `[CR-NEW]` で出す**(チェックリスト追加候補として扱う)。無理やり近い既存 ID にマッピングしないこと。review-hint の照合精度が落ち、チェックリストの成長機会も失われるため
|
|
53
54
|
- 良い実装は明示的に記録する(削除しないよう伝える)
|
|
@@ -50,6 +50,7 @@ plan-report に基づき実装・デバッグ・リファクタリングを行
|
|
|
50
50
|
**During:**
|
|
51
51
|
- 1タスク = 1コミットの粒度を保つ
|
|
52
52
|
- Green フェーズでは test-report の不合格テストを通す最小限のコードのみ書く(テストが要求しない機能追加・将来の拡張・ついでの改善は禁止)
|
|
53
|
+
- 最小限であっても**汎用解**を書く。テスト入力に hard-code して通すこと・特定テストケースだけに効く workaround は禁止。テストは正しさの検証であって解の定義ではないため、全ての valid input に対し正しい一般ロジックを実装する(「最小限」と「汎用解」は両立する: スコープを足さず・しかし test 入力に過適合しない)
|
|
53
54
|
- 設計上の不明点は推測せず、合理的な判断をコードコメントに残して進む(例: `# 設計書に記載なし: ○○と判断して実装`)
|
|
54
55
|
- 実装完了後に判断した内容を報告してユーザーが確認できるようにする
|
|
55
56
|
- 根本的な設計の欠落(実装の方向性が定まらないレベル)の場合のみ作業を止めて報告する
|
{claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/security-reviewer.md
RENAMED
|
@@ -49,6 +49,7 @@ SQLインジェクション・XSS・認証認可・秘密情報漏洩などの
|
|
|
49
49
|
|
|
50
50
|
**During:**
|
|
51
51
|
- 指摘は深刻度(Critical / High / Medium / Low)で分類する
|
|
52
|
+
- この段階の役割は**網羅(coverage)であり取捨選択ではない**。確信度が低い指摘・Low 深刻度の指摘も握り潰さず report する(MEMORY.md の許容例外・脅威モデル外として合意済みの観点は除く)。各指摘に確信度を併記し、深刻度・確信度による最終的な絞り込みは下流(planner → ユーザー承認)に委ねる
|
|
52
53
|
- **指摘ごとに該当する checklist_id を `[SR-XX-NNN]` 形式で併記する**(`.claude/skills/dev-workflow/references/security-review-checklist.md` の各項目に付与済み)。review-hint(レビュー判断ヒント機能)の照合キーになるため、必須とする。複数該当する場合は最も近いものを 1 つ選ぶ
|
|
53
54
|
- **該当 ID がない場合は `[SR-NEW]` で出す**(チェックリスト追加候補として扱う)。無理やり近い既存 ID にマッピングしないこと。review-hint の照合精度が落ち、チェックリストの成長機会も失われるため
|
|
54
55
|
- 悪用シナリオを具体的に記述して再現可能な形で報告する
|
{claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/agents/wt_developer.md
RENAMED
|
@@ -55,6 +55,7 @@ plan-report に基づき実装・デバッグ・リファクタリングを行
|
|
|
55
55
|
**During:**
|
|
56
56
|
- 1タスク = 1コミットの粒度を保つ
|
|
57
57
|
- Green フェーズでは test-report の不合格テストを通す最小限のコードのみ書く(テストが要求しない機能追加・将来の拡張・ついでの改善は禁止)
|
|
58
|
+
- 最小限であっても**汎用解**を書く。テスト入力に hard-code して通すこと・特定テストケースだけに効く workaround は禁止。テストは正しさの検証であって解の定義ではないため、全ての valid input に対し正しい一般ロジックを実装する(「最小限」と「汎用解」は両立する: スコープを足さず・しかし test 入力に過適合しない)
|
|
58
59
|
- 設計上の不明点は推測せず、合理的な判断をコードコメントに残して進む(例: `# 設計書に記載なし: ○○と判断して実装`)
|
|
59
60
|
- 実装完了後に判断した内容を報告してユーザーが確認できるようにする
|
|
60
61
|
- 根本的な設計の欠落(実装の方向性が定まらないレベル)の場合のみ作業を止めて報告する
|
{claude_code_conductor-2.29.3 → claude_code_conductor-2.30.0}/.claude/docs/platform-adapters.md
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Platform Adapters
|
|
2
2
|
|
|
3
3
|
C3 は **Claude Code** を canonical platform として設計されているが、
|
|
4
|
-
`c3 init --platform` で Codex / Cursor 向けの adapter を生成し、同じ `.claude/`
|
|
4
|
+
`c3 init --platform` で Codex / Cursor / OpenCode 向けの adapter を生成し、同じ `.claude/`
|
|
5
5
|
ツリーを共通の source of truth として利用できる。
|
|
6
6
|
|
|
7
7
|
本ドキュメントは:
|
|
@@ -22,6 +22,7 @@ C3 は **Claude Code** を canonical platform として設計されているが
|
|
|
22
22
|
| `claude` (デフォルト) | `.claude/` のみ | Claude Code ネイティブ |
|
|
23
23
|
| `codex` | `.claude/` + `AGENTS.md` + `.codex/` + `.agents/` | Codex CLI / 職場 Codex |
|
|
24
24
|
| `cursor` | `.claude/` + `.cursor/` | Cursor IDE |
|
|
25
|
+
| `opencode` | `.claude/` + `AGENTS.md` + `.opencode/` | OpenCode |
|
|
25
26
|
| `all` | 上記すべて | マルチプラットフォーム共存 |
|
|
26
27
|
|
|
27
28
|
`c3 init --platform claude` 以外でも `.claude/` は canonical source として残り、
|
|
@@ -51,6 +52,16 @@ adapter は派生ファイルを生成するのみ(`.claude/` の中身を変
|
|
|
51
52
|
| `.cursor/rules/c3-core.mdc` | Cursor の rule。`alwaysApply: true` で C3 workflow を常時参照 | `_cursor_core_rule` の静的テキスト |
|
|
52
53
|
| `.cursor/mcp.json` | Cursor の MCP サーバー設定。`mcpServers.c3` のみ管理対象 | `_write_cursor_mcp` で既存 JSON にマージ |
|
|
53
54
|
|
|
55
|
+
### `opencode` 選択時
|
|
56
|
+
|
|
57
|
+
| パス | 内容 | 生成ロジック |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| `AGENTS.md` | プロジェクト直下。OpenCode に C3 workflow の存在と `@c3-*` agent の使い方を伝える | `_opencode_agents_section` を managed block で挿入(Codex とは別マーカー) |
|
|
60
|
+
| `.opencode/agents/c3-<name>.md` | `.claude/agents/<name>.md` から生成した OpenCode agent 定義 | `_opencode_agent_md`。`interviewer`/`architect`/`planner` は `mode: all-purpose`、他は `mode: subagent` |
|
|
61
|
+
| `.opencode/agents/c3-skill-<name>.md` | `.claude/skills/<name>/SKILL.md` を OpenCode agent として変換 | `_skill_to_opencode_agent_md`。`mode: all-purpose` 固定 |
|
|
62
|
+
|
|
63
|
+
> OpenCode adapter は MCP 設定ファイルを生成しない。`AskUserQuestion` は OpenCode 上でユーザーに直接確認する方式(`AGENTS.md` の adapter 指示で `multiSelect: true` を維持)。
|
|
64
|
+
|
|
54
65
|
---
|
|
55
66
|
|
|
56
67
|
## 3. MCP server (`c3.mcp_server`)
|
|
@@ -140,22 +151,22 @@ managed block は使わず、`mcpServers.c3` キーだけを上書き。他の
|
|
|
140
151
|
|
|
141
152
|
## 6. 動作差分まとめ
|
|
142
153
|
|
|
143
|
-
| 機能 | Claude Code | Codex | Cursor |
|
|
144
|
-
|
|
145
|
-
| `AskUserQuestion` | ネイティブツール | MCP `c3_ask_user_question` / fallback `c3 ask` | 同左 |
|
|
146
|
-
| `Agent` ツール | ネイティブ subagent | `.codex/agents/<name>.toml` 経由の subagent | runtime に subagent 機構があれば使用、無ければ同一 agent 内でフェーズ実行 |
|
|
147
|
-
| `Skill` ツール / `/<skill>` | ネイティブ | `.agents/skills/<name>/SKILL.md` を読む | `.claude/skills/<name>/SKILL.md` を rule から指示 |
|
|
148
|
-
| `isolation: worktree` | サポート | 一部 Codex runtime で対応、不可時は同一 worktree 実行 | 反映されない |
|
|
149
|
-
| `permissionMode` | サポート | 概念なし(無視) | 概念なし(無視) |
|
|
150
|
-
| `tools` 制限 | サポート | Codex subagent のツール制限に部分対応 | rule テキスト内で補完 |
|
|
151
|
-
| `hooks` (lifecycle) | サポート | 非対応(無視) | 非対応(無視) |
|
|
152
|
-
| `memory` (`MEMORY.md` 注入) | サポート | `.claude/agent-memory/` を共通参照 | 同左 |
|
|
153
|
-
| パターン昇格 (`/promote-pattern`) | ネイティブ | `c3 init --platform codex` 後は `.agents/skills/promote-pattern/SKILL.md` を読んで実行 | rule から `.claude/skills/promote-pattern/SKILL.md` を指示 |
|
|
154
|
-
| レポート (`.claude/reports/`) | 共通 | 共通 | 共通 |
|
|
155
|
-
| state (`.claude/state/`) | 共通 | 共通 | 共通 |
|
|
154
|
+
| 機能 | Claude Code | Codex | Cursor | OpenCode |
|
|
155
|
+
|---|---|---|---|---|
|
|
156
|
+
| `AskUserQuestion` | ネイティブツール | MCP `c3_ask_user_question` / fallback `c3 ask` | 同左 | `AGENTS.md` の指示でユーザーに直接確認(`multiSelect` 維持) |
|
|
157
|
+
| `Agent` ツール | ネイティブ subagent | `.codex/agents/<name>.toml` 経由の subagent | runtime に subagent 機構があれば使用、無ければ同一 agent 内でフェーズ実行 | `.opencode/agents/c3-<name>.md` を `@mention` で起動 |
|
|
158
|
+
| `Skill` ツール / `/<skill>` | ネイティブ | `.agents/skills/<name>/SKILL.md` を読む | `.claude/skills/<name>/SKILL.md` を rule から指示 | `.opencode/agents/c3-skill-<name>.md`(本文に `.claude/skills/<name>/SKILL.md` を埋め込み) |
|
|
159
|
+
| `isolation: worktree` | サポート | 一部 Codex runtime で対応、不可時は同一 worktree 実行 | 反映されない | 反映されない |
|
|
160
|
+
| `permissionMode` | サポート | 概念なし(無視) | 概念なし(無視) | 概念なし(無視) |
|
|
161
|
+
| `tools` 制限 | サポート | Codex subagent のツール制限に部分対応 | rule テキスト内で補完 | 全 agent に `bash/read/edit/write/websearch` を付与 |
|
|
162
|
+
| `hooks` (lifecycle) | サポート | 非対応(無視) | 非対応(無視) | 非対応(無視) |
|
|
163
|
+
| `memory` (`MEMORY.md` 注入) | サポート | `.claude/agent-memory/` を共通参照 | 同左 | 同左 |
|
|
164
|
+
| パターン昇格 (`/promote-pattern`) | ネイティブ | `c3 init --platform codex` 後は `.agents/skills/promote-pattern/SKILL.md` を読んで実行 | rule から `.claude/skills/promote-pattern/SKILL.md` を指示 | `.opencode/agents/c3-skill-promote-pattern.md` を `@mention` |
|
|
165
|
+
| レポート (`.claude/reports/`) | 共通 | 共通 | 共通 | 共通 |
|
|
166
|
+
| state (`.claude/state/`) | 共通 | 共通 | 共通 | 共通 |
|
|
156
167
|
|
|
157
168
|
レポート・state・memory のファイル名と書き込み先は全プラットフォーム共通。これにより
|
|
158
|
-
Claude Code / Codex / Cursor が同じプロジェクトを行き来しても workflow 状態が保たれる。
|
|
169
|
+
Claude Code / Codex / Cursor / OpenCode が同じプロジェクトを行き来しても workflow 状態が保たれる。
|
|
159
170
|
|
|
160
171
|
---
|
|
161
172
|
|
|
@@ -164,4 +175,6 @@ Claude Code / Codex / Cursor が同じプロジェクトを行き来しても wo
|
|
|
164
175
|
- **`AskUserQuestion` の `multiSelect: true`**: MCP elicitation の仕様上、ホストが multi-select UI に対応していない場合は単一選択に degrade される。`c3 ask --file` の fallback は multi-select に対応
|
|
165
176
|
- **Cursor の subagent**: 2026-05 時点で Cursor は dedicated subagent 機構が限定的。adapter は「同一 agent でフェーズ実行・レポート契約を維持」を方針とする
|
|
166
177
|
- **Codex の `isolation: worktree`**: Codex 側の subagent runtime に依存。worktree 非対応の場合は無視される
|
|
178
|
+
- **OpenCode の `AskUserQuestion`**: OpenCode adapter は MCP 設定を生成しないため、`c3_ask_user_question` ツールは使わず `AGENTS.md` の指示に従ってユーザーへ直接確認する。`multiSelect: true` は「複数選択の質問」として維持するよう指示済み
|
|
179
|
+
- **OpenCode の `tools` 制限**: 生成される agent には一律で `bash/read/edit/write/websearch` を付与する。Claude 側 frontmatter の細かな `tools` 制限は反映されない(C3 の `code-reviewer` / `security-reviewer` は Claude 側でもレポート出力のため `write` を持つ)
|
|
167
180
|
- **改行コード**: adapter 生成ファイルは LF 改行で書き出す(`newline="\n"`)。`.gitattributes` で `eol=lf` を固定済み
|
|
@@ -217,13 +217,14 @@ recall_chunker.py → embedding.py → recall_index.py
|
|
|
217
217
|
|
|
218
218
|
## 6. クロスプラットフォーム adapter
|
|
219
219
|
|
|
220
|
-
`.claude/` を canonical source としたまま、Codex / Cursor 向けの派生生成物を作る。
|
|
220
|
+
`.claude/` を canonical source としたまま、Codex / Cursor / OpenCode 向けの派生生成物を作る。
|
|
221
221
|
|
|
222
222
|
| プラットフォーム | 生成物 | 生成コマンド |
|
|
223
223
|
|---|---|---|
|
|
224
224
|
| Claude Code | `.claude/`(primary) | — |
|
|
225
225
|
| Codex | `/AGENTS.md` / `.codex/` / `.agents/skills/` | `c3 init --platform codex` |
|
|
226
226
|
| Cursor | `.cursor/rules/c3-core.mdc` / `.cursor/mcp.json` | `c3 init --platform cursor` |
|
|
227
|
+
| OpenCode | `/AGENTS.md` / `.opencode/agents/` | `c3 init --platform opencode` |
|
|
227
228
|
|
|
228
229
|
- 生成ロジック: `adapters.py` + `platforms.py`。adapter 生成物は **派生物**(直接編集すると再生成で上書き・配布元 `.gitignore` で除外)。
|
|
229
230
|
- `AskUserQuestion` 互換: MCP tool `c3_ask_user_question`(`mcp_server.py`)、非対応時の fallback は `c3 ask`(`cli_ask.py`)。
|
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.30.0] - 2026-06-02
|
|
4
|
+
|
|
5
|
+
**新プラットフォーム adapter(機能追加・破壊的変更なし)**: `c3 init --platform opencode` で [OpenCode](https://opencode.ai) 向けの adapter を生成できるようになった。`.claude/` を canonical source としたまま、`AGENTS.md`(C3 専用 managed block)と `.opencode/agents/c3-*.md` / `.opencode/agents/c3-skill-*.md` を派生生成する。外部コントリビューター(PR #3 / @ma2tak)の実装に、C3 側でテスト・ドキュメント整備を追加してリリースする。
|
|
6
|
+
|
|
7
|
+
### 追加
|
|
8
|
+
|
|
9
|
+
- **OpenCode adapter(`c3 init --platform opencode`)**: `SUPPORTED_PLATFORMS` に `opencode` を追加。生成物は (1) `AGENTS.md` に C3 workflow の存在と `@c3-*` agent の使い方を記す managed block(Codex とは別マーカー `<!-- BEGIN/END C3 OPENCODE ADAPTER -->`)、(2) `.claude/agents/<name>.md` から変換した `.opencode/agents/c3-<name>.md`(`interviewer`/`architect`/`planner` は `mode: all-purpose`、他は `mode: subagent`)、(3) `.claude/skills/<name>/SKILL.md` から変換した `.opencode/agents/c3-skill-<name>.md`(`mode: all-purpose`)。`c3 init --platform all` にも含まれる。
|
|
10
|
+
- **OpenCode adapter のテスト(`tests/test_adapters.py`)**: 外部 contract から書く既存方針に倣い、`_opencode_agent_md` の必須キーと mode マッピング(interactive 3 種 / その他)、`_skill_to_opencode_agent_md`、`_opencode_agents_section` の rules / CLAUDE.md 注入と空時の省略、`scaffold_adapters((opencode,))` の生成ファイル・managed block・冪等性・`.claude/` 不在時 `FileNotFoundError` を固定する回帰テストを追加。
|
|
11
|
+
|
|
12
|
+
### 動作仕様(既知の差分)
|
|
13
|
+
|
|
14
|
+
- **MCP を生成しない**: OpenCode adapter は `.codex/config.toml` / `.cursor/mcp.json` のような MCP 設定を作らない。`AskUserQuestion` は `AGENTS.md` の指示に従ってユーザーへ直接確認する方式(`multiSelect: true` は複数選択の質問として維持)。
|
|
15
|
+
- **`tools` 一律付与**: 生成される agent / skill には一律で `bash/read/edit/write/websearch` を付与する。Claude 側 frontmatter の細かな `tools` 制限は反映されない(C3 の `code-reviewer` / `security-reviewer` は Claude 側でもレポート出力のため `write` を持つ)。
|
|
16
|
+
|
|
17
|
+
### ドキュメント
|
|
18
|
+
|
|
19
|
+
- `.claude/docs/platform-adapters.md`(§1 選択肢・§2 生成物・§6 動作差分・§7 既知の制限)、`.claude/CLAUDE.md`(Platform Compatibility)、`README.md`、`docs/cli-reference.md`、`docs/getting-started.md`、`ARCHITECTURE.md` に `opencode` を追記。
|
|
20
|
+
|
|
21
|
+
### 後方互換
|
|
22
|
+
|
|
23
|
+
- 既存プラットフォーム(claude / codex / cursor)の生成物・挙動に変更なし。`opencode` は明示指定(または `all`)時のみ生成される追加機能。**破壊的変更なし**・migration 不要。
|
|
24
|
+
|
|
25
|
+
## [2.29.4] - 2026-05-31
|
|
26
|
+
|
|
27
|
+
**ドキュメント PATCH(コード変更・破壊的変更・migration なし)**: Anthropic 公式「Prompting best practices」(Claude Opus 4.8 / Sonnet 4.6 等の最新モデル向け)の推奨を C3 の agent 定義に反映。`code-reviewer` / `security-reviewer` / `developer` / `wt_developer` の 4 定義にプロンプト文言を 1 行ずつ追加した。コード・公開 API・DB スキーマに変更なし。
|
|
28
|
+
|
|
29
|
+
### ドキュメント
|
|
30
|
+
|
|
31
|
+
- **`code-reviewer` / `security-reviewer`: 発見段階の役割が「網羅(coverage)」であることを明記**: 公式 BP の「code review harness の recall 低下対策」を反映。最新モデルは "conservative" / "high-severity のみ" 等の抑制指示を忠実に守り、調査はしても指摘を report しない傾向がある。これを防ぐため「発見段階の役割は網羅であり取捨選択ではない。Low / 低確信度の指摘も握り潰さず report する(`MEMORY.md` の許容例外・脅威モデル外として合意済みの観点は除く)。重大度・確信度による最終的な絞り込みは下流(planner → ユーザー承認)に委ねる」を `During` セクションに追記。
|
|
32
|
+
- **`developer` / `wt_developer`: test-overfit / hard-coding 回避を明記**: 公式 BP の「テストを通すことへの過集中回避」を反映。Green フェーズの「最小限のコードのみ書く」の直後に「最小限であっても汎用解を書く。テスト入力に hard-code して通すこと・特定テストケースだけに効く workaround は禁止。全ての valid input に対し正しい一般ロジックを実装する(『最小限』と『汎用解』は両立する)」を追記。既存の「将来の拡張禁止」とは矛盾しない(スコープを足さず・しかし test 入力に過適合しない)。
|
|
33
|
+
|
|
34
|
+
### 後方互換
|
|
35
|
+
|
|
36
|
+
- agent 定義本文(散文・プロンプト文言)の追記のみ。frontmatter・公開 API・CLI・DB スキーマに変更なし。migration 不要。**破壊的変更なし**。
|
|
37
|
+
- agent 定義の内容を assert するテストは存在しない。`.claude/agents` に触れる構造系テスト(adapter 生成 / 削除検出 / invocation hook / `cli list`)は全て green を確認済み。
|
|
38
|
+
|
|
3
39
|
## [2.29.3] - 2026-05-28
|
|
4
40
|
|
|
5
41
|
**ドキュメント + 配布調整 PATCH(コード変更・破壊的変更・migration なし)**: sdist への `ARCHITECTURE.md` 同梱と、`deletions.txt` 機構導入(v2.18.0)以前の削除 23 件の遡及追記をまとめてリリース。利用先で次回 `c3 update` 時に古い `.claude/` 残骸が除去される範囲が広がる。コード・公開 API・DB スキーマに変更なし。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-code-conductor
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.30.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
|
|
@@ -192,7 +192,7 @@ C3 のスラッシュコマンドはすべてスキル(`skills/{name}/SKILL.md
|
|
|
192
192
|
| コマンド | 役割 |
|
|
193
193
|
|---|---|
|
|
194
194
|
| `c3 init` | 利用先プロジェクトに `.claude/` を展開する |
|
|
195
|
-
| `c3 init --platform codex|cursor|all` | `.claude/` を canonical source にしたまま Codex/Cursor adapter を追加 |
|
|
195
|
+
| `c3 init --platform codex|cursor|opencode|all` | `.claude/` を canonical source にしたまま Codex/Cursor/OpenCode adapter を追加 |
|
|
196
196
|
| `c3 update` | `.claude/` をパッケージ最新版へ更新する(個人ファイルはスキップ) |
|
|
197
197
|
| `c3 list-agents` / `list-skills` | 設置済みアセットを一覧表示 |
|
|
198
198
|
| `c3 doctor` | 環境診断(`.claude/`・settings.json・claude バイナリ・adapter 生成物) |
|
|
@@ -262,14 +262,15 @@ c3 init
|
|
|
262
262
|
|
|
263
263
|
`c3 init` がパッケージに同梱された `.claude/` テンプレートをカレントディレクトリへコピーします。後日テンプレート側を更新したい場合は `c3 update` で差分のみ反映できます(`reports/` や `memory/sessions/` 等の個人ファイルは保持されます)。
|
|
264
264
|
|
|
265
|
-
Codex/Cursor でも同じ C3 workflow を使う場合は、`.claude/` を動かさず adapter を追加します。
|
|
265
|
+
Codex/Cursor/OpenCode でも同じ C3 workflow を使う場合は、`.claude/` を動かさず adapter を追加します。
|
|
266
266
|
|
|
267
267
|
```bash
|
|
268
|
-
c3 init --platform codex
|
|
269
|
-
c3 init --platform cursor
|
|
268
|
+
c3 init --platform codex # AGENTS.md / .agents/skills / .codex を生成
|
|
269
|
+
c3 init --platform cursor # .cursor/rules / .cursor/mcp.json を生成
|
|
270
|
+
c3 init --platform opencode # AGENTS.md / .opencode/agents を生成
|
|
270
271
|
```
|
|
271
272
|
|
|
272
|
-
Codex/Cursor adapter は `.claude/skills` と `.claude/agents` を参照元にします。`AskUserQuestion` は MCP tool `c3_ask_user_question`、または fallback の `c3 ask`
|
|
273
|
+
Codex/Cursor/OpenCode adapter は `.claude/skills` と `.claude/agents` を参照元にします。`AskUserQuestion` は MCP tool `c3_ask_user_question`、または fallback の `c3 ask` で単一選択・複数選択を維持します(OpenCode は MCP を生成せず `AGENTS.md` の指示でユーザーに直接確認)。Claude Code の `Agent` / `Skill` tool 前提は、Codex では `.codex/agents/` と `.agents/skills/`、Cursor では `.cursor/rules/c3-core.mdc`、OpenCode では `.opencode/agents/` の `@c3-*` で読み替えます。
|
|
273
274
|
|
|
274
275
|
**3. プロジェクトを Claude Code で開き、初期設定を行う**
|
|
275
276
|
|
|
@@ -145,7 +145,7 @@ C3 のスラッシュコマンドはすべてスキル(`skills/{name}/SKILL.md
|
|
|
145
145
|
| コマンド | 役割 |
|
|
146
146
|
|---|---|
|
|
147
147
|
| `c3 init` | 利用先プロジェクトに `.claude/` を展開する |
|
|
148
|
-
| `c3 init --platform codex|cursor|all` | `.claude/` を canonical source にしたまま Codex/Cursor adapter を追加 |
|
|
148
|
+
| `c3 init --platform codex|cursor|opencode|all` | `.claude/` を canonical source にしたまま Codex/Cursor/OpenCode adapter を追加 |
|
|
149
149
|
| `c3 update` | `.claude/` をパッケージ最新版へ更新する(個人ファイルはスキップ) |
|
|
150
150
|
| `c3 list-agents` / `list-skills` | 設置済みアセットを一覧表示 |
|
|
151
151
|
| `c3 doctor` | 環境診断(`.claude/`・settings.json・claude バイナリ・adapter 生成物) |
|
|
@@ -215,14 +215,15 @@ c3 init
|
|
|
215
215
|
|
|
216
216
|
`c3 init` がパッケージに同梱された `.claude/` テンプレートをカレントディレクトリへコピーします。後日テンプレート側を更新したい場合は `c3 update` で差分のみ反映できます(`reports/` や `memory/sessions/` 等の個人ファイルは保持されます)。
|
|
217
217
|
|
|
218
|
-
Codex/Cursor でも同じ C3 workflow を使う場合は、`.claude/` を動かさず adapter を追加します。
|
|
218
|
+
Codex/Cursor/OpenCode でも同じ C3 workflow を使う場合は、`.claude/` を動かさず adapter を追加します。
|
|
219
219
|
|
|
220
220
|
```bash
|
|
221
|
-
c3 init --platform codex
|
|
222
|
-
c3 init --platform cursor
|
|
221
|
+
c3 init --platform codex # AGENTS.md / .agents/skills / .codex を生成
|
|
222
|
+
c3 init --platform cursor # .cursor/rules / .cursor/mcp.json を生成
|
|
223
|
+
c3 init --platform opencode # AGENTS.md / .opencode/agents を生成
|
|
223
224
|
```
|
|
224
225
|
|
|
225
|
-
Codex/Cursor adapter は `.claude/skills` と `.claude/agents` を参照元にします。`AskUserQuestion` は MCP tool `c3_ask_user_question`、または fallback の `c3 ask`
|
|
226
|
+
Codex/Cursor/OpenCode adapter は `.claude/skills` と `.claude/agents` を参照元にします。`AskUserQuestion` は MCP tool `c3_ask_user_question`、または fallback の `c3 ask` で単一選択・複数選択を維持します(OpenCode は MCP を生成せず `AGENTS.md` の指示でユーザーに直接確認)。Claude Code の `Agent` / `Skill` tool 前提は、Codex では `.codex/agents/` と `.agents/skills/`、Cursor では `.cursor/rules/c3-core.mdc`、OpenCode では `.opencode/agents/` の `@c3-*` で読み替えます。
|
|
226
227
|
|
|
227
228
|
**3. プロジェクトを Claude Code で開き、初期設定を行う**
|
|
228
229
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Generate Codex and
|
|
1
|
+
"""Generate Codex, Cursor, and OpenCode adapter files from the canonical ``.claude/`` tree."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -14,11 +14,73 @@ import yaml
|
|
|
14
14
|
|
|
15
15
|
from c3._excludes import should_skip
|
|
16
16
|
|
|
17
|
+
# ---------------------------------------------------------------------------
|
|
18
|
+
# Managed-block marker constants (CR L-04: defined before helpers that use them)
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
|
|
17
21
|
MANAGED_CODEX_BEGIN = "<!-- BEGIN C3 CODEX ADAPTER -->"
|
|
18
22
|
MANAGED_CODEX_END = "<!-- END C3 CODEX ADAPTER -->"
|
|
23
|
+
MANAGED_OPENCODE_BEGIN = "<!-- BEGIN C3 OPENCODE ADAPTER -->"
|
|
24
|
+
MANAGED_OPENCODE_END = "<!-- END C3 OPENCODE ADAPTER -->"
|
|
19
25
|
MANAGED_CODEX_TOML_BEGIN = "# BEGIN C3 CODEX ADAPTER"
|
|
20
26
|
MANAGED_CODEX_TOML_END = "# END C3 CODEX ADAPTER"
|
|
21
27
|
|
|
28
|
+
# All Markdown managed-block delimiter strings across every adapter platform
|
|
29
|
+
# (SR-AI-001). Used by _sanitize_for_managed_block to strip any marker regardless
|
|
30
|
+
# of platform. The TOML markers (MANAGED_CODEX_TOML_BEGIN/END) are intentionally
|
|
31
|
+
# excluded: they delimit blocks in .codex/config.toml, never in the Markdown
|
|
32
|
+
# content (CLAUDE.md / rules) that _sanitize_for_managed_block operates on.
|
|
33
|
+
_ALL_MANAGED_MARKERS = (
|
|
34
|
+
MANAGED_CODEX_BEGIN,
|
|
35
|
+
MANAGED_CODEX_END,
|
|
36
|
+
MANAGED_OPENCODE_BEGIN,
|
|
37
|
+
MANAGED_OPENCODE_END,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# ---------------------------------------------------------------------------
|
|
41
|
+
# YAML / sanitization helpers
|
|
42
|
+
# ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _yaml_inline_scalar(value: str) -> str:
|
|
46
|
+
"""Return *value* as a YAML-safe inline scalar (single-line, no trailing newline).
|
|
47
|
+
|
|
48
|
+
Uses ``yaml.safe_dump`` so that special characters (colons, double-quotes,
|
|
49
|
+
newlines) are automatically quoted in a way that round-trips cleanly.
|
|
50
|
+
The trailing newline and optional YAML document-end marker (``...``) that
|
|
51
|
+
``safe_dump`` appends are stripped so the result can be embedded directly
|
|
52
|
+
after ``key: `` in a YAML frontmatter line.
|
|
53
|
+
"""
|
|
54
|
+
dumped = yaml.safe_dump(value, default_flow_style=True, allow_unicode=True)
|
|
55
|
+
result = dumped.strip()
|
|
56
|
+
# safe_dump may append '\n...' as a document-end marker; remove it.
|
|
57
|
+
if result.endswith("\n..."):
|
|
58
|
+
result = result[:-4].rstrip()
|
|
59
|
+
return result
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _sanitize_for_managed_block(content: str) -> str:
|
|
63
|
+
"""Strip lines that could corrupt a managed block boundary.
|
|
64
|
+
|
|
65
|
+
Removes:
|
|
66
|
+
- Lines that are exactly any CODEX or OPENCODE managed-block marker string
|
|
67
|
+
(``MANAGED_CODEX_BEGIN``, ``MANAGED_CODEX_END``, ``MANAGED_OPENCODE_BEGIN``,
|
|
68
|
+
``MANAGED_OPENCODE_END``). Stripping all adapter markers prevents stray
|
|
69
|
+
delimiter lines from escaping a managed block when platform=all is used
|
|
70
|
+
(SR-AI-001 / CR M-03 / CR-NEW-01).
|
|
71
|
+
- Lines whose first character is ``@`` (Claude Code ``@``-include directives
|
|
72
|
+
such as ``@rules/promoted/index.md`` that are not meaningful to OpenCode
|
|
73
|
+
and could confuse parsers).
|
|
74
|
+
"""
|
|
75
|
+
clean_lines: list[str] = []
|
|
76
|
+
for line in content.splitlines():
|
|
77
|
+
if line in _ALL_MANAGED_MARKERS:
|
|
78
|
+
continue
|
|
79
|
+
if line.startswith("@"):
|
|
80
|
+
continue
|
|
81
|
+
clean_lines.append(line)
|
|
82
|
+
return "\n".join(clean_lines)
|
|
83
|
+
|
|
22
84
|
|
|
23
85
|
@dataclass(frozen=True)
|
|
24
86
|
class AdapterAction:
|
|
@@ -43,6 +105,8 @@ def scaffold_adapters(
|
|
|
43
105
|
actions.extend(_write_codex_adapter(target_root, dry_run=dry_run))
|
|
44
106
|
if "cursor" in platforms:
|
|
45
107
|
actions.extend(_write_cursor_adapter(target_root, dry_run=dry_run))
|
|
108
|
+
if "opencode" in platforms:
|
|
109
|
+
actions.extend(_write_opencode_adapter(target_root, dry_run=dry_run))
|
|
46
110
|
return actions
|
|
47
111
|
|
|
48
112
|
|
|
@@ -56,6 +120,23 @@ def print_adapter_actions(actions: list[AdapterAction], *, dry_run: bool = False
|
|
|
56
120
|
print(f" {action.action}: {action.path}")
|
|
57
121
|
|
|
58
122
|
|
|
123
|
+
def _write_opencode_adapter(target_root: Path, *, dry_run: bool) -> list[AdapterAction]:
|
|
124
|
+
"""Generate the three OpenCode adapter artefacts:
|
|
125
|
+
|
|
126
|
+
1. ``AGENTS.md`` managed block (``MANAGED_OPENCODE_BEGIN`` … ``MANAGED_OPENCODE_END``)
|
|
127
|
+
containing C3 usage instructions, CLAUDE.md content, and promoted rules.
|
|
128
|
+
2. ``.opencode/agents/c3-<name>.md`` — one file per agent defined in
|
|
129
|
+
``.claude/agents/*.md``.
|
|
130
|
+
3. ``.opencode/agents/c3-skill-<name>.md`` — one file per skill defined in
|
|
131
|
+
``.claude/skills/<name>/SKILL.md``.
|
|
132
|
+
"""
|
|
133
|
+
actions: list[AdapterAction] = []
|
|
134
|
+
actions.extend(_write_opencode_agents_md(target_root, dry_run=dry_run))
|
|
135
|
+
actions.extend(_write_opencode_agents(target_root, dry_run=dry_run))
|
|
136
|
+
actions.extend(_write_opencode_skills(target_root, dry_run=dry_run))
|
|
137
|
+
return actions
|
|
138
|
+
|
|
139
|
+
|
|
59
140
|
def _write_codex_adapter(target_root: Path, *, dry_run: bool) -> list[AdapterAction]:
|
|
60
141
|
actions: list[AdapterAction] = []
|
|
61
142
|
actions.extend(_write_managed_block(
|
|
@@ -299,6 +380,227 @@ mention the Claude Code `Skill` tool, read the matching file under
|
|
|
299
380
|
"""
|
|
300
381
|
|
|
301
382
|
|
|
383
|
+
def _write_opencode_agents_md(target_root: Path, *, dry_run: bool) -> list[AdapterAction]:
|
|
384
|
+
"""Write C3 adapter instructions into AGENTS.md for OpenCode."""
|
|
385
|
+
claude_root = target_root / ".claude"
|
|
386
|
+
rules_content = _collect_rules_for_opencode(claude_root)
|
|
387
|
+
claude_md = claude_root / "CLAUDE.md"
|
|
388
|
+
claude_md_content = claude_md.read_text(encoding="utf-8") if claude_md.exists() else ""
|
|
389
|
+
# CR L-03: sanitization is delegated entirely to _opencode_agents_section,
|
|
390
|
+
# which calls _sanitize_for_managed_block on both arguments. Calling it
|
|
391
|
+
# here a second time would be redundant (the function is idempotent), but
|
|
392
|
+
# centralising the responsibility in _opencode_agents_section is cleaner.
|
|
393
|
+
section = _opencode_agents_section(rules_content, claude_md_content)
|
|
394
|
+
return _write_managed_block(
|
|
395
|
+
target_root / "AGENTS.md",
|
|
396
|
+
section,
|
|
397
|
+
MANAGED_OPENCODE_BEGIN,
|
|
398
|
+
MANAGED_OPENCODE_END,
|
|
399
|
+
dry_run=dry_run,
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
def _collect_rules_for_opencode(claude_root: Path) -> str:
|
|
404
|
+
"""Read ``.claude/rules/*.md`` files (top-level only; subdirectories are not walked).
|
|
405
|
+
|
|
406
|
+
Intentionally non-recursive: ``rules/promoted/`` contains a managed index
|
|
407
|
+
frame (``index.md``) that is nearly empty, and rglob-ing it would inject
|
|
408
|
+
noise into the OpenCode managed block.
|
|
409
|
+
|
|
410
|
+
SR-V-002: applies the same symlink guard used by ``_write_opencode_agents``
|
|
411
|
+
and ``_write_opencode_skills``; files that resolve outside ``rules_dir`` are
|
|
412
|
+
skipped silently.
|
|
413
|
+
"""
|
|
414
|
+
rules_dir = claude_root / "rules"
|
|
415
|
+
if not rules_dir.is_dir():
|
|
416
|
+
return ""
|
|
417
|
+
rules_dir_resolved = rules_dir.resolve()
|
|
418
|
+
parts: list[str] = []
|
|
419
|
+
for f in sorted(rules_dir.glob("*.md")):
|
|
420
|
+
# SR-V-002: symlink guard — skip entries that resolve outside rules_dir.
|
|
421
|
+
try:
|
|
422
|
+
resolved = f.resolve(strict=True)
|
|
423
|
+
except OSError:
|
|
424
|
+
continue
|
|
425
|
+
if not resolved.is_relative_to(rules_dir_resolved):
|
|
426
|
+
continue
|
|
427
|
+
content = f.read_text(encoding="utf-8").strip()
|
|
428
|
+
if content:
|
|
429
|
+
parts.append(f"### {f.stem}\n\n{content}")
|
|
430
|
+
return "\n\n".join(parts)
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
def _opencode_agents_section(rules: str, claude_md: str) -> str:
|
|
434
|
+
# NOTE: The @mention list below is intentionally static and lists only the
|
|
435
|
+
# user-facing entry-point agents. Internal agents such as ``wt_*`` variants
|
|
436
|
+
# and ``project-setup`` are excluded because they are spawned programmatically
|
|
437
|
+
# by the parallel-agents skill and are not meant to be invoked directly by
|
|
438
|
+
# the user. (CR M-01 / L-03: design-intent comment; no dynamic generation.)
|
|
439
|
+
section = """# C3 Adapter for OpenCode
|
|
440
|
+
|
|
441
|
+
This repository uses Claude Code Conductor (C3). The canonical C3 workflow is
|
|
442
|
+
kept under `.claude/`; OpenCode adapter files are generated from that source.
|
|
443
|
+
|
|
444
|
+
## How to Use C3 with OpenCode
|
|
445
|
+
|
|
446
|
+
- `@c3-interviewer` - Start a requirements interview
|
|
447
|
+
- `@c3-architect` - Generate architecture design
|
|
448
|
+
- `@c3-planner` - Create a task plan
|
|
449
|
+
- `@c3-developer` - Implement code (TDD)
|
|
450
|
+
- `@c3-tester` - Write and run tests
|
|
451
|
+
- `@c3-code-reviewer` - Review code quality
|
|
452
|
+
- `@c3-security-reviewer` - Security review
|
|
453
|
+
- `@c3-doc-writer` - Generate documentation
|
|
454
|
+
- `@c3-systematic-debugger` - Debug complex issues
|
|
455
|
+
|
|
456
|
+
## Key Concepts
|
|
457
|
+
|
|
458
|
+
1. C3 state (reports, memory, sessions) lives in `.claude/`
|
|
459
|
+
2. Agents are invoked via `@mention` in OpenCode
|
|
460
|
+
3. C3 reports are the handoff mechanism between agents
|
|
461
|
+
4. User approval is required between phases
|
|
462
|
+
|
|
463
|
+
When C3 instructions contain an `AskUserQuestion` JSON block, ask the user
|
|
464
|
+
directly and preserve `multiSelect: true` as a multi-select question.
|
|
465
|
+
|
|
466
|
+
When C3 instructions mention the Claude Code `Agent` tool, use OpenCode
|
|
467
|
+
subagents via `@mention`. When they mention the `Skill` tool, read the
|
|
468
|
+
matching `.claude/skills/<name>/SKILL.md` file.
|
|
469
|
+
"""
|
|
470
|
+
# Sanitize embedded content to strip @-include directives and managed-block
|
|
471
|
+
# marker strings that could corrupt the OpenCode managed block boundary
|
|
472
|
+
# (SR-AI-001 / CR M-03 / CR-NEW-01).
|
|
473
|
+
safe_claude_md = _sanitize_for_managed_block(claude_md)
|
|
474
|
+
safe_rules = _sanitize_for_managed_block(rules)
|
|
475
|
+
if safe_claude_md.strip():
|
|
476
|
+
section += f"\n\n## C3 Behavior Rules\n\n{safe_claude_md.strip()}"
|
|
477
|
+
if safe_rules.strip():
|
|
478
|
+
section += f"\n\n## C3 Injected Rules\n\n{safe_rules}"
|
|
479
|
+
return section
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
def _write_opencode_agents(target_root: Path, *, dry_run: bool) -> list[AdapterAction]:
|
|
483
|
+
"""Convert .claude/agents/*.md to .opencode/agents/c3-*.md"""
|
|
484
|
+
source_root = target_root / ".claude" / "agents"
|
|
485
|
+
if not source_root.is_dir():
|
|
486
|
+
return []
|
|
487
|
+
actions: list[AdapterAction] = []
|
|
488
|
+
source_root_resolved = source_root.resolve()
|
|
489
|
+
for source in sorted(source_root.glob("*.md")):
|
|
490
|
+
# CR M-04 / SR-NEW: mirror the should_skip guard from _write_codex_agents.
|
|
491
|
+
# rel is relative to .claude/ (e.g. "agents/tdd-develop.md") to match
|
|
492
|
+
# the EXCLUDE_PATTERNS convention used by _write_codex_agents.
|
|
493
|
+
rel = source.relative_to(target_root / ".claude")
|
|
494
|
+
if should_skip(rel.as_posix()):
|
|
495
|
+
continue
|
|
496
|
+
# SR-V-002: symlink guard — skip sources that resolve outside source_root.
|
|
497
|
+
try:
|
|
498
|
+
resolved = source.resolve(strict=True)
|
|
499
|
+
except OSError:
|
|
500
|
+
continue
|
|
501
|
+
if not resolved.is_relative_to(source_root_resolved):
|
|
502
|
+
continue
|
|
503
|
+
name = source.stem
|
|
504
|
+
text = source.read_text(encoding="utf-8")
|
|
505
|
+
metadata, body = _split_frontmatter(text)
|
|
506
|
+
description = str(metadata.get("description") or _first_heading(body) or name)
|
|
507
|
+
agent_md = _opencode_agent_md(name, description, body)
|
|
508
|
+
dest = target_root / ".opencode" / "agents" / f"c3-{name}.md"
|
|
509
|
+
actions.extend(_write_file_if_changed(dest, agent_md, dry_run=dry_run))
|
|
510
|
+
return actions
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
def _opencode_agent_md(name: str, description: str, body: str) -> str:
|
|
514
|
+
"""Generate an OpenCode agent markdown file with YAML frontmatter."""
|
|
515
|
+
interactive = {"interviewer", "architect", "planner"}
|
|
516
|
+
mode = "all-purpose" if name in interactive else "subagent"
|
|
517
|
+
# Strip trailing whitespace from the combined description so that an empty
|
|
518
|
+
# ``description`` argument does not produce a trailing space on the line
|
|
519
|
+
# (CR L-01). Pass the stripped value through _yaml_inline_scalar so that
|
|
520
|
+
# colons, double-quotes, and newlines are safely quoted (CR H-01 / SR-V-001).
|
|
521
|
+
full_desc = _yaml_inline_scalar(f"C3 {name} agent. {description}".strip())
|
|
522
|
+
return (
|
|
523
|
+
f"---\n"
|
|
524
|
+
f"name: c3-{name}\n"
|
|
525
|
+
f"mode: {mode}\n"
|
|
526
|
+
f"description: {full_desc}\n"
|
|
527
|
+
f"tools:\n"
|
|
528
|
+
f" - bash\n - read\n - edit\n - write\n - websearch\n"
|
|
529
|
+
f"---\n\n"
|
|
530
|
+
f"# C3 Agent: {name}\n\n"
|
|
531
|
+
f"Generated from `.claude/agents/{name}.md`.\n\n"
|
|
532
|
+
f"## Adapter Notes\n\n"
|
|
533
|
+
f"- C3 state root: `.claude/`\n"
|
|
534
|
+
f"- Reports go to `.claude/reports/`\n"
|
|
535
|
+
f"- Session memory: `.claude/memory/`\n"
|
|
536
|
+
f"- When done, write your output report to the appropriate path\n\n"
|
|
537
|
+
f"## Original Agent Definition\n\n"
|
|
538
|
+
f"{body.strip()}\n"
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
def _write_opencode_skills(target_root: Path, *, dry_run: bool) -> list[AdapterAction]:
|
|
543
|
+
"""Convert .claude/skills/*/SKILL.md to .opencode/agents/c3-skill-*.md"""
|
|
544
|
+
source_root = target_root / ".claude" / "skills"
|
|
545
|
+
if not source_root.is_dir():
|
|
546
|
+
return []
|
|
547
|
+
actions: list[AdapterAction] = []
|
|
548
|
+
source_root_resolved = source_root.resolve()
|
|
549
|
+
for skill_dir in sorted(source_root.iterdir()):
|
|
550
|
+
if not skill_dir.is_dir():
|
|
551
|
+
continue
|
|
552
|
+
skill_file = skill_dir / "SKILL.md"
|
|
553
|
+
if not skill_file.exists():
|
|
554
|
+
continue
|
|
555
|
+
skill_name = skill_dir.name
|
|
556
|
+
# CR M-04 / SR-NEW: mirror should_skip guard from _write_codex_skills.
|
|
557
|
+
# rel is relative to .claude/ (e.g. "skills/worktree-tdd-workflow/SKILL.md").
|
|
558
|
+
rel = skill_file.relative_to(target_root / ".claude")
|
|
559
|
+
if should_skip(rel.as_posix()):
|
|
560
|
+
continue
|
|
561
|
+
# SR-V-002: symlink guard — skip files that resolve outside source_root.
|
|
562
|
+
try:
|
|
563
|
+
resolved = skill_file.resolve(strict=True)
|
|
564
|
+
except OSError:
|
|
565
|
+
continue
|
|
566
|
+
if not resolved.is_relative_to(source_root_resolved):
|
|
567
|
+
continue
|
|
568
|
+
text = skill_file.read_text(encoding="utf-8")
|
|
569
|
+
metadata, body = _split_frontmatter(text)
|
|
570
|
+
description = str(metadata.get("description") or _first_heading(body) or skill_name)
|
|
571
|
+
agent_md = _skill_to_opencode_agent_md(skill_name, description, body)
|
|
572
|
+
dest = target_root / ".opencode" / "agents" / f"c3-skill-{skill_name}.md"
|
|
573
|
+
actions.extend(_write_file_if_changed(dest, agent_md, dry_run=dry_run))
|
|
574
|
+
return actions
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
def _skill_to_opencode_agent_md(skill_name: str, description: str, body: str) -> str:
|
|
578
|
+
"""Convert a C3 SKILL.md to an OpenCode agent definition."""
|
|
579
|
+
# CR H-02 / L-06 / SR-V-001: use the shared YAML-safe scalar helper so that
|
|
580
|
+
# double-quotes or special characters in description do not break the
|
|
581
|
+
# frontmatter (previously used a raw double-quoted string literal).
|
|
582
|
+
full_desc = _yaml_inline_scalar(f"C3 skill: {description}")
|
|
583
|
+
return (
|
|
584
|
+
f"---\n"
|
|
585
|
+
f"name: c3-skill-{skill_name}\n"
|
|
586
|
+
f"mode: all-purpose\n"
|
|
587
|
+
f"description: {full_desc}\n"
|
|
588
|
+
f"tools:\n"
|
|
589
|
+
f" - bash\n - read\n - edit\n - write\n - websearch\n"
|
|
590
|
+
f"---\n\n"
|
|
591
|
+
f"# C3 Skill: {skill_name}\n\n"
|
|
592
|
+
f"Generated from `.claude/skills/{skill_name}/SKILL.md`.\n\n"
|
|
593
|
+
f"## Adapter Notes\n\n"
|
|
594
|
+
f"- This skill is the OpenCode equivalent of the C3 `/{skill_name}` command\n"
|
|
595
|
+
f"- C3 state root: `.claude/`\n"
|
|
596
|
+
f"- When the original references `AskUserQuestion`, ask the user directly\n"
|
|
597
|
+
f"- When the original references the `Agent` tool, use `@mention`\n"
|
|
598
|
+
f"- When the original references the `Skill` tool, read `.claude/skills/<name>/SKILL.md`\n\n"
|
|
599
|
+
f"## Original Skill Definition\n\n"
|
|
600
|
+
f"{body.strip()}\n"
|
|
601
|
+
)
|
|
602
|
+
|
|
603
|
+
|
|
302
604
|
def _convert_skill(text: str, skill_name: str) -> str:
|
|
303
605
|
metadata, body = _split_frontmatter(text)
|
|
304
606
|
metadata["name"] = metadata.get("name") or skill_name
|