claude-code-conductor 0.7.0__tar.gz → 0.7.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/CLAUDE.md +1 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/agents/code-reviewer.md +10 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/agents/developer.md +10 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/agents/security-reviewer.md +10 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/agents/systematic-debugger.md +10 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/agents/tester.md +10 -0
- claude_code_conductor-0.7.1/.claude/hooks/subagent_log.py +212 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/settings.json +2 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/settings.local.json +33 -1
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.gitignore +3 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/CHANGELOG.md +26 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/PKG-INFO +1 -1
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/hatch_build.py +2 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/c3/__init__.py +1 -1
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/c3/_excludes.py +2 -0
- claude_code_conductor-0.7.1/tests/hooks/test_permission_handler.py +725 -0
- claude_code_conductor-0.7.1/tests/hooks/test_restore_session.py +401 -0
- claude_code_conductor-0.7.1/tests/hooks/test_subagent_log.py +900 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/agents/architect.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/agents/doc-writer.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/agents/interviewer.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/agents/planner.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/agents/project-setup.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/agents/tdd-develop.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/docs/parallel-orchestra-manifest.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/docs/settings.json.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/hooks/clear_file_history.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/hooks/enable_sandbox.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/hooks/permission_handler.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/hooks/pre_compact.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/hooks/pre_tool.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/hooks/restore_session.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/hooks/session_utils.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/hooks/statusline.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/hooks/stop.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/hooks/validate_skill_change.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/hooks/worktree_guard.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/memory/.gitkeep +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/permission_rules.json +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/rules/code-review-checklist.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/rules/promoted/index.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/rules/security-review-checklist.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/code-review/SKILL.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/dev-workflow/SKILL.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/develop/SKILL.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/doc/SKILL.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/extract-lib/SKILL.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/init-session/SKILL.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/mcp-config/SKILL.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/pattern-status/SKILL.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/promote-pattern/SKILL.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/report-timestamp/SKILL.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/report-timestamp/scripts/get_timestamp.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/setup/SKILL.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/start/SKILL.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/wave-execution/SKILL.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/skills/worktree-tdd-workflow/SKILL.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/LICENSE +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/README.md +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/pyproject.toml +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/c3/__main__.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/c3/cli.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/c3/cli_doctor.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/c3/cli_init.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/c3/cli_list.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/c3/cli_po.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/c3/cli_update.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/c3/paths.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/c3/po/__init__.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/c3/po/manifest.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/c3/po/run.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/parallel_orchestra/__init__.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/parallel_orchestra/_exceptions.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/parallel_orchestra/cli.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/parallel_orchestra/manifest.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/parallel_orchestra/report.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/src/parallel_orchestra/runner.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/__init__.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/conftest.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/hooks/__init__.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/hooks/test_clear_file_history.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/hooks/test_enable_sandbox.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/hooks/test_session_utils.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/hooks/test_statusline.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/hooks/test_statusline_template_sync.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/__init__.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/conftest.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/test_cli.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/test_manifest.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/test_report.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/test_retry_backoff.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/test_review_fixes.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/test_review_fixes2.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/test_review_fixes3.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/test_review_fixes4.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/test_review_fixes5.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/test_runner_t7.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/test_runner_v04_fix.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/test_runner_v04_m1.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/parallel_orchestra/test_runner_v04_m2.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_clear_file_history.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_cli_init.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_cli_list.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_cli_po.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_cli_po_tempfile.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_docstring_consistency.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_enable_sandbox.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_excludes.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_manifest_fixes.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_manifest_yaml_escape.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_paths.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_po_manifest.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_po_run.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_po_waves.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_pre_compact.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_pre_tool_hook.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_precompact_additional.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_precompact_toctou_fixes.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_session_utils_additional.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_statusline.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_stop_additional.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_stop_hook.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_stop_precompact_fixes.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_sync_template_clear_file_history.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_sync_template_stop.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_sync_validate_skill.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_template_pre_tool_hook.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_validate_skill_change.py +0 -0
- {claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/tests/test_worktree_guard.py +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: code-reviewer
|
|
3
3
|
model: sonnet
|
|
4
|
+
memory: project
|
|
4
5
|
description: コード品質レビュー担当。品質・保守性・パフォーマンスをレビューし code-review-report を出力する。ソース編集不可。
|
|
5
6
|
tools:
|
|
6
7
|
- Read
|
|
@@ -15,6 +16,15 @@ tools:
|
|
|
15
16
|
## Core Mandate
|
|
16
17
|
コードの品質・保守性・パフォーマンスをレビューし、改善提案を code-review-report として出力する。
|
|
17
18
|
|
|
19
|
+
## Memory
|
|
20
|
+
- 起動時に `.claude/agent-memory/code-reviewer/MEMORY.md` がシステムプロンプトに自動注入される(フロントマター `memory: project` による)。注入された内容を踏まえてレビューすること。
|
|
21
|
+
- 作業終了時、次回以降のレビューに役立つ知見があれば MEMORY.md に追記する。記録対象は以下に限定する:
|
|
22
|
+
- 再現価値のあるレビュー観点・指摘パターン
|
|
23
|
+
- **許容例外**: ユーザーが指摘を許容した観点と理由(次回レビューでの再指摘を防ぐ)
|
|
24
|
+
- 本プロジェクト特有のコーディング規約・トレードオフ判断
|
|
25
|
+
- 雑記録・一回性の進捗ログは記録しない。MEMORY.md は 200 行以内を保ち、超える場合は価値の低いエントリから削除する。
|
|
26
|
+
- 形式は箇条書き 1 行 + 必要なら次行にインデントで補足。許容例外は `[許容例外]` プレフィックスを付けて理由を併記する。
|
|
27
|
+
|
|
18
28
|
## Key Scope
|
|
19
29
|
|
|
20
30
|
✅ 担当すること:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: developer
|
|
3
3
|
model: sonnet
|
|
4
|
+
memory: project
|
|
4
5
|
description: 実装・デバッグ担当。plan-report に基づき実装し tester が検証できる状態にする。
|
|
5
6
|
tools:
|
|
6
7
|
- Read
|
|
@@ -18,6 +19,15 @@ tools:
|
|
|
18
19
|
## Core Mandate
|
|
19
20
|
plan-report に基づき実装・デバッグ・リファクタリングを行い、tester が検証できる状態にする。
|
|
20
21
|
|
|
22
|
+
## Memory
|
|
23
|
+
- 起動時に `.claude/agent-memory/developer/MEMORY.md` がシステムプロンプトに自動注入される(フロントマター `memory: project` による)。注入された内容を踏まえて作業すること。
|
|
24
|
+
- 作業終了時、次回以降の作業に役立つ知見があれば MEMORY.md に追記する。記録対象は以下に限定する:
|
|
25
|
+
- 再現価値のある実装・リファクタリングのパターン
|
|
26
|
+
- 同じハマり方を繰り返さないための注意点(言語・ライブラリ・ツール特有の落とし穴)
|
|
27
|
+
- 本プロジェクト特有の制約・許容例外(理由とセットで)
|
|
28
|
+
- 雑記録・一回性の進捗ログは記録しない。MEMORY.md は 200 行以内を保ち、超える場合は価値の低いエントリから削除する。
|
|
29
|
+
- 形式は箇条書き 1 行 + 必要なら次行にインデントで補足。日付や ID は不要(コンテンツ自身が自己説明的であること)。
|
|
30
|
+
|
|
21
31
|
## Key Scope
|
|
22
32
|
|
|
23
33
|
✅ 担当すること:
|
{claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/agents/security-reviewer.md
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: security-reviewer
|
|
3
3
|
model: sonnet
|
|
4
|
+
memory: project
|
|
4
5
|
description: セキュリティ診断担当。脆弱性を診断し security-review-report を出力する。ソース編集不可。
|
|
5
6
|
tools:
|
|
6
7
|
- Read
|
|
@@ -15,6 +16,15 @@ tools:
|
|
|
15
16
|
## Core Mandate
|
|
16
17
|
SQLインジェクション・XSS・認証認可・秘密情報漏洩などの脆弱性を診断し、security-review-report を出力する。
|
|
17
18
|
|
|
19
|
+
## Memory
|
|
20
|
+
- 起動時に `.claude/agent-memory/security-reviewer/MEMORY.md` がシステムプロンプトに自動注入される(フロントマター `memory: project` による)。注入された内容を踏まえて診断すること。
|
|
21
|
+
- 作業終了時、次回以降の診断に役立つ知見があれば MEMORY.md に追記する。記録対象は以下に限定する:
|
|
22
|
+
- 再現価値のある脆弱性パターン・診断観点
|
|
23
|
+
- **許容例外**: ユーザーが指摘を許容したリスク・脅威モデル外と判断した観点と理由(次回診断での再指摘を防ぐ)
|
|
24
|
+
- 本プロジェクト特有の脅威モデル・信頼境界・許容されている設計(理由とセットで)
|
|
25
|
+
- 雑記録・一回性の進捗ログは記録しない。MEMORY.md は 200 行以内を保ち、超える場合は価値の低いエントリから削除する。
|
|
26
|
+
- 形式は箇条書き 1 行 + 必要なら次行にインデントで補足。許容例外は `[許容例外]` プレフィックスを付けて理由を併記する。
|
|
27
|
+
|
|
18
28
|
## Key Scope
|
|
19
29
|
|
|
20
30
|
✅ 担当すること:
|
{claude_code_conductor-0.7.0 → claude_code_conductor-0.7.1}/.claude/agents/systematic-debugger.md
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: systematic-debugger
|
|
3
3
|
model: sonnet
|
|
4
|
+
memory: project
|
|
4
5
|
description: デバッグ調査担当。developer が行き詰まった際に根本原因調査とパターン分析を行い debug-analysis-report を出力する。コードの修正は行わない。
|
|
5
6
|
tools:
|
|
6
7
|
- Read
|
|
@@ -17,6 +18,15 @@ tools:
|
|
|
17
18
|
developer が詰まった問題の根本原因を調査し、debug-analysis-report を出力する。
|
|
18
19
|
コードの修正は行わない。調査と分析のみ担当する。
|
|
19
20
|
|
|
21
|
+
## Memory
|
|
22
|
+
- 起動時に `.claude/agent-memory/systematic-debugger/MEMORY.md` がシステムプロンプトに自動注入される(フロントマター `memory: project` による)。注入された内容を踏まえて調査すること。
|
|
23
|
+
- 作業終了時、次回以降の調査に役立つ知見があれば MEMORY.md に追記する。記録対象は以下に限定する:
|
|
24
|
+
- **過去の根本原因パターン**: 「症状 → 原因」のペア(同じ症状を再調査せずに済む)
|
|
25
|
+
- **有効だった調査経路**: 短時間で原因到達できた Grep / コマンド・差分の見方
|
|
26
|
+
- 本プロジェクト特有の落とし穴(環境・設定・依存関係に起因する繰り返し問題)
|
|
27
|
+
- 雑記録・一回性の進捗ログは記録しない。MEMORY.md は 200 行以内を保ち、超える場合は価値の低いエントリから削除する。
|
|
28
|
+
- 形式は箇条書き 1 行 + 必要なら次行にインデントで補足。「症状 → 原因」のペアは矢印で明示する。
|
|
29
|
+
|
|
20
30
|
## Key Scope
|
|
21
31
|
|
|
22
32
|
✅ 担当すること:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tester
|
|
3
3
|
model: sonnet
|
|
4
|
+
memory: project
|
|
4
5
|
description: テスト設計・実行担当。テスト仕様の設計・実行・test-report を出力する。ソース編集不可。
|
|
5
6
|
tools:
|
|
6
7
|
- Read
|
|
@@ -16,6 +17,15 @@ tools:
|
|
|
16
17
|
## Core Mandate
|
|
17
18
|
テスト仕様の設計・テストコード作成・テスト実行を行い、品質状況を test-report として出力する。
|
|
18
19
|
|
|
20
|
+
## Memory
|
|
21
|
+
- 起動時に `.claude/agent-memory/tester/MEMORY.md` がシステムプロンプトに自動注入される(フロントマター `memory: project` による)。注入された内容を踏まえて作業すること。
|
|
22
|
+
- 作業終了時、次回以降の作業に役立つ知見があれば MEMORY.md に追記する。記録対象は以下に限定する:
|
|
23
|
+
- 再現価値のあるテスト設計パターン(Red の書き方・テスト分割の粒度・モック戦略)
|
|
24
|
+
- 本プロジェクト特有のテスト落とし穴(環境依存・並行実行・フレーク要因)
|
|
25
|
+
- テスト実行コマンド・前提条件などプロジェクト特有の情報
|
|
26
|
+
- 雑記録・一回性の進捗ログは記録しない。MEMORY.md は 200 行以内を保ち、超える場合は価値の低いエントリから削除する。
|
|
27
|
+
- 形式は箇条書き 1 行 + 必要なら次行にインデントで補足。日付や ID は不要(コンテンツ自身が自己説明的であること)。
|
|
28
|
+
|
|
19
29
|
## Key Scope
|
|
20
30
|
|
|
21
31
|
✅ 担当すること:
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""SubagentStart / SubagentStop hook: log agent execution events.
|
|
3
|
+
|
|
4
|
+
C3 開発版専用。配布版(_template/)には含めない(hatch_build.py の
|
|
5
|
+
EXCLUDE_PATTERNS で除外)。settings.local.json の hooks セクションから
|
|
6
|
+
呼ばれる。
|
|
7
|
+
|
|
8
|
+
stdin から受け取った JSON のうちホワイトリスト対象フィールドのみを
|
|
9
|
+
`.claude/logs/agent-runs.jsonl` に追記する。
|
|
10
|
+
SubagentStop 時には同 session_id + agent_id の最古未消費 Start を
|
|
11
|
+
検索して duration_seconds を算出する。
|
|
12
|
+
|
|
13
|
+
公式仕様で SubagentStart / SubagentStop の入力 JSON に agent_id が
|
|
14
|
+
含まれることが確認されたため、agent_id ベースのペアリングに移行した。
|
|
15
|
+
|
|
16
|
+
既知の制限(TOCTOU):
|
|
17
|
+
複数プロセスが同時にログファイルに書き込む場合、_find_unmatched_start が
|
|
18
|
+
読み取った直後に別プロセスが同じ Start を消費する可能性がある(TOCTOU)。
|
|
19
|
+
本スクリプトは C3 開発版・ローカルファイル前提のため、この制限は許容する。
|
|
20
|
+
ロック機構は実装しない。
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import collections
|
|
24
|
+
import json
|
|
25
|
+
import os
|
|
26
|
+
import sys
|
|
27
|
+
from datetime import datetime, timezone
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
sys.stdin.reconfigure(encoding='utf-8')
|
|
31
|
+
sys.stdout.reconfigure(encoding='utf-8')
|
|
32
|
+
sys.stderr.reconfigure(encoding='utf-8')
|
|
33
|
+
except AttributeError:
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
_HOOKS_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
37
|
+
_CLAUDE_DIR = os.path.dirname(_HOOKS_DIR)
|
|
38
|
+
LOG_DIR = os.path.join(_CLAUDE_DIR, 'logs')
|
|
39
|
+
LOG_FILE = os.path.join(LOG_DIR, 'agent-runs.jsonl')
|
|
40
|
+
|
|
41
|
+
# stdin の最大読み込みバイト数 (sec-M-2)
|
|
42
|
+
_MAX_STDIN_BYTES = 1 * 1024 * 1024 # 1 MB
|
|
43
|
+
|
|
44
|
+
# ログ走査の最大行数 (sec-M-2)
|
|
45
|
+
_MAX_SCAN_LINES = 10_000
|
|
46
|
+
|
|
47
|
+
# イベント名定数 (code-L-1)
|
|
48
|
+
_EVENT_START = "SubagentStart"
|
|
49
|
+
_EVENT_STOP = "SubagentStop"
|
|
50
|
+
|
|
51
|
+
# payload のホワイトリスト対象フィールド (sec-M-1)
|
|
52
|
+
_SAFE_PAYLOAD_FIELDS = frozenset({
|
|
53
|
+
'hook_event_name',
|
|
54
|
+
'session_id',
|
|
55
|
+
'agent_id',
|
|
56
|
+
'agent_type',
|
|
57
|
+
'cwd',
|
|
58
|
+
'transcript_path',
|
|
59
|
+
'stop_hook_active',
|
|
60
|
+
'permission_mode',
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
# U+2028 (LINE SEPARATOR) / U+2029 (PARAGRAPH SEPARATOR) の定数 (sec-H-1)
|
|
64
|
+
# ensure_ascii=False の json.dumps はこれらをエスケープしないため、
|
|
65
|
+
# _append_log で明示的に \\u2028 / \\u2029 へ置換する。
|
|
66
|
+
_U2028 = '
'
|
|
67
|
+
_U2029 = '
'
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _now_iso() -> str:
|
|
71
|
+
return datetime.now(timezone.utc).astimezone().isoformat(timespec='seconds')
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _sanitize_payload(payload: dict) -> dict:
|
|
75
|
+
"""ホワイトリスト対象フィールドのみを抽出して返す (sec-M-1)。
|
|
76
|
+
|
|
77
|
+
last_assistant_message / agent_transcript_path 等の長文・任意コンテンツ系を除外し、
|
|
78
|
+
デバッグに必要な cwd / transcript_path は保持する。
|
|
79
|
+
"""
|
|
80
|
+
return {k: v for k, v in payload.items() if k in _SAFE_PAYLOAD_FIELDS}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _read_log_records() -> list[dict]:
|
|
84
|
+
"""LOG_FILE を読み込んで有効な JSONL レコードのリストを返す。
|
|
85
|
+
|
|
86
|
+
末尾 _MAX_SCAN_LINES 行のみ走査してメモリ使用量を抑える (sec-M-2)。
|
|
87
|
+
JSON パース失敗行はスキップする。
|
|
88
|
+
"""
|
|
89
|
+
if not os.path.exists(LOG_FILE):
|
|
90
|
+
return []
|
|
91
|
+
records = []
|
|
92
|
+
with open(LOG_FILE, 'r', encoding='utf-8') as f:
|
|
93
|
+
for line in collections.deque(f, maxlen=_MAX_SCAN_LINES):
|
|
94
|
+
line = line.strip()
|
|
95
|
+
if not line:
|
|
96
|
+
continue
|
|
97
|
+
try:
|
|
98
|
+
records.append(json.loads(line))
|
|
99
|
+
except json.JSONDecodeError:
|
|
100
|
+
continue
|
|
101
|
+
return records
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _find_unmatched_start(
|
|
105
|
+
records: list[dict], session_id: str, agent_id: str
|
|
106
|
+
) -> dict | None:
|
|
107
|
+
"""同 session_id + agent_id の対応 SubagentStop が無い最古 SubagentStart を返す。
|
|
108
|
+
|
|
109
|
+
agent_id ベースでペアリングするため、同 session 内の並列エージェントが
|
|
110
|
+
互いに誤ペアリングすることはない。
|
|
111
|
+
公式仕様で agent_id が SubagentStart / SubagentStop のペイロードに
|
|
112
|
+
含まれることが確認されている。
|
|
113
|
+
|
|
114
|
+
既知の制限(TOCTOU):
|
|
115
|
+
本関数は読み取り後に別プロセスが同 Start を消費する可能性があるが、
|
|
116
|
+
C3 開発版・ローカルファイル前提のため許容する。
|
|
117
|
+
"""
|
|
118
|
+
pending_starts: collections.deque[dict] = collections.deque()
|
|
119
|
+
for r in records:
|
|
120
|
+
p = r.get('payload', {})
|
|
121
|
+
if p.get('session_id') != session_id or p.get('agent_id') != agent_id:
|
|
122
|
+
continue
|
|
123
|
+
event_name = p.get('hook_event_name', '')
|
|
124
|
+
if event_name == _EVENT_START:
|
|
125
|
+
pending_starts.append(r)
|
|
126
|
+
elif event_name == _EVENT_STOP:
|
|
127
|
+
if pending_starts:
|
|
128
|
+
pending_starts.popleft()
|
|
129
|
+
return pending_starts[0] if pending_starts else None
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _calc_duration_seconds(start_ts: str, end_ts: str) -> float | None:
|
|
133
|
+
"""ISO8601 文字列の差分を秒数(小数点3桁)で返す。パース失敗時は None を返す。"""
|
|
134
|
+
try:
|
|
135
|
+
start_dt = datetime.fromisoformat(start_ts)
|
|
136
|
+
end_dt = datetime.fromisoformat(end_ts)
|
|
137
|
+
return round((end_dt - start_dt).total_seconds(), 3)
|
|
138
|
+
except (ValueError, TypeError):
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _append_log(record: dict) -> None:
|
|
143
|
+
"""record を JSONL 形式で LOG_FILE に追記する。
|
|
144
|
+
|
|
145
|
+
ensure_ascii=False で json.dumps した後、_U2028 / _U2029 を
|
|
146
|
+
\\u2028 / \\u2029 に明示置換する (sec-H-1)。json.dumps は
|
|
147
|
+
ensure_ascii=False 時にこれらをエスケープしないため、
|
|
148
|
+
JSONL の行区切りが壊れる恐れがある。
|
|
149
|
+
O_APPEND でファイルシステムレベルの追記アトミック性を確保する (sec-L-1)。
|
|
150
|
+
"""
|
|
151
|
+
os.makedirs(LOG_DIR, mode=0o700, exist_ok=True)
|
|
152
|
+
try:
|
|
153
|
+
line = json.dumps(record, ensure_ascii=False)
|
|
154
|
+
line = line.replace(_U2028, '\\u2028').replace(_U2029, '\\u2029')
|
|
155
|
+
fd = os.open(LOG_FILE, os.O_WRONLY | os.O_CREAT | os.O_APPEND, 0o600)
|
|
156
|
+
with os.fdopen(fd, 'w', encoding='utf-8') as f:
|
|
157
|
+
f.write(line + '\n')
|
|
158
|
+
except Exception as e:
|
|
159
|
+
print(f'[subagent_log] ログ追記に失敗しました: {e}', file=sys.stderr)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def main() -> int:
|
|
163
|
+
"""stdin から JSON を読み込み、サニタイズして LOG_FILE に追記する。
|
|
164
|
+
|
|
165
|
+
SubagentStop イベントの場合は同 session_id + agent_id の最古未消費 Start を
|
|
166
|
+
検索して duration_seconds / matched_start_ts を付加する。
|
|
167
|
+
stdin の IOError・JSON パースエラーを含む全例外を catch して 0 を返す。
|
|
168
|
+
"""
|
|
169
|
+
try:
|
|
170
|
+
raw = sys.stdin.read(_MAX_STDIN_BYTES + 1)
|
|
171
|
+
if len(raw) > _MAX_STDIN_BYTES:
|
|
172
|
+
print(
|
|
173
|
+
f'[subagent_log] stdin が上限 ({_MAX_STDIN_BYTES} bytes) を超えています。'
|
|
174
|
+
'record を書き込まずに終了します。',
|
|
175
|
+
file=sys.stderr,
|
|
176
|
+
)
|
|
177
|
+
return 0
|
|
178
|
+
payload = json.loads(raw)
|
|
179
|
+
except json.JSONDecodeError as e:
|
|
180
|
+
print(f'[subagent_log] stdin の JSON パースに失敗しました: {e}', file=sys.stderr)
|
|
181
|
+
return 0
|
|
182
|
+
except Exception as e:
|
|
183
|
+
print(f'[subagent_log] stdin の読み込みに失敗しました: {e}', file=sys.stderr)
|
|
184
|
+
return 0
|
|
185
|
+
|
|
186
|
+
event_name = payload.get('hook_event_name', '')
|
|
187
|
+
session_id = payload.get('session_id', '')
|
|
188
|
+
now_ts = _now_iso()
|
|
189
|
+
|
|
190
|
+
record = {
|
|
191
|
+
'ts': now_ts,
|
|
192
|
+
'payload': _sanitize_payload(payload),
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if event_name == _EVENT_STOP:
|
|
196
|
+
agent_id = payload.get('agent_id', '')
|
|
197
|
+
if agent_id:
|
|
198
|
+
records = _read_log_records()
|
|
199
|
+
start = _find_unmatched_start(records, session_id, agent_id)
|
|
200
|
+
if start is not None:
|
|
201
|
+
duration = _calc_duration_seconds(start.get('ts', ''), now_ts)
|
|
202
|
+
if duration is not None:
|
|
203
|
+
record['duration_seconds'] = duration
|
|
204
|
+
record['matched_start_ts'] = start.get('ts')
|
|
205
|
+
|
|
206
|
+
_append_log(record)
|
|
207
|
+
|
|
208
|
+
return 0
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
if __name__ == '__main__':
|
|
212
|
+
sys.exit(main())
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"Edit(.claude/reports/**)",
|
|
26
26
|
"Edit(.claude/memory/sessions/**)",
|
|
27
27
|
"Edit(.claude/memory/**)",
|
|
28
|
+
"Edit(.claude/agent-memory/**)",
|
|
28
29
|
"Edit(.claude/rules/**)",
|
|
29
30
|
"Edit(.claude/rules/promoted/**)",
|
|
30
31
|
"Edit(.claude/skills/**)",
|
|
@@ -34,6 +35,7 @@
|
|
|
34
35
|
"Write(.claude/tmp/**)",
|
|
35
36
|
"Write(.claude/memory/**)",
|
|
36
37
|
"Write(.claude/memory/sessions/**)",
|
|
38
|
+
"Write(.claude/agent-memory/**)",
|
|
37
39
|
"Write(.claude/rules/**)",
|
|
38
40
|
"Write(.claude/rules/promoted/**)",
|
|
39
41
|
"Write(.claude/skills/**)",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"permissions": {
|
|
3
3
|
"allow": [
|
|
4
|
+
"Bash(python .claude/hooks/permission_handler.py*)",
|
|
4
5
|
"Bash(python .claude/hooks/clear_file_history.py*)",
|
|
5
6
|
"Bash(python .claude/hooks/enable_sandbox.py*)",
|
|
6
7
|
"Bash(python .claude/hooks/stop.py*)",
|
|
@@ -8,6 +9,7 @@
|
|
|
8
9
|
"Bash(python .claude/hooks/pre_compact.py*)",
|
|
9
10
|
"Bash(python .claude/hooks/validate_skill_change.py*)",
|
|
10
11
|
"Bash(python .claude/hooks/statusline.py*)",
|
|
12
|
+
"Bash(python .claude/hooks/subagent_log.py*)",
|
|
11
13
|
"Bash(python *)",
|
|
12
14
|
"Bash(pytest *)",
|
|
13
15
|
"Bash(xargs wc *)",
|
|
@@ -31,7 +33,37 @@
|
|
|
31
33
|
"Bash(git check-ignore *)",
|
|
32
34
|
"Bash(git stash *)",
|
|
33
35
|
"Bash(mkdir -p .claude/reports/archive)",
|
|
34
|
-
"Bash(mv .claude/reports/*.md .claude/reports/archive/)"
|
|
36
|
+
"Bash(mv .claude/reports/*.md .claude/reports/archive/)",
|
|
37
|
+
"Bash(pip list *)",
|
|
38
|
+
"Bash(New-Item -ItemType Directory -Force -Path \"C:\\\\Users\\\\shoma\\\\github_project\\\\claude-code-conductor\\\\.claude\\\\reports\")",
|
|
39
|
+
"Bash(Out-Null)",
|
|
40
|
+
"Bash(Write-Output \"OK\")",
|
|
41
|
+
"Bash(python3 *)",
|
|
42
|
+
"Bash(gh release *)"
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
"hooks": {
|
|
46
|
+
"SubagentStart": [
|
|
47
|
+
{
|
|
48
|
+
"matcher": "",
|
|
49
|
+
"hooks": [
|
|
50
|
+
{
|
|
51
|
+
"type": "command",
|
|
52
|
+
"command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/subagent_log.py\""
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"SubagentStop": [
|
|
58
|
+
{
|
|
59
|
+
"matcher": "",
|
|
60
|
+
"hooks": [
|
|
61
|
+
{
|
|
62
|
+
"type": "command",
|
|
63
|
+
"command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/subagent_log.py\""
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
|
35
67
|
]
|
|
36
68
|
}
|
|
37
69
|
}
|
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.7.1] - 2026-05-08
|
|
4
|
+
|
|
5
|
+
### 追加(開発者向け)
|
|
6
|
+
|
|
7
|
+
- `agents/`: developer / tester / code-reviewer / security-reviewer / systematic-debugger の 5 サブエージェントに `memory: project` フロントマターを付与。`.claude/agent-memory/<エージェント名>/MEMORY.md` が起動時にシステムプロンプトへ自動注入され、セッションをまたいだ知見蓄積が可能になった。配布版(`_template/`)には `agent-memory/` を含めず、利用側はゼロから蓄積する方針。
|
|
8
|
+
- `hooks/subagent_log.py`(C3 開発版専用): SubagentStart / SubagentStop イベントの payload を `.claude/logs/agent-runs.jsonl` に追記する hook を追加。`payload.agent_id` ベースで Start / Stop をペアリングし `duration_seconds` を計算。配布版(`_template/`)からは `EXCLUDE_PATTERNS` で除外。
|
|
9
|
+
|
|
10
|
+
### 修正(`subagent_log.py` 堅牢化)
|
|
11
|
+
|
|
12
|
+
- U+2028 / U+2029 を JSON ASCII エスケープして JSONL 構造破壊を防止。
|
|
13
|
+
- payload をホワイトリスト方式でサニタイズし、`last_assistant_message` 等の長文・任意コンテンツが永続化されないように変更。
|
|
14
|
+
- `stdin` を 1 MB 上限・ログ走査を末尾 10,000 行に制限してメモリ DoS を防止。
|
|
15
|
+
- ファイル作成パーミッションを `0o700` / `0o600` に明示設定(POSIX)。
|
|
16
|
+
- `stdin` / `json.loads` 失敗時の `Exception` catch と record 非書き込みでフェイルセーフ化。
|
|
17
|
+
- `_append_log` の catch を `OSError` から `Exception` に拡大(`json.dumps` の `TypeError` 等も対応)。
|
|
18
|
+
- `collections.deque` ベースのペアリングで `popleft()` を `O(1)` 化、走査コストを削減。
|
|
19
|
+
|
|
20
|
+
### 内部(テスト・ドキュメント整備)
|
|
21
|
+
|
|
22
|
+
- `tests/hooks/test_subagent_log.py` を 6 → 19 ケースに拡張(U+2028 エスケープ・残留 Start・Stop 先着・サニタイズ・巨大 payload・`TypeError` 耐性・`main()` 戻り値検証など)。
|
|
23
|
+
- `tests/hooks/test_restore_session.py` を新規追加(13 ケース、`find_latest_session` / `extract_section` / `main` subprocess)。
|
|
24
|
+
- `tests/hooks/test_permission_handler.py` を新規追加(29 ケース、`load_rules` / `_glob_to_regex` / `matches_pattern` / `describe_tool` / `main` subprocess / `notify_on_auto`)。
|
|
25
|
+
- `.claude/docs/taxonomy.md`: `.claude/rules/` フロントマターの `description` キー記述を削除(公式仕様に存在しないため)。
|
|
26
|
+
- `.claude/CLAUDE.md`: コミットメッセージ・チェンジログ・リリースページの日本語記述ルールを追記。
|
|
27
|
+
- `.claude/settings.local.json`: SubagentStart / SubagentStop hook 登録と開発作業用 Bash 許可を追加。
|
|
28
|
+
|
|
3
29
|
## [0.6.4] - 2026-05-07
|
|
4
30
|
|
|
5
31
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-code-conductor
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Multi-agent orchestration framework for Claude Code (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
|
|
@@ -25,10 +25,12 @@ EXCLUDE_PATTERNS: tuple[str, ...] = (
|
|
|
25
25
|
"memory/sessions/*",
|
|
26
26
|
"memory/patterns.json",
|
|
27
27
|
"memory/agent-audit.log",
|
|
28
|
+
"agent-memory/*",
|
|
28
29
|
"tmp/*",
|
|
29
30
|
"docs/decisions.md",
|
|
30
31
|
"docs/taxonomy.md",
|
|
31
32
|
"docs/game-studios-research.md",
|
|
33
|
+
"hooks/subagent_log.py",
|
|
32
34
|
"settings.local.json",
|
|
33
35
|
"pytest_temp.ini",
|
|
34
36
|
"logs/*",
|
|
@@ -22,10 +22,12 @@ EXCLUDE_PATTERNS: tuple[str, ...] = (
|
|
|
22
22
|
"memory/sessions/*",
|
|
23
23
|
"memory/patterns.json",
|
|
24
24
|
"memory/agent-audit.log",
|
|
25
|
+
"agent-memory/*",
|
|
25
26
|
"tmp/*",
|
|
26
27
|
"docs/decisions.md",
|
|
27
28
|
"docs/taxonomy.md",
|
|
28
29
|
"docs/game-studios-research.md",
|
|
30
|
+
"hooks/subagent_log.py",
|
|
29
31
|
"settings.local.json",
|
|
30
32
|
"pytest_temp.ini",
|
|
31
33
|
"logs/*",
|