claude-code-conductor 2.48.1__tar.gz → 2.50.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 (221) hide show
  1. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/agents/architect.md +1 -0
  2. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/agents/planner.md +1 -0
  3. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/docs/platform-adapters.md +12 -1
  4. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/dev-workflow/SKILL.md +15 -0
  5. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/init-session/SKILL.md +35 -6
  6. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/report-timestamp/SKILL.md +10 -0
  7. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.gitignore +1 -0
  8. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/CHANGELOG.md +34 -0
  9. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/PKG-INFO +1 -1
  10. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/hatch_build.py +2 -0
  11. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/__init__.py +1 -1
  12. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/_excludes.py +2 -0
  13. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/adapters.py +2 -2
  14. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/cli_doctor.py +77 -0
  15. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_adapters.py +44 -1
  16. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_cli_doctor.py +168 -0
  17. claude_code_conductor-2.50.0/tests/test_excludes.py +473 -0
  18. claude_code_conductor-2.48.1/tests/test_excludes.py +0 -65
  19. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/CLAUDE.md +0 -0
  20. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/agents/code-reviewer.md +0 -0
  21. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/agents/design-critic.md +0 -0
  22. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/agents/developer.md +0 -0
  23. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/agents/doc-writer.md +0 -0
  24. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/agents/interviewer.md +0 -0
  25. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/agents/project-setup.md +0 -0
  26. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/agents/security-reviewer.md +0 -0
  27. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/agents/systematic-debugger.md +0 -0
  28. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/agents/tester.md +0 -0
  29. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/agents/wt_developer.md +0 -0
  30. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/agents/wt_systematic-debugger.md +0 -0
  31. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/agents/wt_tester.md +0 -0
  32. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/breaking-changes.txt +0 -0
  33. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/deletions.txt +0 -0
  34. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/docs/config-policy.md +0 -0
  35. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/docs/parallel-agents-setup.md +0 -0
  36. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/docs/settings.json.md +0 -0
  37. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/_hook_utils.py +0 -0
  38. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/check_agent_invocation.py +0 -0
  39. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/consolidate_memory.py +0 -0
  40. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/permission_handler.py +0 -0
  41. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/permission_handler_toast.py +0 -0
  42. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/planner_check.py +0 -0
  43. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/post_tool.py +0 -0
  44. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/pre_compact.py +0 -0
  45. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/pre_tool.py +0 -0
  46. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/recall_autorebuild.py +0 -0
  47. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/recall_inject.py +0 -0
  48. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/restore_session.py +0 -0
  49. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/select_tier.py +0 -0
  50. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/session_start.py +0 -0
  51. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/session_stop.py +0 -0
  52. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/session_utils.py +0 -0
  53. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/statusline.py +0 -0
  54. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/stop.py +0 -0
  55. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/tier_autoapply.py +0 -0
  56. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/tier_gap_check.py +0 -0
  57. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/hooks/worktree_guard.py +0 -0
  58. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/memory/.gitkeep +0 -0
  59. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/permission_rules.json +0 -0
  60. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/rules/promoted/index.md +0 -0
  61. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/settings.json +0 -0
  62. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/brainstorm/SKILL.md +0 -0
  63. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/codex-review/SKILL.md +0 -0
  64. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/dev-workflow/references/code-review-checklist.md +0 -0
  65. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/dev-workflow/references/design-critic-rubric.md +0 -0
  66. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/dev-workflow/references/design-rubric.md +0 -0
  67. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/dev-workflow/references/interview-rubric.md +0 -0
  68. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/dev-workflow/references/plan-design-guidelines.md +0 -0
  69. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/dev-workflow/references/security-review-checklist.md +0 -0
  70. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/dev-workflow/scripts/record_agent_outcome.py +0 -0
  71. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/dev-workflow/scripts/record_review_decision.py +0 -0
  72. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/dev-workflow/scripts/review_hint_inject.py +0 -0
  73. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/develop/SKILL.md +0 -0
  74. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/doc/SKILL.md +0 -0
  75. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/extract-lib/SKILL.md +0 -0
  76. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/init-session/scripts/session_guard.py +0 -0
  77. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/mcp-config/SKILL.md +0 -0
  78. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/parallel-agents/SKILL.md +0 -0
  79. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/pattern-status/SKILL.md +0 -0
  80. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/promote-pattern/SKILL.md +0 -0
  81. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/recall/SKILL.md +0 -0
  82. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/report-timestamp/scripts/get_timestamp.py +0 -0
  83. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/review-phase/SKILL.md +0 -0
  84. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/setup/SKILL.md +0 -0
  85. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/setup/reference.md +0 -0
  86. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/setup/templates/coding-standards-template.md +0 -0
  87. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/setup/templates/project-conventions-template.md +0 -0
  88. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/skills/start/SKILL.md +0 -0
  89. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/.claude/state/.gitkeep +0 -0
  90. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/ARCHITECTURE.md +0 -0
  91. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/LICENSE +0 -0
  92. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/LICENSES/fastembed-LICENSE +0 -0
  93. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/LICENSES/fastembed-NOTICE +0 -0
  94. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/LICENSES/numpy-LICENSE +0 -0
  95. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/LICENSES/onnxruntime-LICENSE +0 -0
  96. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/LICENSES/paraphrase-multilingual-MiniLM-L12-v2-LICENSE +0 -0
  97. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/README.md +0 -0
  98. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/pyproject.toml +0 -0
  99. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/__main__.py +0 -0
  100. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/_db_params.py +0 -0
  101. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/_terminal.py +0 -0
  102. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/cli.py +0 -0
  103. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/cli_ask.py +0 -0
  104. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/cli_init.py +0 -0
  105. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/cli_list.py +0 -0
  106. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/cli_metrics.py +0 -0
  107. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/cli_plan.py +0 -0
  108. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/cli_recall.py +0 -0
  109. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/cli_tier.py +0 -0
  110. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/cli_update.py +0 -0
  111. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/db.py +0 -0
  112. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/embedding.py +0 -0
  113. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/gitutil.py +0 -0
  114. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/mcp_server.py +0 -0
  115. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/migrate.py +0 -0
  116. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/migrations/001_initial.sql +0 -0
  117. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/migrations/002_agent_cost_runs.sql +0 -0
  118. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/migrations/003_tier_cost.sql +0 -0
  119. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/migrations/004_agent_outcomes.sql +0 -0
  120. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/migrations/005_drop_agent_tier_bandit.sql +0 -0
  121. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/migrations/006_review_decisions_severity.sql +0 -0
  122. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/migrations/README.md +0 -0
  123. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/migrations/__init__.py +0 -0
  124. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/paths.py +0 -0
  125. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/plan_validator.py +0 -0
  126. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/platforms.py +0 -0
  127. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/pricing.py +0 -0
  128. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/question.py +0 -0
  129. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/recall_chunker.py +0 -0
  130. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/recall_index.py +0 -0
  131. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/src/c3/usage_ingester.py +0 -0
  132. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/__init__.py +0 -0
  133. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/_pre_compact_helpers.py +0 -0
  134. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/conftest.py +0 -0
  135. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/fixtures/usage/README.md +0 -0
  136. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/fixtures/usage/mainline.jsonl +0 -0
  137. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/fixtures/usage/subagents/agent-deadbeef.jsonl +0 -0
  138. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/fixtures/usage/subagents/agent-deadbeef.meta.json +0 -0
  139. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/__init__.py +0 -0
  140. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_check_agent_invocation.py +0 -0
  141. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_consolidate_memory.py +0 -0
  142. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_hook_utils.py +0 -0
  143. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_permission_handler.py +0 -0
  144. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_permission_handler_toast.py +0 -0
  145. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_pip_reinstall_reminder.py +0 -0
  146. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_planner_check.py +0 -0
  147. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_planner_check_dev.py +0 -0
  148. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_post_tool.py +0 -0
  149. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_pre_tool.py +0 -0
  150. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_recall_autorebuild.py +0 -0
  151. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_recall_inject.py +0 -0
  152. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_record_agent_outcome.py +0 -0
  153. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_record_review_decision.py +0 -0
  154. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_restore_session.py +0 -0
  155. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_review_hint_inject.py +0 -0
  156. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_select_tier.py +0 -0
  157. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_select_tier_escalation.py +0 -0
  158. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_session_start.py +0 -0
  159. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_session_stop.py +0 -0
  160. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_session_utils.py +0 -0
  161. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_settings_local_absolute_paths.py +0 -0
  162. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_settings_tier_autoapply_registration.py +0 -0
  163. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_similarity_boost.py +0 -0
  164. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_statusline.py +0 -0
  165. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_statusline_template_sync.py +0 -0
  166. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_sync_check.py +0 -0
  167. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_template_guard.py +0 -0
  168. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_tier_autoapply.py +0 -0
  169. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_tier_gap_check.py +0 -0
  170. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/hooks/test_tier_security_fixes.py +0 -0
  171. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/skills/__init__.py +0 -0
  172. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/skills/_skill_helpers.py +0 -0
  173. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/skills/test_dev_workflow_no_task_type.py +0 -0
  174. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/skills/test_init_session_no_task_type.py +0 -0
  175. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/skills/test_parallel_agents_skill_tier.py +0 -0
  176. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/skills/test_planner_lightweight.py +0 -0
  177. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/skills/test_recall_skill.py +0 -0
  178. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/skills/test_session_backlog_reconciliation.py +0 -0
  179. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/skills/test_session_guard.py +0 -0
  180. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/skills/test_setup_templates.py +0 -0
  181. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/skills/test_start_skill_bugfix_flow.py +0 -0
  182. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/skills/test_start_skill_new_flow.py +0 -0
  183. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/skills/test_start_skill_security_audit_phase.py +0 -0
  184. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_check_deletions.py +0 -0
  185. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_cli_ask.py +0 -0
  186. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_cli_entry.py +0 -0
  187. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_cli_init.py +0 -0
  188. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_cli_list.py +0 -0
  189. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_cli_metrics.py +0 -0
  190. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_cli_plan.py +0 -0
  191. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_cli_recall.py +0 -0
  192. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_cli_tier.py +0 -0
  193. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_cli_update_breaking_changes.py +0 -0
  194. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_cli_update_deletions.py +0 -0
  195. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_db.py +0 -0
  196. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_docstring_consistency.py +0 -0
  197. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_embedding.py +0 -0
  198. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_extract_breaking_changes.py +0 -0
  199. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_gitutil.py +0 -0
  200. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_mcp_server_elicit.py +0 -0
  201. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_migrate.py +0 -0
  202. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_paths.py +0 -0
  203. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_plan_validator.py +0 -0
  204. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_pre_compact.py +0 -0
  205. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_pre_tool_hook.py +0 -0
  206. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_precompact_additional.py +0 -0
  207. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_precompact_toctou_fixes.py +0 -0
  208. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_pricing.py +0 -0
  209. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_recall_chunker.py +0 -0
  210. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_recall_index.py +0 -0
  211. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_references_migration.py +0 -0
  212. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_session_utils_additional.py +0 -0
  213. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_skill_no_builtin_conflict.py +0 -0
  214. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_statusline.py +0 -0
  215. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_stop_additional.py +0 -0
  216. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_stop_hook.py +0 -0
  217. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_stop_precompact_fixes.py +0 -0
  218. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_sync_template_stop.py +0 -0
  219. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_template_pre_tool_hook.py +0 -0
  220. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_usage_ingester.py +0 -0
  221. {claude_code_conductor-2.48.1 → claude_code_conductor-2.50.0}/tests/test_worktree_guard.py +0 -0
