claude-code-conductor 2.73.0__tar.gz → 2.75.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 (277) hide show
  1. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/docs/config-policy.md +24 -1
  2. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/statusline.py +6 -3
  3. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.gitignore +4 -0
  4. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/CHANGELOG.md +62 -0
  5. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/PKG-INFO +27 -1
  6. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/README.md +26 -0
  7. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/__init__.py +1 -1
  8. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/cli_init.py +74 -2
  9. claude_code_conductor-2.75.0/tests/_sync_semantics.py +421 -0
  10. claude_code_conductor-2.75.0/tests/conftest.py +57 -0
  11. claude_code_conductor-2.75.0/tests/hooks/test_statusline_reconfigure_guard.py +197 -0
  12. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_claude_gitignore.py +13 -2
  13. claude_code_conductor-2.75.0/tests/test_cli_init_symlink_guard.py +704 -0
  14. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_statusline.py +10 -1
  15. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_stop_agent_memory_warn.py +5 -22
  16. claude_code_conductor-2.75.0/tests/test_three_file_sync.py +1316 -0
  17. claude_code_conductor-2.73.0/tests/conftest.py +0 -15
  18. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/.gitignore +0 -0
  19. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/CLAUDE.md +0 -0
  20. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/agents/architect.md +0 -0
  21. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/agents/code-reviewer.md +0 -0
  22. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/agents/design-critic.md +0 -0
  23. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/agents/developer.md +0 -0
  24. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/agents/doc-writer.md +0 -0
  25. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/agents/interviewer.md +0 -0
  26. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/agents/planner.md +0 -0
  27. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/agents/project-setup.md +0 -0
  28. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/agents/security-reviewer.md +0 -0
  29. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/agents/systematic-debugger.md +0 -0
  30. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/agents/tester.md +0 -0
  31. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/agents/wt_developer.md +0 -0
  32. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/agents/wt_systematic-debugger.md +0 -0
  33. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/agents/wt_tester.md +0 -0
  34. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/breaking-changes.txt +0 -0
  35. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/deletions.txt +0 -0
  36. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/docs/autonomous-mode-onboarding.md +0 -0
  37. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/docs/nul-boundary.md +0 -0
  38. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/docs/parallel-agents-setup.md +0 -0
  39. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/docs/platform-adapters.md +0 -0
  40. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/docs/settings.json.md +0 -0
  41. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/_hook_utils.py +0 -0
  42. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/check_agent_invocation.py +0 -0
  43. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/consolidate_memory.py +0 -0
  44. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/patterns_guard.py +0 -0
  45. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/planner_check.py +0 -0
  46. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/post_tool.py +0 -0
  47. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/pre_compact.py +0 -0
  48. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/pre_tool.py +0 -0
  49. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/recall_autorebuild.py +0 -0
  50. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/recall_inject.py +0 -0
  51. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/report_contract_check.py +0 -0
  52. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/report_path_guard.py +0 -0
  53. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/restore_session.py +0 -0
  54. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/select_tier.py +0 -0
  55. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/session_mode_watch.py +0 -0
  56. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/session_start.py +0 -0
  57. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/session_stop.py +0 -0
  58. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/session_utils.py +0 -0
  59. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/stop.py +0 -0
  60. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/tier_autoapply.py +0 -0
  61. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/tier_gap_check.py +0 -0
  62. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/hooks/worktree_guard.py +0 -0
  63. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/memory/.gitkeep +0 -0
  64. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/memory/archive/.gitkeep +0 -0
  65. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/memory/sessions/.gitkeep +0 -0
  66. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/reports/.gitkeep +0 -0
  67. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/rules/judgment-principles.md +0 -0
  68. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/rules/promoted/index.md +0 -0
  69. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/settings.json +0 -0
  70. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/autonomous-mode/SKILL.md +0 -0
  71. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/autonomous-mode/scripts/mode_line.py +0 -0
  72. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/brainstorm/SKILL.md +0 -0
  73. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/codex-review/SKILL.md +0 -0
  74. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/dev-workflow/SKILL.md +0 -0
  75. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/dev-workflow/references/c3-omission-declaration.md +0 -0
  76. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/dev-workflow/references/code-review-checklist.md +0 -0
  77. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/dev-workflow/references/design-critic-rubric.md +0 -0
  78. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/dev-workflow/references/design-rubric.md +0 -0
  79. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/dev-workflow/references/interview-rubric.md +0 -0
  80. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/dev-workflow/references/plan-design-guidelines.md +0 -0
  81. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/dev-workflow/references/reachability-map.md +0 -0
  82. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/dev-workflow/references/record-protocol.md +0 -0
  83. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/dev-workflow/references/security-review-checklist.md +0 -0
  84. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/dev-workflow/scripts/detect_execution_verification.py +0 -0
  85. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/dev-workflow/scripts/record_agent_outcome.py +0 -0
  86. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/dev-workflow/scripts/record_review_decision.py +0 -0
  87. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/dev-workflow/scripts/review_hint_inject.py +0 -0
  88. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/develop/SKILL.md +0 -0
  89. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/doc/SKILL.md +0 -0
  90. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/extract-lib/SKILL.md +0 -0
  91. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/init-session/SKILL.md +0 -0
  92. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/init-session/scripts/session_guard.py +0 -0
  93. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/mcp-config/SKILL.md +0 -0
  94. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/parallel-agents/SKILL.md +0 -0
  95. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/pattern-status/SKILL.md +0 -0
  96. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/promote-pattern/SKILL.md +0 -0
  97. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/recall/SKILL.md +0 -0
  98. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/report-timestamp/SKILL.md +0 -0
  99. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/report-timestamp/scripts/get_timestamp.py +0 -0
  100. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/review-phase/SKILL.md +0 -0
  101. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/setup/SKILL.md +0 -0
  102. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/setup/reference.md +0 -0
  103. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/setup/templates/coding-standards-template.md +0 -0
  104. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/setup/templates/project-conventions-template.md +0 -0
  105. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/start/SKILL.md +0 -0
  106. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/skills/start/scripts/archive_reports.py +0 -0
  107. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/state/.gitkeep +0 -0
  108. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/state/setup_done.flag +0 -0
  109. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/.claude/tmp/.gitkeep +0 -0
  110. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/ARCHITECTURE.md +0 -0
  111. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/LICENSE +0 -0
  112. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/LICENSES/fastembed-LICENSE +0 -0
  113. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/LICENSES/fastembed-NOTICE +0 -0
  114. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/LICENSES/numpy-LICENSE +0 -0
  115. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/LICENSES/onnxruntime-LICENSE +0 -0
  116. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/LICENSES/paraphrase-multilingual-MiniLM-L12-v2-LICENSE +0 -0
  117. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/hatch_build.py +0 -0
  118. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/pyproject.toml +0 -0
  119. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/__main__.py +0 -0
  120. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/_db_params.py +0 -0
  121. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/_excludes.py +0 -0
  122. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/_terminal.py +0 -0
  123. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/adapters.py +0 -0
  124. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/cli.py +0 -0
  125. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/cli_ask.py +0 -0
  126. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/cli_doctor.py +0 -0
  127. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/cli_list.py +0 -0
  128. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/cli_metrics.py +0 -0
  129. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/cli_plan.py +0 -0
  130. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/cli_recall.py +0 -0
  131. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/cli_run.py +0 -0
  132. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/cli_tier.py +0 -0
  133. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/cli_update.py +0 -0
  134. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/db.py +0 -0
  135. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/embedding.py +0 -0
  136. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/gitutil.py +0 -0
  137. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/mcp_server.py +0 -0
  138. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/migrate.py +0 -0
  139. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/migrations/001_initial.sql +0 -0
  140. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/migrations/002_agent_cost_runs.sql +0 -0
  141. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/migrations/003_tier_cost.sql +0 -0
  142. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/migrations/004_agent_outcomes.sql +0 -0
  143. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/migrations/005_drop_agent_tier_bandit.sql +0 -0
  144. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/migrations/006_review_decisions_severity.sql +0 -0
  145. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/migrations/007_review_decisions_resolution.sql +0 -0
  146. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/migrations/008_drop_agent_runs.sql +0 -0
  147. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/migrations/README.md +0 -0
  148. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/migrations/__init__.py +0 -0
  149. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/paths.py +0 -0
  150. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/plan_validator.py +0 -0
  151. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/platforms.py +0 -0
  152. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/pricing.py +0 -0
  153. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/question.py +0 -0
  154. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/recall_chunker.py +0 -0
  155. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/recall_index.py +0 -0
  156. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/refgraph.py +0 -0
  157. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/src/c3/usage_ingester.py +0 -0
  158. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/__init__.py +0 -0
  159. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/_pre_compact_helpers.py +0 -0
  160. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/fixtures/usage/README.md +0 -0
  161. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/fixtures/usage/mainline.jsonl +0 -0
  162. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/fixtures/usage/subagents/agent-deadbeef.jsonl +0 -0
  163. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/fixtures/usage/subagents/agent-deadbeef.meta.json +0 -0
  164. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/__init__.py +0 -0
  165. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_check_agent_invocation.py +0 -0
  166. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_consolidate_memory.py +0 -0
  167. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_detect_execution_verification.py +0 -0
  168. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_hook_utils.py +0 -0
  169. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_pip_reinstall_reminder.py +0 -0
  170. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_planner_check.py +0 -0
  171. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_planner_check_dev.py +0 -0
  172. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_post_tool.py +0 -0
  173. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_pre_tool.py +0 -0
  174. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_recall_autorebuild.py +0 -0
  175. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_recall_inject.py +0 -0
  176. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_record_agent_outcome.py +0 -0
  177. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_record_review_decision.py +0 -0
  178. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_report_path_guard.py +0 -0
  179. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_restore_session.py +0 -0
  180. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_review_hint_inject.py +0 -0
  181. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_select_tier.py +0 -0
  182. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_select_tier_escalation.py +0 -0
  183. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_session_start.py +0 -0
  184. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_session_stop.py +0 -0
  185. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_session_utils.py +0 -0
  186. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_settings_local_absolute_paths.py +0 -0
  187. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_settings_tier_autoapply_registration.py +0 -0
  188. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_similarity_boost.py +0 -0
  189. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_statusline.py +0 -0
  190. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_statusline_template_sync.py +0 -0
  191. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_sync_check.py +0 -0
  192. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_template_guard.py +0 -0
  193. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_tier_autoapply.py +0 -0
  194. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_tier_gap_check.py +0 -0
  195. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/hooks/test_tier_security_fixes.py +0 -0
  196. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/__init__.py +0 -0
  197. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/_skill_helpers.py +0 -0
  198. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_c3_omission_declaration.py +0 -0
  199. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_dev_workflow_no_task_type.py +0 -0
  200. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_e0_verification_exit.py +0 -0
  201. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_init_session_no_task_type.py +0 -0
  202. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_marker_compliance.py +0 -0
  203. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_parallel_agents_skill_tier.py +0 -0
  204. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_planner_lightweight.py +0 -0
  205. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_reachability_map.py +0 -0
  206. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_recall_skill.py +0 -0
  207. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_session_backlog_reconciliation.py +0 -0
  208. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_session_guard.py +0 -0
  209. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_setup_templates.py +0 -0
  210. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_start_skill_bugfix_flow.py +0 -0
  211. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_start_skill_new_flow.py +0 -0
  212. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/skills/test_start_skill_security_audit_phase.py +0 -0
  213. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_adapters.py +0 -0
  214. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_archive_reports.py +0 -0
  215. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_audit_review_decisions.py +0 -0
  216. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_check_deletions.py +0 -0
  217. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_ci_workflows.py +0 -0
  218. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_cli_ask.py +0 -0
  219. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_cli_doctor.py +0 -0
  220. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_cli_doctor_launcher.py +0 -0
  221. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_cli_entry.py +0 -0
  222. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_cli_init.py +0 -0
  223. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_cli_list.py +0 -0
  224. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_cli_metrics.py +0 -0
  225. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_cli_plan.py +0 -0
  226. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_cli_recall.py +0 -0
  227. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_cli_run.py +0 -0
  228. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_cli_tier.py +0 -0
  229. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_cli_update_breaking_changes.py +0 -0
  230. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_cli_update_deletions.py +0 -0
  231. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_db.py +0 -0
  232. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_db_connect_lint.py +0 -0
  233. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_docstring_consistency.py +0 -0
  234. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_embedding.py +0 -0
  235. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_excludes.py +0 -0
  236. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_extract_breaking_changes.py +0 -0
  237. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_gitutil.py +0 -0
  238. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_hooks_stdin_idiom.py +0 -0
  239. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_init_only_patterns.py +0 -0
  240. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_mcp_server_elicit.py +0 -0
  241. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_migrate.py +0 -0
  242. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_mode_line.py +0 -0
  243. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_no_bare_python_launcher.py +0 -0
  244. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_no_passonly_tests.py +0 -0
  245. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_nul_boundary_lint.py +0 -0
  246. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_paths.py +0 -0
  247. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_patterns_guard.py +0 -0
  248. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_permission_handler_removal.py +0 -0
  249. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_plan_validator.py +0 -0
  250. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_pre_compact.py +0 -0
  251. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_pre_tool_hook.py +0 -0
  252. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_precompact_additional.py +0 -0
  253. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_precompact_toctou_fixes.py +0 -0
  254. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_pricing.py +0 -0
  255. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_recall_chunker.py +0 -0
  256. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_recall_index.py +0 -0
  257. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_references_migration.py +0 -0
  258. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_refgraph.py +0 -0
  259. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_refgraph_query.py +0 -0
  260. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_refgraph_structural.py +0 -0
  261. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_report_contract_check.py +0 -0
  262. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_scripts_src_bootstrap.py +0 -0
  263. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_scripts_stdout_encoding.py +0 -0
  264. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_session_mode_watch.py +0 -0
  265. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_session_utils_additional.py +0 -0
  266. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_settings_hooks_registration.py +0 -0
  267. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_skill_no_builtin_conflict.py +0 -0
  268. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_start_skill_archive_contract.py +0 -0
  269. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_stop_additional.py +0 -0
  270. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_stop_hook.py +0 -0
  271. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_stop_precompact_fixes.py +0 -0
  272. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_sync_template_stop.py +0 -0
  273. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_template_pre_tool_hook.py +0 -0
  274. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_usage_ingester.py +0 -0
  275. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_verify_wheel.py +0 -0
  276. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_worktree_guard.py +0 -0
  277. {claude_code_conductor-2.73.0 → claude_code_conductor-2.75.0}/tests/test_wt_agent_sync.py +0 -0
