claude-code-conductor 2.29.4__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.
Files changed (199) hide show
  1. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/CLAUDE.md +6 -6
  2. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/docs/platform-adapters.md +28 -15
  3. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/ARCHITECTURE.md +2 -1
  4. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/CHANGELOG.md +22 -0
  5. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/PKG-INFO +7 -6
  6. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/README.md +6 -5
  7. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/__init__.py +1 -1
  8. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/adapters.py +303 -1
  9. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/cli_doctor.py +21 -0
  10. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/platforms.py +1 -1
  11. claude_code_conductor-2.30.0/tests/test_adapters.py +807 -0
  12. claude_code_conductor-2.30.0/tests/test_cli_doctor.py +183 -0
  13. claude_code_conductor-2.29.4/tests/test_adapters.py +0 -276
  14. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/agents/architect.md +0 -0
  15. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/agents/code-reviewer.md +0 -0
  16. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/agents/developer.md +0 -0
  17. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/agents/doc-writer.md +0 -0
  18. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/agents/interviewer.md +0 -0
  19. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/agents/planner.md +0 -0
  20. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/agents/project-setup.md +0 -0
  21. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/agents/security-reviewer.md +0 -0
  22. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/agents/systematic-debugger.md +0 -0
  23. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/agents/tester.md +0 -0
  24. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/agents/wt_developer.md +0 -0
  25. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/agents/wt_systematic-debugger.md +0 -0
  26. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/agents/wt_tester.md +0 -0
  27. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/breaking-changes.txt +0 -0
  28. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/deletions.txt +0 -0
  29. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/docs/config-policy.md +0 -0
  30. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/docs/parallel-agents-setup.md +0 -0
  31. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/docs/settings.json.md +0 -0
  32. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/_hook_utils.py +0 -0
  33. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/check_agent_invocation.py +0 -0
  34. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/consolidate_memory.py +0 -0
  35. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/permission_handler.py +0 -0
  36. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/permission_handler_toast.py +0 -0
  37. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/planner_check.py +0 -0
  38. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/post_tool.py +0 -0
  39. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/pre_compact.py +0 -0
  40. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/pre_tool.py +0 -0
  41. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/recall_inject.py +0 -0
  42. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/restore_session.py +0 -0
  43. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/select_tier.py +0 -0
  44. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/session_start.py +0 -0
  45. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/session_stop.py +0 -0
  46. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/session_utils.py +0 -0
  47. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/statusline.py +0 -0
  48. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/stop.py +0 -0
  49. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/hooks/worktree_guard.py +0 -0
  50. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/memory/.gitkeep +0 -0
  51. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/permission_rules.json +0 -0
  52. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/rules/promoted/index.md +0 -0
  53. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/settings.json +0 -0
  54. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/brainstorm/SKILL.md +0 -0
  55. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/codex-review/SKILL.md +0 -0
  56. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/dev-workflow/SKILL.md +0 -0
  57. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/dev-workflow/references/code-review-checklist.md +0 -0
  58. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/dev-workflow/references/plan-design-guidelines.md +0 -0
  59. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/dev-workflow/references/security-review-checklist.md +0 -0
  60. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/dev-workflow/scripts/record_review_decision.py +0 -0
  61. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/dev-workflow/scripts/record_tier_outcome.py +0 -0
  62. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/dev-workflow/scripts/review_hint_inject.py +0 -0
  63. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/develop/SKILL.md +0 -0
  64. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/doc/SKILL.md +0 -0
  65. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/extract-lib/SKILL.md +0 -0
  66. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/init-session/SKILL.md +0 -0
  67. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/mcp-config/SKILL.md +0 -0
  68. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/parallel-agents/SKILL.md +0 -0
  69. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/pattern-status/SKILL.md +0 -0
  70. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/promote-pattern/SKILL.md +0 -0
  71. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/recall/SKILL.md +0 -0
  72. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/report-timestamp/SKILL.md +0 -0
  73. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/report-timestamp/scripts/get_timestamp.py +0 -0
  74. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/review-phase/SKILL.md +0 -0
  75. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/setup/SKILL.md +0 -0
  76. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/setup/reference.md +0 -0
  77. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/setup/templates/coding-standards-template.md +0 -0
  78. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/setup/templates/project-conventions-template.md +0 -0
  79. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/skills/start/SKILL.md +0 -0
  80. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.claude/state/.gitkeep +0 -0
  81. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/.gitignore +0 -0
  82. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/LICENSE +0 -0
  83. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/LICENSES/chroma-hnswlib-LICENSE +0 -0
  84. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/LICENSES/chroma-hnswlib-NOTICE +0 -0
  85. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/LICENSES/fastembed-LICENSE +0 -0
  86. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/LICENSES/fastembed-NOTICE +0 -0
  87. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/LICENSES/onnxruntime-LICENSE +0 -0
  88. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/LICENSES/paraphrase-multilingual-MiniLM-L12-v2-LICENSE +0 -0
  89. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/hatch_build.py +0 -0
  90. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/pyproject.toml +0 -0
  91. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/__main__.py +0 -0
  92. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/_db_params.py +0 -0
  93. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/_excludes.py +0 -0
  94. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/_terminal.py +0 -0
  95. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/cli.py +0 -0
  96. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/cli_ask.py +0 -0
  97. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/cli_init.py +0 -0
  98. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/cli_list.py +0 -0
  99. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/cli_plan.py +0 -0
  100. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/cli_recall.py +0 -0
  101. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/cli_tier.py +0 -0
  102. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/cli_update.py +0 -0
  103. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/db.py +0 -0
  104. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/embedding.py +0 -0
  105. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/mcp_server.py +0 -0
  106. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/migrate.py +0 -0
  107. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/migrations/001_initial.sql +0 -0
  108. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/migrations/002_agent_cost_runs.sql +0 -0
  109. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/migrations/003_tier_cost.sql +0 -0
  110. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/migrations/README.md +0 -0
  111. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/migrations/__init__.py +0 -0
  112. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/paths.py +0 -0
  113. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/plan_validator.py +0 -0
  114. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/pricing.py +0 -0
  115. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/question.py +0 -0
  116. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/recall_chunker.py +0 -0
  117. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/recall_index.py +0 -0
  118. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/src/c3/usage_ingester.py +0 -0
  119. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/__init__.py +0 -0
  120. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/conftest.py +0 -0
  121. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/fixtures/usage/README.md +0 -0
  122. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/fixtures/usage/mainline.jsonl +0 -0
  123. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/fixtures/usage/subagents/agent-deadbeef.jsonl +0 -0
  124. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/fixtures/usage/subagents/agent-deadbeef.meta.json +0 -0
  125. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/__init__.py +0 -0
  126. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_check_agent_invocation.py +0 -0
  127. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_consolidate_memory.py +0 -0
  128. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_hook_utils.py +0 -0
  129. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_permission_handler.py +0 -0
  130. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_permission_handler_toast.py +0 -0
  131. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_pip_reinstall_reminder.py +0 -0
  132. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_planner_check.py +0 -0
  133. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_planner_check_dev.py +0 -0
  134. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_post_tool.py +0 -0
  135. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_pre_tool.py +0 -0
  136. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_recall_inject.py +0 -0
  137. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_record_review_decision.py +0 -0
  138. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_record_tier_outcome.py +0 -0
  139. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_restore_session.py +0 -0
  140. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_review_hint_inject.py +0 -0
  141. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_select_tier.py +0 -0
  142. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_select_tier_escalation.py +0 -0
  143. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_session_start.py +0 -0
  144. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_session_stop.py +0 -0
  145. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_session_utils.py +0 -0
  146. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_settings_local_absolute_paths.py +0 -0
  147. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_similarity_boost.py +0 -0
  148. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_statusline.py +0 -0
  149. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_statusline_template_sync.py +0 -0
  150. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_sync_check.py +0 -0
  151. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/hooks/test_template_guard.py +0 -0
  152. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/skills/__init__.py +0 -0
  153. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/skills/_skill_helpers.py +0 -0
  154. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/skills/test_dev_workflow_no_task_type.py +0 -0
  155. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/skills/test_init_session_no_task_type.py +0 -0
  156. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/skills/test_planner_lightweight.py +0 -0
  157. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/skills/test_recall_skill.py +0 -0
  158. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/skills/test_session_backlog_reconciliation.py +0 -0
  159. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/skills/test_setup_templates.py +0 -0
  160. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/skills/test_start_skill_bugfix_flow.py +0 -0
  161. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/skills/test_start_skill_new_flow.py +0 -0
  162. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/skills/test_start_skill_security_audit_phase.py +0 -0
  163. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_check_deletions.py +0 -0
  164. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_cli_ask.py +0 -0
  165. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_cli_entry.py +0 -0
  166. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_cli_init.py +0 -0
  167. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_cli_list.py +0 -0
  168. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_cli_plan.py +0 -0
  169. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_cli_recall.py +0 -0
  170. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_cli_tier.py +0 -0
  171. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_cli_update_breaking_changes.py +0 -0
  172. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_cli_update_deletions.py +0 -0
  173. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_db.py +0 -0
  174. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_docstring_consistency.py +0 -0
  175. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_embedding.py +0 -0
  176. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_excludes.py +0 -0
  177. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_extract_breaking_changes.py +0 -0
  178. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_mcp_server_elicit.py +0 -0
  179. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_migrate.py +0 -0
  180. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_paths.py +0 -0
  181. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_plan_validator.py +0 -0
  182. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_pre_compact.py +0 -0
  183. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_pre_tool_hook.py +0 -0
  184. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_precompact_additional.py +0 -0
  185. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_precompact_toctou_fixes.py +0 -0
  186. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_pricing.py +0 -0
  187. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_recall_chunker.py +0 -0
  188. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_recall_index.py +0 -0
  189. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_references_migration.py +0 -0
  190. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_session_utils_additional.py +0 -0
  191. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_skill_no_builtin_conflict.py +0 -0
  192. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_statusline.py +0 -0
  193. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_stop_additional.py +0 -0
  194. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_stop_hook.py +0 -0
  195. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_stop_precompact_fixes.py +0 -0
  196. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_sync_template_stop.py +0 -0
  197. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_template_pre_tool_hook.py +0 -0
  198. {claude_code_conductor-2.29.4 → claude_code_conductor-2.30.0}/tests/test_usage_ingester.py +0 -0
  199. {claude_code_conductor-2.29.4 → 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` を直接読み込む(スラッシュコマンド自動展開は Claude Code 専用機能)
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
 
@@ -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,27 @@
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
+
3
25
  ## [2.29.4] - 2026-05-31
4
26
 
5
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 スキーマに変更なし。
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-code-conductor
3
- Version: 2.29.4
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 # AGENTS.md / .agents/skills / .codex を生成
269
- c3 init --platform cursor # .cursor/rules / .cursor/mcp.json を生成
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` で単一選択・複数選択を維持します。Claude Code の `Agent` / `Skill` tool 前提は、Codex では `.codex/agents/` と `.agents/skills/`、Cursor では `.cursor/rules/c3-core.mdc` で読み替えます。
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 # AGENTS.md / .agents/skills / .codex を生成
222
- c3 init --platform cursor # .cursor/rules / .cursor/mcp.json を生成
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` で単一選択・複数選択を維持します。Claude Code の `Agent` / `Skill` tool 前提は、Codex では `.codex/agents/` と `.agents/skills/`、Cursor では `.cursor/rules/c3-core.mdc` で読み替えます。
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,3 +1,3 @@
1
1
  """Claude Code Conductor (C3) - multi-agent orchestration framework for Claude Code."""
2
2
 
3
- __version__ = "2.29.4"
3
+ __version__ = "2.30.0"
@@ -1,4 +1,4 @@
1
- """Generate Codex and Cursor adapter files from the canonical ``.claude/`` tree."""
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
@@ -48,6 +48,8 @@ def handle(args: argparse.Namespace) -> int:
48
48
  findings.extend(_check_codex_adapter())
49
49
  if "cursor" in platforms:
50
50
  findings.extend(_check_cursor_adapter())
51
+ if "opencode" in platforms:
52
+ findings.extend(_check_opencode_adapter())
51
53
 
52
54
  exit_code = 0
53
55
  for status, label, detail in findings:
@@ -117,6 +119,25 @@ def _check_codex_adapter() -> list[tuple[str, str, str]]:
117
119
  return findings
118
120
 
119
121
 
122
+ def _check_opencode_adapter() -> list[tuple[str, str, str]]:
123
+ root = claude_root_for(Path.cwd())
124
+ if root is None:
125
+ return [(_WARN, "opencode adapter", "skipped (.claude/ not found)")]
126
+ findings = []
127
+ agents_md = root / "AGENTS.md"
128
+ opencode_agents = root / ".opencode" / "agents"
129
+ findings.append(_file_or_warn("AGENTS.md", agents_md, "run `c3 init --platform opencode`"))
130
+ findings.append(
131
+ _dir_or_warn(".opencode/agents", opencode_agents, "run `c3 init --platform opencode`")
132
+ )
133
+ opencode = shutil.which("opencode")
134
+ if opencode is None:
135
+ findings.append((_WARN, "opencode binary", "not on PATH; install OpenCode CLI to use the adapter"))
136
+ else:
137
+ findings.append((_OK, "opencode binary", opencode))
138
+ return findings
139
+
140
+
120
141
  def _check_cursor_adapter() -> list[tuple[str, str, str]]:
121
142
  root = claude_root_for(Path.cwd())
122
143
  if root is None:
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- SUPPORTED_PLATFORMS = ("claude", "codex", "cursor")
5
+ SUPPORTED_PLATFORMS = ("claude", "codex", "cursor", "opencode")
6
6
  PLATFORM_CHOICES = (*SUPPORTED_PLATFORMS, "all")
7
7
 
8
8