@@ -5,6 +5,7 @@ description: 設計・技術選定担当。requirements-report を受け取り
5
5
  tools:
6
6
  - Read
7
7
  - Write
8
+ - Edit
8
9
  - Glob
9
10
  - Grep
10
11
  - Skill
@@ -5,6 +5,7 @@ description: 計画立案担当。全レポートを統合しタスク分解し
5
5
  tools:
6
6
  - Read
7
7
  - Write
8
+ - Edit
8
9
  - Glob
9
10
  - Grep
10
11
  - Skill
@@ -11,7 +11,7 @@ C3 は **Claude Code** を canonical platform として設計されているが
11
11
  - 動作差分のまとめ
12
12
 
13
13
  を一箇所にまとめたリファレンス。実装は `src/c3/adapters.py` / `src/c3/mcp_server.py` /
14
- `src/c3/cli_ask.py` / `src/c3/platforms.py` を参照。
14
+ `src/c3/cli_ask.py` / `src/c3/platforms.py` / `src/c3/cli_doctor.py` を参照。
15
15
 
16
16
  ---
17
17
 
@@ -92,6 +92,9 @@ python -m c3.mcp_server
92
92
  `C3_PROJECT_ROOT` 環境変数でプロジェクトルートを指定可能(adapter 生成時に自動設定)。