@@ -283,17 +283,40 @@ C3 の wheel 配布除外パターンは **3 つのファイルに分散して
283
283
  **KEEP 対象が sdist exclude 配下にある場合は `pyproject.toml` の force-include も同期対象**:
284
284
  公開ビルドは sdist を経由するため、sdist から落ちたファイルは wheel にも届かない。
285
285
 
286
+ この辺(KEEP ↔ sdist exclude / force-include)は `tests/test_three_file_sync.py` が双方向に機械検証する
287
+ (救済漏れと、用途不明な force-include キーの増殖の両方を検出する)。
288
+ ただし **KEEP に相当する配布必須ファイルは force-include による救済を認めず、ignore 規則そのもの(否定行)で戻す**
289
+ (force-include で救うと git 履歴から消える脆い救済になるため。force-include が担うのは sdist exclude 経路の救済に限る)。
290
+ この検査は**配布元 C3 のリポジトリ専用**である: 配布元 C3 が公開する wheel に `tests/` は含まれず、
291
+ 利用先プロジェクトにこの検査は配置されない。ただし**配布元 C3 が PyPI へ公開する第二の成果物である
292
+ sdist には `tests/` が含まれる**(`pyproject.toml` の sdist `include`)。sdist は PyPI で公開されるため
293
+ `tests/` 配下の内容は第三者が閲覧可能であり、機密情報を書いてはならない。
294
+
286
295
  ### 同期確認の方法