93
93
  ソースインストール時は `PYTHONPATH` も adapter が `<repo>/src` に設定する。
94
94
 
95
+ 生成される `.codex/config.toml` / `.cursor/mcp.json` の `command` は `python` ではなく、
96
+ adapter 生成時点の `sys.executable`(絶対パス)を書き込む。理由は「7. 既知の制限」を参照。
97
+
95
98
  ---
96
99
 
97
100
  ## 4. `c3 ask` CLI fallback
@@ -178,3 +181,11 @@ Claude Code / Codex / Cursor / OpenCode が同じプロジェクトを行き来
178
181
  - **OpenCode の `AskUserQuestion`**: OpenCode adapter は MCP 設定を生成しないため、`c3_ask_user_question` ツールは使わず `AGENTS.md` の指示に従ってユーザーへ直接確認する。`multiSelect: true` は「複数選択の質問」として維持するよう指示済み
179
182
  - **OpenCode の `tools` 制限**: 生成される agent には一律で `bash/read/edit/write/websearch` を付与する。Claude 側 frontmatter の細かな `tools` 制限は反映されない(C3 の `code-reviewer` / `security-reviewer` は Claude 側でもレポート出力のため `write` を持つ)
180
183
  - **改行コード**: adapter 生成ファイルは LF 改行で書き出す(`newline="\n"`)。`.gitattributes` で `eol=lf` を固定済み
184
+ - **Codex の trust 要件**: プロジェクトが Codex に trust されていない場合、`.codex/config.toml` は**エラーなしで無視**される(Codex 公式仕様)。MCP サーバーが読み込まれず `AskUserQuestion` が動かない場合は、まず対象プロジェクトを Codex 側で trust 済みか確認する(Codex CLI: 初回起動時のプロンプトで trust するか、設定で許可済みディレクトリに追加する)
185
+ - **MCP `command` の絶対パス化**: adapter が書き込む `command` は `python` ではなく `sys.executable`(adapter 生成時の絶対パス)を使う。理由:
186
+ - macOS 12.3 以降、無印 `python` は標準に存在しない(`python3` のみ。Homebrew も同様)。`command: "python"` のままだと Codex が MCP spawn 時に program not found となり、「起動時にエラーで読み込まれない」症状になる
187
+ - `python` が PATH 上にあっても、pipx / venv などの隔離環境では `No module named c3` で起動失敗することがある
188
+ - GUI 起動の Codex(Desktop / IDE 拡張)はシェルの PATH を継承しないことがある(最小 PATH)
189
+ - 代案の「POSIX では `python3` にする」は不採用: 無印 python 不在の問題しか救えず、pipx 隔離や GUI PATH 最小の問題には無力なため
190
+ - `c3 doctor --platform codex|cursor` は生成済み config から `command` を読み取り、実行可能か・`<command> -c "import c3"` が成功するかを自己診断する
191
+ - **adapter 生成物はマシン固有**: `command` に埋め込む `sys.executable` は生成したマシン・環境(venv / pipx / システム Python)に依存する絶対パスであるため、adapter 生成物(`.codex/config.toml` / `.cursor/mcp.json` など)はチームで共有せず、各マシンで `c3 init --platform <p>` または `c3 update --platform <p>` を実行して再生成する運用とする
@@ -24,6 +24,21 @@ user-invocable: false
24
24
 
25
25
  ---
26
26
 
27
+ **運転モードによるゲート挙動の切替(既定は HITL・非破壊)**: 各フェーズの承認ゲート
28
+ (**A-4 / B-3 / C-1 / C-2 / C-3 / D-2.5 / D-3 / D-5 / E-1 / E-2 の 10 個**。D-0 は AskUserQuestion を
29
+ 持たない実行モード判別ステップのため承認ゲートに含めない=DC-AS-003)に到達したら、まず
30
+ session.tmp の `モード:` 行を確認する。**有効な自律宣言**(§3-3)でなければ**以下の各ゲートを
31
+ 記載どおり AskUserQuestion で実行する(従来動作)**。有効な自律宣言のときのみ、
32
+ `.claude/skills/autonomous-mode/SKILL.md` の「ゲート対応表」に従って承認ゲートを客観収束条件に
33
+ 付け替える。**非可逆操作の関所・情報不足の質問・重量フェーズ着手前の usage 確認は常に人間**
34
+ (自律でも停止して確認する=人間の 3 関所・§4-1 / requirements §7)。
35
+
36
+ > **skill 未 Read でも『モード行を見て skill を Read せよ』の 1 段で復帰できる** — develop / review-phase を「直接開始」した場合(init-session を経ない起動)、autonomous-mode skill の明示 Read が挟まらない可能性がある。ただし本ブロックが
37
+ > 各ゲートで `モード:` 行の確認を要求するため、skill 未 Read でも「モード行を見て skill を Read せよ」
38
+ > の 1 段で復帰できる(`.claude/skills/autonomous-mode/SKILL.md` 参照・復元の単一障害点を作らない)。
39
+
40
+ ---
41
+
27
42
  ## tier-routing 結果記録の運用
28
43
 
29
44
  各フェーズの承認ゲート・タスク単位で `record_agent_outcome.py` を呼び、role 別に実際に使われた tier の成功/失敗を記録する(architecture-report-20260702-214748.md §3-4)。全記録ブロック共通のルール:
@@ -54,11 +54,18 @@ python .claude/skills/init-session/scripts/session_guard.py mark
54
54
  Glob で `.claude/memory/sessions/*.tmp` を検索し、ファイル名(YYYYMMDD)が最大のものを Read する。
55
55
  ファイルが存在しない場合は「前回セッションなし」として Step 3 へ進む。
56
56
 