287
296
 
288
297
  `.dev/hooks/_sync_check.py`(PostToolUse hook)が、3 ファイルのいずれかを変更した時に
289
298
  残り 2 ファイルの同期を `stderr` で警告する。警告が出たら必ず対応する。
290
299
 
300
+ 同期の実効一致はテスト 2 本が機械検証する(hook の警告は編集時の即時注意喚起、テストは CI /
301
+ フルスイートでの機械判定という役割分担):
302
+
303
+ | テスト | 検証する辺 |
304
+ |---|---|
305
+ | `tests/test_excludes.py` | `_excludes.py` ↔ `hatch_build.py`(パターン集合の完全一致) |
306
+ | `tests/test_three_file_sync.py` | `.gitignore` ↔ `_excludes.py`(挙動の一致)・`pyproject.toml` の sdist exclude / force-include |
307
+
308
+ これらのテストも**配布元 C3 のリポジトリ専用**である: 配布元 C3 が公開する wheel に `tests/` は
309
+ 含まれず、利用先プロジェクトにこれらのテストは配置されない。ただし**配布元 C3 が PyPI へ公開する
310
+ 第二の成果物である sdist には `tests/` が含まれる**(`pyproject.toml` の sdist `include`)。
311
+ sdist は PyPI で公開されるため `tests/` 配下の内容は第三者が閲覧可能であり、機密情報を書いてはならない。
312
+
291
313
  ### 変更手順
292
314
 
293
315
  1. `.gitignore` / `_excludes.py` / `hatch_build.py` のいずれかを変更
294
316
  2. `_sync_check.py` の警告を確認
295
317
  3. 残り 2 ファイルに同じパターンを追加(または削除)。3 ファイルが既に同じ意図を持っている場合は、出遅れた 1 ファイルを合わせるだけでよい(配布元の root `.gitignore` を `KEEP_PATTERNS` の意図へ合わせた 2026-08-14 の是正が実例)
296
- 4. 配布元では `python scripts/verify_wheel.py` で wheel 実体を機械検証する(`scripts/` は配布物に含まれないため、利用先には存在しないコマンド)
318
+ 4. 意図的差分(3 ファイルの意図をあえて揃えない例外)を増減する場合は、`tests/test_three_file_sync.py` の許容リスト(理由文字列必須)と件数定数群を同時更新する(配布元専用。増減いずれの場合もレビュー対象)
319
+ 5. 配布元では `python scripts/verify_wheel.py` で wheel 実体を機械検証する(`scripts/` は配布物に含まれないため、利用先には存在しないコマンド)
297
320
 
298
321
  ### 過去の同期漏れ defect
299
322
 
@@ -13,9 +13,12 @@ import threading
13
13
  from datetime import datetime, timezone