57
- > **セキュリティ注記(SR L-2)**: `現在地:` 行の値をユーザーへ表示する前に、
57
+ `モード:` 行も Read 対象に含める。セッションファイル内に `モード: ` で始まる行があれば、Step 3 のサマリ表示と Step 5 の復元判定に使用する。
58
+
59
+ > **セキュリティ注記(SR L-2 表示用)**: `現在地:` 行と `モード:` 行の値をユーザーへ表示する前に、
58
60
  > 制御文字(C0/C1)・DEL・改行(`\n`/`\r`)・`-->`・U+2028/U+2029 を除去して表示すること。
59
61
  > セッションファイルは外部編集が可能な信頼境界であり、悪意ある値が混入した場合の
60
62
  > ターミナルインジェクションを防ぐ。
61
63
 
64
+ > **パス用 choke point(§3-4(b) 封じ込め検査)**: `plan-path` を `Read` 引数に使う場合は、
65
+ > 表示用 SR L-2 とは別に、改行・NUL・制御文字を除去し、絶対パスへ正規化(realpath)して、
66
+ > `~/.claude/plans/` 以下に収まるかを判定する。許可ルート外またはシンボリックリンク解決後に
67
+ > 範囲外になる場合は無効化する。その後、正規化されたパスに対して `Read` で実在確認を行う。
68
+
62
69
  ---
63
70
 
64
71
  ## Step 1.5: 残タスクと git log を照合する(陳腐化チェック)