14
14
  from typing import Any
15
15
 
16
- sys.stdout.reconfigure(encoding='utf-8')
17
- sys.stderr.reconfigure(encoding='utf-8')
18
- sys.stdin.reconfigure(encoding='utf-8')
16
+ try:
17
+ sys.stdin.reconfigure(encoding='utf-8')
18
+ sys.stdout.reconfigure(encoding='utf-8')
19
+ sys.stderr.reconfigure(encoding='utf-8')
20
+ except AttributeError:
21
+ pass
19
22
 
20
23
  MAX_INPUT = 64 * 1024 # 64 KB
21
24
 
@@ -86,3 +86,7 @@ site/
86
86
  # Personal Claude Code overrides (per-user / per-worktree, never committed)
87
87
  # wheel からは _excludes.py / hatch_build.py で既に除外済み。git でも tracking しない方針。
88
88
  .claude/settings.local.json
89
+
90
+ # agent 作業残骸 pytest_temp.ini の再発防止ガード(2026-05-02 混入・v0.4.2〔44be00f〕で削除+
91
+ # EXCLUDE_PATTERNS ガード化。本行はその git 側の対)
92
+ .claude/pytest_temp.ini
@@ -1,5 +1,67 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.75.0] - 2026-08-16
4
+
5
+ ### 追加
6
+
7
+ - **`c3 init` のテンプレート展開(`_copytree`)に symlink / NTFS ジャンクション防御を追加した**:
8
+ 各 entry の realpath が「コピー元ルートの realpath + 相対パス」と完全一致することを検査し、
9
+ 一致しない entry(symlink・ジャンクション・壊れたリンク)はコピーせず stderr へ 1 件 1 行の警告を
10
+ 出してスキップする。`is_symlink()` 単体判定はジャンクションに `False` を返すため採用せず、
11
+ realpath 完全一致方式に一本化した。比較の両辺とも realpath 済みのため、コピー元ルート自体が
12
+ リンク経由(macOS の `/tmp` 等)でも全件スキップに縮退しない。加えて:
13
+ - entry 側の realpath が `OSError`(`ELOOP` 含む)を送出した場合は「リンク疑い」として
14
+ 警告付きスキップに倒す(fail-soft・`c3 init` 全体は異常終了しない。ルート側の解決不能は
15
+ テンプレート根本の異常のため従来どおり例外で停止する)
16
+ - `shutil.copy2` 直前にリンク再検証を行い、検査とコピーの間の差し替え(TOCTOU)の窓を狭めた
17
+ (残余の窓は脅威モデル上許容・docstring に記録)
18
+ - 性質テスト `tests/test_cli_init_symlink_guard.py` を新設(symlink 系・ジャンクション実測・
19
+ ルートをリンク経由で渡す回帰ガード・例外系/再検証の検知テストを含む)。ジャンクション/リンク作成の
20
+ テストヘルパー `_make_link` は `tests/conftest.py` へ共有化した
21
+ - `.claude/hooks/statusline.py` の reconfigure 保護テスト
22
+ `tests/hooks/test_statusline_reconfigure_guard.py` を新設した(`reconfigure` 属性を持たない
23
+ ストリーム環境でも hook のロードがクラッシュしないこと)
24
+
25
+ ### 変更
26
+
27
+ - `.claude/hooks/statusline.py` のストリーム reconfigure を canonical 順序(stdin→stdout→stderr)+
28
+ `try/except AttributeError` の確立イディオムへ統一した(配布 hook 22 本で唯一の無保護だった)
29
+ - `README.md` / `docs/getting-started.md` の前提条件に仮想環境(venv)の作成手順を追加した。
30
+ PEP 668(externally-managed-environment)環境で素の `pip install` が失敗する旨と、
31
+ 隔離環境の但し書き 3 点(Claude Code を起動するシェルでも同じ venv を activate すること・
32
+ `pipx install claude-code-conductor` の代替・同一シェルでの `c3 doctor` による PATH 解決確認)を明記した
33
+ - root `.gitignore` に `.claude/pytest_temp.ini` のガード行を追加した(2026-05-02 に agent 作業残骸として
34
+ 混入し v0.4.2 で削除+`EXCLUDE_PATTERNS` ガード化された経緯の git 側の対)。これに伴い
35
+ `tests/test_three_file_sync.py` の許容リスト A から同エントリを削除し、実効検査件数の下限を
36
+ 16 / 16(遊びなし)へ締めた
37
+
38
+ ## [2.74.0] - 2026-08-15
39
+
40
+ ### 追加
41
+
42
+ - **3 ファイル同期(`.gitignore` / `_excludes.py` / `pyproject.toml`)を機械検証化した**:
43
+ `tests/test_three_file_sync.py`(検査)と `tests/_sync_semantics.py`(検出器・引数注入の
44
+ 純粋関数)を追加した。これまで `.dev/hooks/_sync_check.py` の警告(編集時の注意喚起)しか
45
+ 無かった辺を、CI / フルスイートで機械判定する:
46
+ - 辺 1: `_excludes.py` の `EXCLUDE_PATTERNS` / `KEEP_PATTERNS` と root `.gitignore` の意図一致を、
47
+ 表記の一致ではなく**挙動の一致**(プローブパス+`git check-ignore` の実挙動/`should_skip`)で
48
+ 双方向に検証する
49
+ - 辺 2: `KEEP_PATTERNS` と `pyproject.toml` の sdist force-include を双方向に検証する
50
+ (救済漏れと、用途不明な force-include キーの増殖の両方を検出)
51
+ - 辺 3: sdist exclude の `.claude/` エントリが `should_skip` の意図と整合することを検証する
52
+
53
+ 意図的差分は理由文字列必須の許容リストとして明示し、実効検査件数の下限・許容リスト件数を
54
+ 凍結して「何も検査していないのに緑」になる退化を塞いでいる。
55
+ `.dev/hooks/_sync_check.py` は編集時の即時フィードバック層として存置する。
56
+
57
+ ### 変更
58
+
59
+ - `/CLAUDE.md` §2 と `.claude/docs/config-policy.md` §6 に、上記の機械検証 2 本と
60
+ 許容リスト・件数定数群の同時更新の運用を追記した(**配布元 C3 のリポジトリ専用の検査**である旨の
61
+ 但し書き付き。配布元 C3 が公開する wheel に `tests/` は含まれず利用先プロジェクトには配置されないが、
62
+ 配布元 C3 が PyPI へ公開する第二の成果物である sdist には `tests/` が含まれる。sdist は PyPI で
63
+ 公開されるため `tests/` 配下の内容は第三者が閲覧可能であり、機密情報を書いてはならない)。
64
+
3
65
  ## [2.73.0] - 2026-08-15