@@ -97,6 +104,8 @@ Glob で `.claude/memory/sessions/*.tmp` を検索し、ファイル名(YYYYMM
97
104
 
98
105
  **現在地:** {session.tmp の「現在地:」行の値。空なら「(未設定)」と表示。表示前に制御文字・改行・`-->`・U+2028/U+2029 を除去すること(SR L-2)}
99
106
 
107
+ **運転モード:** {session.tmp の「モード:」行の値。無効/不在は「HITL(既定)」と表示。値は SR L-2 でサニタイズする}
108
+
100
109
  **残タスク:**
101
110
  {残タスクリスト。完了済み [x] は省略する}
102
111
 
@@ -156,13 +165,33 @@ AskUserQuestion ツールで以下を提示する:
156
165
  ## Step 5: 選択に応じて分岐する
157
166
 
158
167
  **「続きから作業する」の場合:**
159
- Step 1 で読んだ session.tmp の「現在地:」行の値を確認する。
168
+ Step 1 で読んだ session.tmp の「現在地:」行と「モード:」行の値を確認する。
169
+
170
+ > **パス用封じ込め検査の機械実行必須化(SR-AI-001)**: realpath 正規化+許可ルート封じ込め判定は、
171
+ > `.claude/skills/autonomous-mode/scripts/mode_line.py` を Bash 経由で実際に呼び出して判定結果を得ること。
172
+ > 文字列の目視比較で代替しないこと。スクリプト不在(配布先等)の場合は無効=HITL(fail-closed)。
173
+ > 呼び出し例(セッションファイルからモード行を直接パイプで渡す。コマンドラインに現れるリテラルは
174
+ > ファイルパスのみで、モード行の内容はパイプのデータとして流れシェルに評価されない):
175
+ > `grep -m1 '^モード: ' .claude/memory/sessions/{YYYYMMDD}.tmp | python .claude/skills/autonomous-mode/scripts/mode_line.py`
176
+ > → `VALID<TAB>{正規化済み絶対パス}`(exit 0)/`INVALID<TAB>{理由コード}`(exit 1)の 1 行で判定する。
177
+ > モード行の値をコマンド文字列(here-string・引数・ダブルクォート内展開)に直接埋め込んではならない。
160
178
 
161
179
  - **「現在地:」が非空かつ「完了」でない場合**(dev-workflow フェーズ進行中):
162
- 残タスクに直接着手せず、対応 skill 経由で再開し、各エージェント出力後の Approval Flow を守ること。
163
- - フェーズ D 実装中 → `develop` skill を使う
164
- - フェーズ E レビュー中 → `review-phase` skill を使う
165
- - それ以外 → `start` skill を使う
180
+
181
+ - **「モード:」行が有効な自律宣言の場合**(autonomous-mode skill の有効性判定 3 条件をすべて満たす):
182
+ 1. `モード:` 行から `plan=` で指定されたパスを取得する
183
+ 2. そのパスに対して、Step 1 の「パス用 choke point」検査を実施する(改行/NUL 除去 → realpath 正規化 → `~/.claude/plans/` 封じ込め判定)
184
+ 2.5. 正規化されたパスに対し `Read` で実在確認を行う。存在しなければ無効化し、「モード行が無効(プラン不在/許可ルート外)→ HITL で継続」を明示表示する
185
+ 3. 検査と実在確認を通ったら、`.claude/skills/autonomous-mode/SKILL.md` を Read して、ゲート対応表と運用規約を確認する
186
+ 4. その後、対応 skill(`develop` / `review-phase` / `start` など)を起動して運転を継続する
187
+
188
+ - **「モード:」行が無効(不在・`plan=` 欠落・許可ルート外・実在しない plan)の場合**:
189
+ 「モード行が無効(プラン不在/許可ルート外)→ HITL で継続」を明示表示し、従来どおり HITL 動作で対応 skill を起動する
190
+
191
+ - 残タスクに直接着手せず、対応 skill 経由で再開し、各エージェント出力後の Approval Flow を守ること:
192
+ - フェーズ D 実装中 → `develop` skill を使う
193
+ - フェーズ E レビュー中 → `review-phase` skill を使う
194
+ - それ以外 → `start` skill を使う
166
195
 
167
196
  - **「現在地:」が空または「完了」の場合**:
168
197
  従来どおり残タスク(引き継ぎバックログ)の内容を確認してそのまま作業に入る。
@@ -21,3 +21,13 @@ python "${CLAUDE_SKILL_DIR}/scripts/get_timestamp.py"
21
21
 
22
22
  - PowerShell・bash の date コマンドは使わない(時刻部分が 000000 になる場合がある)
23
23
  - python コマンドが使えない場合のみ `python3` にフォールバックする
24
+
25
+ ## Bash を持たないエージェントの場合(親がタイムスタンプを渡す)
26
+
27
+ architect / planner / design-critic 等、tools に Bash を含まないエージェントは本スクリプトを実行できない。
28
+ その場合は**サブエージェントを起動する親 Claude が本 skill でタイムスタンプを取得し、
29
+ 出力先レポートのファイル名を確定させた形で起動プロンプトに含める**こと(例: 「レポートは
30
+ `.claude/reports/architecture-report-20260714-213000.md` に Write。このファイル名を厳守」)。
31
+ エージェント側でのタイムスタンプの手採番(推測・連番)は禁止する。
32
+ (Bash を持たないエージェントに Bash を追加する対処は採らない: レポート role の最小権限を崩し、
33
+ allow 済み git コマンド経由で「非可逆操作は人間の関所」を迂回する経路が開くため)
@@ -83,6 +83,7 @@ site/
83
83
  # v2.1.0: tdd-develop / worktree-tdd-workflow 廃止後の復活防止
84
84
  .claude/agents/tdd-develop.md
85
85
  .claude/skills/worktree-tdd-workflow/
86
+ .claude/skills/autonomous-mode/
86
87
 
87
88
  # Personal Claude Code overrides (per-user / per-worktree, never committed)
88
89
  # wheel からは _excludes.py / hatch_build.py で既に除外済み。git でも tracking しない方針。
@@ -1,5 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.50.0] - 2026-07-17
4
+
5
+ ### 修正
6
+
7
+ - **MCP 設定の `command` を `sys.executable` 絶対パス化(Codex / Cursor adapter)**: 生成される `.codex/config.toml` / `.cursor/mcp.json` の `command` が `"python"` ハードコードだったため、無印 `python` が存在しない環境(macOS 12.3 以降の標準 / Homebrew)・pipx / venv 隔離(`No module named c3`)・GUI 起動の Codex(シェル PATH 非継承)で MCP サーバーが起動時エラーになり `c3_ask_user_question` が使えなかった問題を修正。`c3 init` / `c3 update --platform` を実行した Python の絶対パスを埋め込む(TOML は既存 `_toml_escape` でエスケープ)。X 上の実利用報告「Claude Code だと動くが Codex だと起動時にエラーで読み込まれない」が起点
8
+
9
+ ### 追加
10
+
11
+ - **`c3 doctor` の MCP 起動自己診断**: 生成済み config(`.codex/config.toml` / `.cursor/mcp.json`)から `command` を読み取り、(a) 実行可能性 (b) `<command> -c "import c3"` の成否を検証する。失敗時は WARN と `c3 update --platform <p>` での再生成を案内。この種の環境起因の起動失敗を利用者が一発で自己診断できるようにした
12
+
13
+ ### 変更
14
+
15
+ - `.claude/docs/platform-adapters.md` の「既知の制限」に、Codex の trust 要件(未 trust プロジェクトの `.codex/config.toml` は**エラーなしで無視**される・trust 手順)・`command` 絶対パス化の理由・adapter 生成物のマシン固有性(チームで共有せず各マシンで `c3 init/update --platform` 再生成する運用)を追記
16
+
17
+ ### 後方互換
18
+
19
+ - 既存の生成済み config は次回 `c3 update --platform` 実行まで従来のまま。再生成すると `command` が実行環境の絶対パスに変わる(マシン固有・意図された挙動。チーム共有リポジトリでは各メンバーが自マシンで再生成する)。**破壊的変更なし**
20
+
21
+ ## [2.49.0] - 2026-07-17
22
+
23
+ ### 追加
24
+
25
+ - **運転モード切替の接続点(autonomous-mode 対応・既定 HITL・非破壊)**: dev-workflow に「運転モードによるゲート挙動の切替」集中参照ブロックを 1 つ追加(既存 10 承認ゲート本文は無改変)。session.tmp の `モード:` 行が有効な自律宣言のときのみ `.claude/skills/autonomous-mode/SKILL.md` のゲート対応表へ委譲する。**自律モード skill 本体は配布対象外**(配布元でのドッグフーディング熟成中・利用先には存在しないためモード行検証が常に無効=完全従来動作で挙動変化ゼロ)
26
+ - **init-session のモード行復元導線**: Step 1/3/5 に `モード:` 行の読込・サマリ表示(`運転モード:`)・自律復帰分岐を追加。plan-path は表示用 SR L-2 とは別の**パス用封じ込め型防御**(改行/NUL 除去→realpath 正規化→許可ルート `~/.claude/plans/` のみへの封じ込め→実在確認)を機械実行(`mode_line.py` へのパイプ渡し・目視代替禁止・スクリプト不在時は無効=HITL の fail-closed)で検証する。無効時は「HITL で継続」を明示表示
27
+ - **配布除外の 3 ファイル同期+機械検査**: `_excludes.py` / `hatch_build.py` に `skills/autonomous-mode/*`、`.gitignore` に `.claude/skills/autonomous-mode/` を追加(配布切替は 3 行削除で往復可)。`tests/test_excludes.py` に 3 ファイル同期の同一性検査(importlib+正規表現フォールバック)・除外パターン検査・モード行有効性判定テスト(空白パス・symlink/junction 偽装・CLI 契約)計 12 件を追加
28
+
29
+ ### 変更
30
+
31
+ - `agents/architect.md`・`agents/planner.md` の tools に `Edit` を追加、`skills/report-timestamp/SKILL.md` に「Bash 非保持エージェントは親がタイムスタンプを取得しファイル名確定済みで渡す(手採番禁止・Bash 追加は最小権限維持のため採らない)」節を追記(2026-07-14 の設計監査で確定した運用契約の明文化)
32
+
33
+ ### 後方互換
34
+
35
+ - `モード:` 行が無い session.tmp では全ゲートが従来どおり AskUserQuestion で動作(機械検証で担保)。wheel の `_template/` 一覧は本リリース前後で増減なし(HEAD 基準ビルドとの全数比較で確認)。**破壊的変更なし**
36
+
3
37
  ## [2.48.1] - 2026-07-15
4
38
 
5
39
  ### 修正
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-code-conductor
3
- Version: 2.48.1
3
+ Version: 2.50.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
@@ -60,6 +60,8 @@ EXCLUDE_PATTERNS: tuple[str, ...] = (
60
60
  # v2.1.0: tdd-develop / worktree-tdd-workflow 廃止(planner が TDD を 3-wave に分解する設計に統一)
61
61
  "agents/tdd-develop.md",
62
62
  "skills/worktree-tdd-workflow/*",
63
+ # autonomous-mode skill を配布除外での熟成・配布切替は本行削除で往復可
64
+ "skills/autonomous-mode/*",
63
65
  )
64
66
 
65
67
  KEEP_PATTERNS: tuple[str, ...] = (
@@ -1,3 +1,3 @@
1
1
  """Claude Code Conductor (C3) - multi-agent orchestration framework for Claude Code."""
2
2
 
3
- __version__ = "2.48.1"
3
+ __version__ = "2.50.0"
@@ -57,6 +57,8 @@ EXCLUDE_PATTERNS: tuple[str, ...] = (
57
57
  # v2.1.0: tdd-develop / worktree-tdd-workflow 廃止(planner が TDD を 3-wave に分解する設計に統一)
58
58
  "agents/tdd-develop.md",
59
59
  "skills/worktree-tdd-workflow/*",
60
+ # autonomous-mode skill を配布除外での熟成・配布切替は本行削除で往復可
61
+ "skills/autonomous-mode/*",
60
62
  )
61
63
 
62
64
  KEEP_PATTERNS: tuple[str, ...] = (
@@ -223,7 +223,7 @@ def _write_cursor_mcp(target_root: Path, *, dry_run: bool) -> list[AdapterAction
223
223
  if pythonpath is not None:
224
224
  env["PYTHONPATH"] = str(pythonpath)
225
225
  servers["c3"] = {
226
- "command": "python",
226
+ "command": sys.executable,
227
227
  "args": ["-m", "c3.mcp_server"],
228
228
  "env": env,
229
229
  }
@@ -331,7 +331,7 @@ tool, read the matching generated Codex skill from `.agents/skills/<name>/SKILL.
331
331
  def _codex_config_section() -> str:
332
332
  lines = [
333
333
  "[mcp_servers.c3]",
334
- 'command = "python"',
334
+ f'command = "{_toml_escape(sys.executable)}"',
335
335
  'args = ["-m", "c3.mcp_server"]',
336
336
  "startup_timeout_sec = 10",
337
337
  "tool_timeout_sec = 600",
@@ -4,7 +4,9 @@ from __future__ import annotations
4
4
 
5
5
  import argparse
6
6
  import json
7
+ import re
7
8
  import shutil
9
+ import subprocess
8
10
  from pathlib import Path
9
11
 
10
12
  from c3._terminal import supports_color as _supports_color
@@ -15,6 +17,8 @@ _OK = "OK"
15
17
  _WARN = "WARN"
16
18
  _ERR = "ERR"
17
19
 
20
+ _MCP_STARTUP_TIMEOUT_SEC = 10
21
+
18
22
 
19
23
  def register(subparsers: argparse._SubParsersAction) -> None:
20
24
  parser = subparsers.add_parser(
@@ -111,6 +115,9 @@ def _check_codex_adapter() -> list[tuple[str, str, str]]:
111
115
  findings.append(_dir_or_warn(".agents/skills", skills, "run `c3 init --platform codex`"))
112
116
  findings.append(_file_or_warn(".codex/config.toml", config, "run `c3 init --platform codex`"))
113
117
  findings.append(_dir_or_warn(".codex/agents", custom_agents, "run `c3 init --platform codex`"))
118
+ if config.is_file():
119
+ command = _extract_codex_mcp_command(config.read_text(encoding="utf-8"))
120
+ findings.append(_check_mcp_command_startup("codex MCP startup", command, "codex"))
114
121
  codex = shutil.which("codex")
115
122
  if codex is None:
116
123
  findings.append((_WARN, "codex binary", "not on PATH; install Codex CLI to use the adapter"))
@@ -147,6 +154,9 @@ def _check_cursor_adapter() -> list[tuple[str, str, str]]:
147
154
  mcp = root / ".cursor" / "mcp.json"
148
155
  findings.append(_file_or_warn(".cursor/rules/c3-core.mdc", rule, "run `c3 init --platform cursor`"))
149
156
  findings.append(_file_or_warn(".cursor/mcp.json", mcp, "run `c3 init --platform cursor`"))
157
+ if mcp.is_file():
158
+ command = _extract_cursor_mcp_command(mcp.read_text(encoding="utf-8"))
159
+ findings.append(_check_mcp_command_startup("cursor MCP startup", command, "cursor"))
150
160
  cursor = shutil.which("cursor-agent") or shutil.which("cursor")
151
161
  if cursor is None:
152
162
  findings.append((_WARN, "cursor binary", "not on PATH; install Cursor CLI/editor to use the adapter"))
@@ -155,6 +165,73 @@ def _check_cursor_adapter() -> list[tuple[str, str, str]]:
155
165
  return findings
156
166
 
157
167
 
168
+ def _extract_codex_mcp_command(config_text: str) -> str | None:
169
+ """Read the ``command`` value from the ``[mcp_servers.c3]`` table.
170
+
171
+ Uses a targeted regex rather than a full TOML parser: ``tomllib`` is only
172
+ available from Python 3.11 while C3 supports 3.10+, and the generated
173
+ config is always a single-line ``key = "value"`` pair under the section.
174
+ """
175
+ match = re.search(
176
+ r'(?ms)^\[mcp_servers\.c3\]\s*$.*?^command\s*=\s*"((?:[^"\\]|\\.)*)"',
177
+ config_text,
178
+ )
179
+ if match is None:
180
+ return None
181
+ return match.group(1).replace('\\"', '"').replace("\\\\", "\\")
182
+
183
+
184
+ def _extract_cursor_mcp_command(mcp_json_text: str) -> str | None:
185
+ try:
186
+ payload = json.loads(mcp_json_text)
187
+ except json.JSONDecodeError:
188
+ return None
189
+ if not isinstance(payload, dict):
190
+ return None
191
+ servers = payload.get("mcpServers")
192
+ if not isinstance(servers, dict):
193
+ return None
194
+ c3 = servers.get("c3")
195
+ if not isinstance(c3, dict):
196
+ return None
197
+ command = c3.get("command")
198
+ return command if isinstance(command, str) else None
199
+
200
+
201
+ def _check_mcp_command_startup(
202
+ label: str, command: str | None, platform: str
203
+ ) -> tuple[str, str, str]:
204
+ """Verify that the generated MCP ``command`` can actually launch and import c3."""
205
+ hint = f"run `c3 update --platform {platform}` to regenerate"
206
+ if not command:
207
+ return _WARN, label, f"command not found in generated config; {hint}"
208
+
209
+ resolvable = (Path(command).is_absolute() and Path(command).is_file()) or (
210
+ shutil.which(command) is not None
211
+ )
212
+ if not resolvable:
213
+ return _WARN, label, f"command not executable: {command}; {hint}"
214
+
215
+ try:
216
+ result = subprocess.run(
217
+ [command, "-c", "import c3"],
218
+ capture_output=True,
219
+ text=True,
220
+ timeout=_MCP_STARTUP_TIMEOUT_SEC,
221
+ )
222
+ except (OSError, subprocess.TimeoutExpired) as exc:
223
+ return _WARN, label, f"failed to launch {command}: {exc}; {hint}"
224
+
225
+ if result.returncode != 0:
226
+ detail = next(
227
+ (line for line in reversed(result.stderr.strip().splitlines()) if line.strip()),
228
+ "import c3 failed",
229
+ )
230
+ return _WARN, label, f'`{command} -c "import c3"` failed: {detail}; {hint}'
231
+
232
+ return _OK, label, f"{command} -c \"import c3\" succeeded"
233
+
234
+
158
235
  def _file_or_warn(label: str, path: Path, hint: str) -> tuple[str, str, str]:
159
236
  if path.is_file():
160
237
  return _OK, label, str(path)
@@ -58,6 +58,48 @@ def test_toml_multiline_escape_keeps_newlines():
58
58
  assert _toml_multiline_escape(text) == text
59
59
 
60
60
 
61
+ # ----------------------------------------------------------------------
62
+ # MCP `command` resolution — absolute sys.executable, not bare "python"
63
+ # ----------------------------------------------------------------------
64
+
65
+
66
+ def test_codex_config_section_uses_absolute_sys_executable(monkeypatch):
67
+ monkeypatch.setattr(adapters.sys, "executable", r"C:\Python312\python.exe")
68
+
69
+ section = adapters._codex_config_section()
70
+
71
+ assert 'command = "C:\\\\Python312\\\\python.exe"' in section
72
+ assert 'command = "python"' not in section
73
+
74
+
75
+ def test_codex_config_section_escapes_plain_posix_executable(monkeypatch):
76
+ monkeypatch.setattr(adapters.sys, "executable", "/usr/bin/python3")
77
+
78
+ section = adapters._codex_config_section()
79
+
80
+ assert 'command = "/usr/bin/python3"' in section
81
+
82
+
83
+ def test_write_codex_config_writes_absolute_windows_command(tmp_path: Path, monkeypatch):
84
+ monkeypatch.setattr(adapters.sys, "executable", r"C:\Users\dev\venv\Scripts\python.exe")
85
+
86
+ adapters._write_codex_config(tmp_path, dry_run=False)
87
+
88
+ config_text = (tmp_path / ".codex" / "config.toml").read_text(encoding="utf-8")
89
+ assert 'command = "C:\\\\Users\\\\dev\\\\venv\\\\Scripts\\\\python.exe"' in config_text
90
+
91
+
92
+ def test_write_cursor_mcp_uses_absolute_sys_executable(tmp_path: Path, monkeypatch):
93
+ monkeypatch.setattr(adapters.sys, "executable", r"C:\Python312\python.exe")
94
+
95
+ adapters._write_cursor_mcp(tmp_path, dry_run=False)
96
+
97
+ payload = json.loads((tmp_path / ".cursor" / "mcp.json").read_text(encoding="utf-8"))
98
+ command = payload["mcpServers"]["c3"]["command"]
99
+ assert command == r"C:\Python312\python.exe"
100
+ assert Path(command).is_absolute()
101
+
102
+
61
103
  # ----------------------------------------------------------------------
62
104
  # _convert_skill
63
105
  # ----------------------------------------------------------------------
@@ -178,7 +220,8 @@ def test_write_cursor_mcp_creates_file_when_missing(tmp_path: Path):
178
220
  actions = _write_cursor_mcp(target, dry_run=False)
179
221
  assert any(a.action == "add" for a in actions)
180
222
  payload = json.loads((target / ".cursor" / "mcp.json").read_text(encoding="utf-8"))
181
- assert payload["mcpServers"]["c3"]["command"] == "python"
223
+ assert payload["mcpServers"]["c3"]["command"] == sys.executable
224
+ assert Path(payload["mcpServers"]["c3"]["command"]).is_absolute()
182
225
 
183
226
 
184
227
  def test_write_cursor_mcp_rejects_invalid_json(tmp_path: Path):
@@ -7,6 +7,8 @@ in handle() for opencode, codex, and cursor platforms.
7
7
  from __future__ import annotations
8
8
 
9
9
  import argparse
10
+ import subprocess
11
+ import sys
10
12
  from pathlib import Path
11
13
 
12
14
  import c3.cli_doctor as cli_doctor
@@ -181,3 +183,169 @@ def test_check_opencode_adapter_reports_binary_present(tmp_path: Path, monkeypat
181
183
  status == _OK and "opencode binary" in label and fake_path in detail
182
184
  for status, label, detail in findings
183
185
  ), f"Expected OK for 'opencode binary' with path, got: {findings}"
186
+
187
+
188
+ # ---------------------------------------------------------------------------
189
+ # MCP startup self-diagnostic — _check_mcp_command_startup
190
+ # ---------------------------------------------------------------------------
191
+
192
+
193
+ def test_check_mcp_command_startup_ok_when_import_succeeds(monkeypatch):
194
+ """When the resolved command can `import c3`, the check must return OK."""
195
+ monkeypatch.setattr(
196
+ cli_doctor.subprocess,
197
+ "run",
198
+ lambda *a, **k: subprocess.CompletedProcess(a[0], 0, stdout="", stderr=""),
199
+ )
200
+
201
+ status, label, detail = cli_doctor._check_mcp_command_startup(
202
+ "codex MCP startup", sys.executable, "codex"
203
+ )
204
+
205
+ assert status == _OK
206
+ assert "codex MCP startup" == label
207
+ assert "import c3" in detail
208
+
209
+
210
+ def test_check_mcp_command_startup_warns_when_command_missing():
211
+ """When the config has no `command` value at all, the check must WARN."""
212
+ status, label, detail = cli_doctor._check_mcp_command_startup(
213
+ "codex MCP startup", None, "codex"
214
+ )
215
+
216
+ assert status == _WARN
217
+ assert "not found" in detail
218
+ assert "c3 update --platform codex" in detail
219
+
220
+
221
+ def test_check_mcp_command_startup_warns_when_command_not_resolvable(monkeypatch):
222
+ """When the command path/binary cannot be located at all, the check must WARN
223
+ without attempting to spawn a subprocess."""
224
+ monkeypatch.setattr(cli_doctor.shutil, "which", lambda name: None)
225
+ called = []
226
+ monkeypatch.setattr(
227
+ cli_doctor.subprocess,
228
+ "run",
229
+ lambda *a, **k: called.append(a) or subprocess.CompletedProcess(a[0], 0),
230
+ )
231
+
232
+ status, label, detail = cli_doctor._check_mcp_command_startup(
233
+ "cursor MCP startup", "/nonexistent/path/to/python", "cursor"
234
+ )
235
+
236
+ assert status == _WARN
237
+ assert "not executable" in detail
238
+ assert "c3 update --platform cursor" in detail
239
+ assert called == []
240
+
241
+
242
+ def test_check_mcp_command_startup_warns_when_import_c3_fails(monkeypatch):
243
+ """When the resolved command runs but `import c3` fails (e.g. an isolated
244
+ venv/pipx environment without c3 installed), the check must WARN."""
245
+ monkeypatch.setattr(
246
+ cli_doctor.subprocess,
247
+ "run",
248
+ lambda *a, **k: subprocess.CompletedProcess(
249
+ a[0], 1, stdout="", stderr="ModuleNotFoundError: No module named 'c3'"
250
+ ),
251
+ )
252
+
253
+ status, label, detail = cli_doctor._check_mcp_command_startup(
254
+ "codex MCP startup", sys.executable, "codex"
255
+ )
256
+
257
+ assert status == _WARN
258
+ assert "No module named" in detail
259
+ assert "c3 update --platform codex" in detail
260
+
261
+
262
+ def test_check_mcp_command_startup_warns_when_launch_raises(monkeypatch):
263
+ """When subprocess.run itself raises (e.g. the binary vanished between the
264
+ resolvability check and the launch), the check must WARN, not raise."""
265
+ def _boom(*a, **k):
266
+ raise FileNotFoundError("no such file")
267
+
268
+ monkeypatch.setattr(cli_doctor.subprocess, "run", _boom)
269
+
270
+ status, label, detail = cli_doctor._check_mcp_command_startup(
271
+ "codex MCP startup", sys.executable, "codex"
272
+ )
273
+
274
+ assert status == _WARN
275
+ assert "failed to launch" in detail
276
+
277
+
278
+ # ---------------------------------------------------------------------------
279
+ # command extraction from generated adapter configs
280
+ # ---------------------------------------------------------------------------
281
+
282
+
283
+ def test_extract_codex_mcp_command_reads_absolute_windows_path():
284
+ config_text = (
285
+ "[mcp_servers.c3]\n"
286
+ 'command = "C:\\\\Python312\\\\python.exe"\n'
287
+ 'args = ["-m", "c3.mcp_server"]\n'
288
+ )
289
+
290
+ command = cli_doctor._extract_codex_mcp_command(config_text)
291
+
292
+ assert command == r"C:\Python312\python.exe"
293
+
294
+
295
+ def test_extract_codex_mcp_command_none_when_section_missing():
296
+ assert cli_doctor._extract_codex_mcp_command("[some_other_table]\nfoo = 1\n") is None
297
+
298
+
299
+ def test_extract_cursor_mcp_command_reads_absolute_path():
300
+ mcp_json = '{"mcpServers": {"c3": {"command": "/usr/bin/python3", "args": []}}}'
301
+
302
+ command = cli_doctor._extract_cursor_mcp_command(mcp_json)
303
+
304
+ assert command == "/usr/bin/python3"
305
+
306
+
307
+ def test_extract_cursor_mcp_command_none_when_invalid_json():
308
+ assert cli_doctor._extract_cursor_mcp_command("{not valid") is None
309
+
310
+
311
+ # ---------------------------------------------------------------------------
312
+ # integration — _check_codex_adapter / _check_cursor_adapter wire the
313
+ # self-diagnostic in using the real, currently-running interpreter
314
+ # ---------------------------------------------------------------------------
315
+
316
+
317
+ def test_check_codex_adapter_includes_ok_mcp_startup_with_real_interpreter(
318
+ tmp_path: Path, monkeypatch
319
+ ):
320
+ """End-to-end: generate a real adapter config pointed at sys.executable
321
+ (which does have c3 importable under the sandbox PYTHONPATH) and confirm
322
+ the doctor wires the self-diagnostic in as OK."""
323
+ (tmp_path / ".claude").mkdir()
324
+ monkeypatch.chdir(tmp_path)
325
+ from c3.adapters import _write_codex_config
326
+
327
+ _write_codex_config(tmp_path, dry_run=False)
328
+
329
+ findings = cli_doctor._check_codex_adapter()
330
+
331
+ assert any(
332
+ status == _OK and label == "codex MCP startup"
333
+ for status, label, _ in findings
334
+ ), f"Expected OK codex MCP startup finding, got: {findings}"
335
+
336
+
337
+ def test_check_cursor_adapter_includes_ok_mcp_startup_with_real_interpreter(
338
+ tmp_path: Path, monkeypatch
339
+ ):
340
+ (tmp_path / ".claude").mkdir()
341
+ monkeypatch.chdir(tmp_path)
342
+ from c3.adapters import _write_cursor_mcp
343
+
344
+ _write_cursor_mcp(tmp_path, dry_run=False)
345
+
346
+ findings = cli_doctor._check_cursor_adapter()
347
+
348
+ assert any(
349
+ status == _OK and label == "cursor MCP startup"
350
+ for status, label, _ in findings
351
+ ), f"Expected OK cursor MCP startup finding, got: {findings}"