4
66
 
5
67
  ### 追加
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: claude-code-conductor
3
- Version: 2.73.0
3
+ Version: 2.75.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
@@ -268,6 +268,30 @@ C3 の `.claude/` はプロジェクトコードに一切触れません。既
268
268
  - [Claude Code](https://claude.ai/code) がインストール済みでログインしていること
269
269
  - Python 3.10 以上がインストール済みであること
270
270
 
271
+ **仮想環境(venv)の準備(推奨)**
272
+
273
+ Python の導入方法によっては、素の `pip install` が PEP 668(externally-managed-environment)により拒否されます(Debian/Ubuntu の apt 版 Python、Homebrew の Python など)。仮想環境(venv)を作ってその中へインストールすれば、この制約を受けずに済みます。
274
+
275
+ Windows(PowerShell):
276
+
277
+ ```powershell
278
+ python -m venv .venv
279
+ .\.venv\Scripts\Activate.ps1
280
+ ```
281
+
282
+ macOS / Linux:
283
+
284
+ ```bash
285
+ python3 -m venv .venv
286
+ source .venv/bin/activate
287
+ ```
288
+
289
+ venv に入れた場合の注意:
290
+
291
+ - C3 の hook は `c3 run` で起動されるため、**Claude Code を起動するシェルでも同じ venv を activate してください**。activate されていないシェルから Claude Code を起動すると `c3` が見つからず、hook が動作しません
292
+ - venv を使わずグローバルに使いたい場合は [pipx](https://pipx.pypa.io/) が代替になります: `pipx install claude-code-conductor`
293
+ - インストール後は、**Claude Code を起動するのと同じシェルで** `c3 doctor` を実行し、`c3` が PATH で解決されることを確認してください(`c3 doctor` が検査するのは実行中シェルの PATH です。別のシェルで実行しても、Claude Code の hook が起動される文脈は再現できません)
294
+
271
295
  ### 手順(推奨: PyPI から)
272
296
 
273
297
  **1. C3 をインストールする**
@@ -276,6 +300,8 @@ C3 の `.claude/` はプロジェクトコードに一切触れません。既
276
300
  pip install claude-code-conductor
277
301
  ```
278
302
 
303
+ > このコマンドが PEP 668(externally-managed-environment)で拒否される場合や、インストール後に hook が動作しない場合は、[前提条件](#前提条件)の venv 手順(activate するシェルの注意点を含む)を参照してください。
304
+
279
305
  **2. プロジェクトに `.claude/` を展開する**
280
306
 
281
307
  ```bash
@@ -223,6 +223,30 @@ C3 の `.claude/` はプロジェクトコードに一切触れません。既
223
223
  - [Claude Code](https://claude.ai/code) がインストール済みでログインしていること
224
224
  - Python 3.10 以上がインストール済みであること
225
225
 
226
+ **仮想環境(venv)の準備(推奨)**
227
+
228
+ Python の導入方法によっては、素の `pip install` が PEP 668(externally-managed-environment)により拒否されます(Debian/Ubuntu の apt 版 Python、Homebrew の Python など)。仮想環境(venv)を作ってその中へインストールすれば、この制約を受けずに済みます。
229
+
230
+ Windows(PowerShell):
231
+
232
+ ```powershell
233
+ python -m venv .venv
234
+ .\.venv\Scripts\Activate.ps1
235
+ ```
236
+
237
+ macOS / Linux:
238
+
239
+ ```bash
240
+ python3 -m venv .venv
241
+ source .venv/bin/activate
242
+ ```
243
+
244
+ venv に入れた場合の注意:
245
+
246
+ - C3 の hook は `c3 run` で起動されるため、**Claude Code を起動するシェルでも同じ venv を activate してください**。activate されていないシェルから Claude Code を起動すると `c3` が見つからず、hook が動作しません
247
+ - venv を使わずグローバルに使いたい場合は [pipx](https://pipx.pypa.io/) が代替になります: `pipx install claude-code-conductor`
248
+ - インストール後は、**Claude Code を起動するのと同じシェルで** `c3 doctor` を実行し、`c3` が PATH で解決されることを確認してください(`c3 doctor` が検査するのは実行中シェルの PATH です。別のシェルで実行しても、Claude Code の hook が起動される文脈は再現できません)
249
+
226
250
  ### 手順(推奨: PyPI から)
227
251
 
228
252
  **1. C3 をインストールする**
@@ -231,6 +255,8 @@ C3 の `.claude/` はプロジェクトコードに一切触れません。既
231
255
  pip install claude-code-conductor
232
256
  ```
233
257
 
258
+ > このコマンドが PEP 668(externally-managed-environment)で拒否される場合や、インストール後に hook が動作しない場合は、[前提条件](#前提条件)の venv 手順(activate するシェルの注意点を含む)を参照してください。
259
+
234
260
  **2. プロジェクトに `.claude/` を展開する**
235
261
 
236
262
  ```bash
@@ -1,3 +1,3 @@
1
1
  """Claude Code Conductor (C3) - multi-agent orchestration framework for Claude Code."""
2
2
 
3
- __version__ = "2.73.0"
3
+ __version__ = "2.75.0"
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import argparse
6
+ import os
6
7
  import shutil
7
8
  import sys
8
9
  from collections.abc import Callable
@@ -181,28 +182,99 @@ def _do_git_init(target_root: Path) -> None:
181
182
  )
182
183
 
183
184
 
184
- def _copytree(src: Path, dst: Path, *, root: Path | None = None) -> int:
185
+ def _is_link_entry(entry: Path, real_root: str, rel: str) -> bool:
186
+ """FR-4 choke point: realpath 完全一致でリンク経由の entry を検出する。
187
+
188
+ ``entry.is_symlink()`` は NTFS ディレクトリジャンクションに ``False`` を返し
189
+ 素通りする(ADR-3・既知パターンの再発 5 回)ため採用しない。判定は
190
+ 「entry の realpath」と「コピー元ルートの realpath + ルートからの相対パス」の
191
+ 完全一致(``.claude/skills/start/scripts/archive_reports.py`` の
192
+ ``_archive_dir_is_contained`` と同じ realpath 封じ込め方式)。
193
+
194
+ ``real_root`` は**呼び出し側で解決済みの** コピー元ルートの realpath(文字列)を
195
+ 受け取る契約(ADR-3 追補 2・``_copytree`` が再帰境界で 1 回だけ計算して伝播する)。
196
+ 本関数は root 側の realpath を行わない。比較の両辺とも realpath 済みであることが
197
+ 判定の前提であり、その担保は呼び出し側の責務になる。
198
+
199
+ entry 側の realpath は ``OSError``(ELOOP・EACCES 等)を送出しうる。解決できない
200
+ entry は安全側に倒して「リンク疑い(``True``)」として扱い、呼び出し側の
201
+ 警告付きスキップに委ねる(fail-soft・ADR-3 追補 1)。
202
+ """
203
+ # expected は「rel の各コンポーネントをリンクとして解決せず」文字列結合した
204
+ # 期待パス。os.path.realpath はここでは呼ばない(呼ぶと entry 側と同じ
205
+ # リンクを辿ってしまい、判定そのものが無効化される)。
206
+ expected = os.path.normpath(os.path.join(real_root, *rel.split("/")))
207
+ try:
208
+ actual = os.path.realpath(entry)
209
+ except OSError:
210
+ return True
211
+ return actual != expected
212
+
213
+
214
+ def _copytree(
215
+ src: Path, dst: Path, *, root: Path | None = None, real_root: str | None = None
216
+ ) -> int:
185
217
  """Copy ``src`` -> ``dst`` recursively, skipping personal/working files.
186
218
 
187
219
  ``root`` defaults to ``src`` and represents the ``.claude/`` directory; the
188
220
  relative path from ``root`` is what ``should_skip`` matches against.
189
221
  Returns the number of regular files written.
222
+
223
+ ``real_root`` は ``root`` の realpath(解決済み文字列)。``None`` の初回呼び出しで
224
+ 1 回だけ計算し、再帰には計算済みの値を渡す(ADR-3 追補 2 の hoist。entry 総数 N 回の
225
+ 重複計算を 1 回に落とす)。
226
+
227
+ root 側 realpath の失敗(``OSError``)は捕捉せず伝播させる。root が解決不能なのは
228
+ テンプレート根本の異常であり、全 entry を「リンク疑い」として警告付きスキップし
229
+ 「0 件コピーの exit 0」を返すより、例外で止める方が利用者に正しく伝わるため
230
+ (per-entry の fail-soft はコピー継続に意味がある場合の設計であり、根本が解決不能なら
231
+ 継続に意味がない・ADR-3 追補 1)。
232
+
233
+ リンク判定 ``_is_link_entry`` の適用位置はファイル経路の 2 箇所のみ:
234
+ (i) ``should_skip`` 前段の初回判定 (ii) ``shutil.copy2`` 直前の再検証。
235
+ ディレクトリ側に再検証は追加しない。ディレクトリ entry が判定後にリンクへ
236
+ 差し替わっても、再帰先の per-entry 検査で全子 entry の realpath が
237
+ ``real_root`` + rel と一致しなくなり内容は漏れないため(構造的再検証・ADR-3 追補 3)。
190
238
  """
191
239
  if root is None:
192
240
  root = src
241
+ if real_root is None:
242
+ # root 側の realpath はここで 1 回だけ。失敗は上記のとおり伝播させる。
243
+ real_root = os.path.realpath(root)
193
244
  dst.mkdir(parents=True, exist_ok=True)
194
245
  count = 0
195
246
  for entry in src.iterdir():
196
247
  rel = entry.relative_to(root).as_posix()
197
248
  target = dst / entry.name
249
+ # FR-4: リンク経由の entry は is_dir()/is_file() 分岐より前にスキップする
250
+ # (両者ともリンクを暗黙に辿るため)。EXCLUDE 対象かどうかに関わらず
251
+ # 検査するため should_skip より前段に置く(架空の EXCLUDE リンクも警告する・
252
+ # architecture DC-GP-003 裁定)。
253
+ if _is_link_entry(entry, real_root, rel):
254
+ print(
255
+ f"c3 init: リンク(symlink/junction)疑いの entry をスキップしました: {rel}",
256
+ file=sys.stderr,
257
+ )
258
+ continue
198
259
  if entry.is_dir():
199
- count += _copytree(entry, target, root=root)
260
+ count += _copytree(entry, target, root=root, real_root=real_root)
200
261
  # Drop directories that ended up empty (everything inside was skipped).
201
262
  if not any(target.iterdir()):
202
263
  target.rmdir()
203
264
  elif entry.is_file():
204
265
  if should_skip(rel):
205
266
  continue
267
+ # 初回判定から copy2 到達までの間にリンクへ差し替わる TOCTOU を狭めるため、
268
+ # copy2 の直前で同じ choke point を再検証する(ADR-3 追補 3)。
269
+ # 残余リスク: 再検証と copy2 の間の窓は閉じない。窓を閉じる ``O_NOFOLLOW`` は
270
+ # POSIX 限定で Windows を含む配布対象では採用できないため不採用とし、
271
+ # 脅威モデル(ローカル開発者ツール)上この残余窓は許容する(ADR-3 追補 5)。
272
+ if _is_link_entry(entry, real_root, rel):
273
+ print(
274
+ f"c3 init: リンク(symlink/junction)疑いの entry をスキップしました: {rel}",
275
+ file=sys.stderr,
276
+ )
277
+ continue
206
278
  shutil.copy2(entry, target)
207
279
  count += 1
208
280
  return count