claude-code-conductor 0.3.4__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/agents/tdd-develop.md +6 -6
- claude_code_conductor-0.4.0/.claude/hooks/pre_compact.py +59 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/hooks/pre_tool.py +0 -15
- claude_code_conductor-0.4.0/.claude/hooks/session_utils.py +42 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/hooks/stop.py +39 -36
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/settings.json +25 -21
- claude_code_conductor-0.4.0/.claude/settings.local.json +33 -0
- claude_code_conductor-0.4.0/.claude/skills/code-review/SKILL.md +14 -0
- claude_code_conductor-0.3.4/.claude/skills/dev-workflow.md → claude_code_conductor-0.4.0/.claude/skills/dev-workflow/SKILL.md +8 -2
- claude_code_conductor-0.4.0/.claude/skills/develop/SKILL.md +16 -0
- claude_code_conductor-0.3.4/.claude/commands/doc.md → claude_code_conductor-0.4.0/.claude/skills/doc/SKILL.md +6 -1
- claude_code_conductor-0.3.4/.claude/commands/extract-lib.md → claude_code_conductor-0.4.0/.claude/skills/extract-lib/SKILL.md +7 -2
- claude_code_conductor-0.3.4/.claude/commands/init-session.md → claude_code_conductor-0.4.0/.claude/skills/init-session/SKILL.md +6 -1
- claude_code_conductor-0.3.4/.claude/commands/mcp.md → claude_code_conductor-0.4.0/.claude/skills/mcp-config/SKILL.md +6 -1
- claude_code_conductor-0.3.4/.claude/commands/promote-pattern.md → claude_code_conductor-0.4.0/.claude/skills/promote-pattern/SKILL.md +25 -14
- claude_code_conductor-0.3.4/.claude/commands/setup.md → claude_code_conductor-0.4.0/.claude/skills/setup/SKILL.md +6 -1
- claude_code_conductor-0.3.4/.claude/commands/start.md → claude_code_conductor-0.4.0/.claude/skills/start/SKILL.md +8 -3
- claude_code_conductor-0.3.4/.claude/skills/wave-execution.md → claude_code_conductor-0.4.0/.claude/skills/wave-execution/SKILL.md +10 -4
- claude_code_conductor-0.3.4/.claude/skills/worktree-tdd-workflow.md → claude_code_conductor-0.4.0/.claude/skills/worktree-tdd-workflow/SKILL.md +6 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/CHANGELOG.md +45 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/PKG-INFO +1 -1
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/src/c3/__init__.py +1 -1
- claude_code_conductor-0.3.4/.claude/commands/develop.md +0 -11
- claude_code_conductor-0.3.4/.claude/commands/review.md +0 -9
- claude_code_conductor-0.3.4/.claude/hooks/pre_compact.py +0 -86
- claude_code_conductor-0.3.4/.claude/settings.local.json +0 -128
- claude_code_conductor-0.3.4/.claude/skills/promoted/index.md +0 -5
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/CLAUDE.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/agents/architect.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/agents/code-reviewer.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/agents/developer.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/agents/doc-writer.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/agents/interviewer.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/agents/planner.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/agents/project-setup.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/agents/security-reviewer.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/agents/tester.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/docs/parallel-orchestra-manifest.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/hooks/clear_file_history.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/hooks/enable_sandbox.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/hooks/statusline.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/hooks/validate_skill_change.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/hooks/worktree_guard.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/memory/.gitkeep +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/pytest_temp.ini +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/rules/code-review-checklist.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/rules/promoted/index.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/rules/security-review-checklist.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.gitignore +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/LICENSE +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/README.md +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/hatch_build.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/pyproject.toml +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/src/c3/__main__.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/src/c3/_excludes.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/src/c3/cli.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/src/c3/cli_doctor.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/src/c3/cli_init.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/src/c3/cli_list.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/src/c3/cli_po.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/src/c3/cli_update.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/src/c3/paths.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/src/c3/po/__init__.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/src/c3/po/detect.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/src/c3/po/manifest.py +0 -0
- {claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/src/c3/po/run.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tdd-develop
|
|
3
3
|
model: sonnet
|
|
4
|
-
description: ヘッドレス専用 TDD コンダクター。**必ず最初に `.claude/skills/worktree-tdd-workflow.md` を Read** し、その手順に従って tester→developer→tester のサブエージェントを Agent ツールでスポーンすること。インライン実装は絶対禁止。AskUserQuestion を使わない。
|
|
4
|
+
description: ヘッドレス専用 TDD コンダクター。**必ず最初に `.claude/skills/worktree-tdd-workflow/SKILL.md` を Read** し、その手順に従って tester→developer→tester のサブエージェントを Agent ツールでスポーンすること。インライン実装は絶対禁止。AskUserQuestion を使わない。
|
|
5
5
|
tools:
|
|
6
6
|
- Read
|
|
7
7
|
- Write
|
|
@@ -19,7 +19,7 @@ tools:
|
|
|
19
19
|
|
|
20
20
|
**いかなるタスクであっても、最初に必ず以下を実行すること:**
|
|
21
21
|
|
|
22
|
-
1. `Read` ツールで `.claude/skills/worktree-tdd-workflow.md` を読み込む
|
|
22
|
+
1. `Read` ツールで `.claude/skills/worktree-tdd-workflow/SKILL.md` を読み込む
|
|
23
23
|
2. 読み込んだワークフローに従って tester → developer → tester の順で **必ず Agent ツールでサブエージェントをスポーン**する
|
|
24
24
|
3. **絶対にインラインで pytest や Edit を直接実行して実装してはならない**
|
|
25
25
|
4. 「自分で実装した方が早い」と感じても、必ず Agent 経由で tester/developer に委譲すること
|
|
@@ -31,13 +31,13 @@ tools:
|
|
|
31
31
|
## Core Mandate
|
|
32
32
|
|
|
33
33
|
ヘッドレス環境で TDD サイクルを自律実行するコンダクター。
|
|
34
|
-
`.claude/skills/worktree-tdd-workflow.md` を読み込み、上限付きループで実行する。
|
|
34
|
+
`.claude/skills/worktree-tdd-workflow/SKILL.md` を読み込み、上限付きループで実行する。
|
|
35
35
|
全テスト合格またはループ上限到達で終了する。
|
|
36
36
|
|
|
37
37
|
## Key Scope
|
|
38
38
|
|
|
39
39
|
✅ 担当すること:
|
|
40
|
-
- `.claude/skills/worktree-tdd-workflow.md` の手順に従った TDD サイクルの実行
|
|
40
|
+
- `.claude/skills/worktree-tdd-workflow/SKILL.md` の手順に従った TDD サイクルの実行
|
|
41
41
|
- ループカウンターの管理と終了判定
|
|
42
42
|
- tester / developer へのコンテキスト(plan-report・test-report のパス)の受け渡し
|
|
43
43
|
- 最終結果の出力
|
|
@@ -58,14 +58,14 @@ tools:
|
|
|
58
58
|
|
|
59
59
|
### Step 0: 初期化
|
|
60
60
|
|
|
61
|
-
1. `.claude/skills/worktree-tdd-workflow.md` を Read してサイクル手順を把握する
|
|
61
|
+
1. `.claude/skills/worktree-tdd-workflow/SKILL.md` を Read してサイクル手順を把握する
|
|
62
62
|
2. Glob で `.claude/reports/plan-report-*.md` の最新ファイルの存在を確認する
|
|
63
63
|
- 存在しない場合: 「plan-report が見つかりません。Parallel Orchestra のマニフェストに plan-report のパスを含めるか、事前に計画フェーズを完了してください」と出力して終了する
|
|
64
64
|
3. ループカウンターを `0` に初期化する
|
|
65
65
|
|
|
66
66
|
### Step 1: TDD サイクル実行
|
|
67
67
|
|
|
68
|
-
`.claude/skills/worktree-tdd-workflow.md` の Step 1〜4 を実行する。
|
|
68
|
+
`.claude/skills/worktree-tdd-workflow/SKILL.md` の Step 1〜4 を実行する。
|
|
69
69
|
|
|
70
70
|
### Step 2: 結果判定
|
|
71
71
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""PreCompact hook: append checkpoint marker to today's session file."""
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
from datetime import datetime, timezone
|
|
8
|
+
|
|
9
|
+
sys.stdout.reconfigure(encoding='utf-8')
|
|
10
|
+
sys.stderr.reconfigure(encoding='utf-8')
|
|
11
|
+
|
|
12
|
+
_HOOKS_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
13
|
+
_CLAUDE_DIR = os.path.dirname(_HOOKS_DIR)
|
|
14
|
+
SESSIONS_DIR = os.path.join(_CLAUDE_DIR, 'memory', 'sessions')
|
|
15
|
+
|
|
16
|
+
from session_utils import is_worktree, create_session_template
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def main():
|
|
20
|
+
try:
|
|
21
|
+
payload = json.loads(sys.stdin.read())
|
|
22
|
+
except (json.JSONDecodeError, ValueError):
|
|
23
|
+
payload = {}
|
|
24
|
+
|
|
25
|
+
cwd = os.getcwd()
|
|
26
|
+
if is_worktree(cwd):
|
|
27
|
+
sys.exit(0)
|
|
28
|
+
|
|
29
|
+
trigger = payload.get('trigger', 'unknown')
|
|
30
|
+
context_items_before = payload.get('context_items_before', 0)
|
|
31
|
+
|
|
32
|
+
os.makedirs(SESSIONS_DIR, exist_ok=True)
|
|
33
|
+
|
|
34
|
+
now = datetime.now(timezone.utc)
|
|
35
|
+
date_str = now.strftime('%Y%m%d')
|
|
36
|
+
session_file = os.path.join(SESSIONS_DIR, f'{date_str}.tmp')
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
with open(session_file, 'x', encoding='utf-8') as f:
|
|
40
|
+
f.write(create_session_template(date_str))
|
|
41
|
+
except FileExistsError:
|
|
42
|
+
pass # already created by stop.py or another process
|
|
43
|
+
|
|
44
|
+
ts = now.isoformat()
|
|
45
|
+
checkpoint = (
|
|
46
|
+
f'\n'
|
|
47
|
+
f'## [PreCompact checkpoint: {trigger} - {ts}]\n'
|
|
48
|
+
f'コンテキスト圧縮 ({trigger}) が発生しました。圧縮前: {context_items_before} アイテム。\n'
|
|
49
|
+
f'このポイント以前の詳細な文脈は失われています。\n'
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
with open(session_file, 'a', encoding='utf-8') as f:
|
|
53
|
+
f.write(checkpoint)
|
|
54
|
+
|
|
55
|
+
print(f'[PreCompact] セッション状態を {session_file} に保存しました', file=sys.stderr)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
if __name__ == '__main__':
|
|
59
|
+
main()
|
|
@@ -32,21 +32,6 @@ def main():
|
|
|
32
32
|
print('[PreToolUse WARNING] 破壊的な DB 操作を検出しました。本番環境での実行でないことを確認してください。',
|
|
33
33
|
file=sys.stderr)
|
|
34
34
|
|
|
35
|
-
# cd コマンド: CWD 固定バグを防ぐためブロック
|
|
36
|
-
# Bash ツールで cd を実行すると以降の全コマンドの CWD が変わり、
|
|
37
|
-
# フックが相対パスで .claude/hooks/ を参照できなくなる。
|
|
38
|
-
# サブシェル $( )・バックティック・eval・改行セパレータ経由のバイパスも検出する。
|
|
39
|
-
if re.search(r'(?:^|[;&|\n`]|\$\()\s*cd(?:\s|$)', cmd) or \
|
|
40
|
-
re.search(r'\beval\b.*\bcd\b', cmd):
|
|
41
|
-
print(
|
|
42
|
-
'[PreToolUse BLOCK] cd コマンドをブロックしました。\n'
|
|
43
|
-
'Bash ツールで cd を実行すると CWD が変わり、以降のフックが失敗します。\n'
|
|
44
|
-
'cd を使わず、プロジェクトルートからの相対パスで実行してください。\n'
|
|
45
|
-
'例: python -m pytest test1/tests -v (cd test1 && python -m pytest の代わり)',
|
|
46
|
-
file=sys.stderr
|
|
47
|
-
)
|
|
48
|
-
sys.exit(2)
|
|
49
|
-
|
|
50
35
|
# rm -rf 系: ブロック
|
|
51
36
|
# rm の直後のフラグのみを収集することで、前のコマンドのフラグを誤検出しない
|
|
52
37
|
if re.search(r'\brm\b', cmd):
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Shared utilities for session management hooks (stop.py, pre_compact.py)."""
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
_HOOKS_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
7
|
+
_CLAUDE_DIR = os.path.dirname(_HOOKS_DIR)
|
|
8
|
+
SESSIONS_DIR = os.path.join(_CLAUDE_DIR, 'memory', 'sessions')
|
|
9
|
+
|
|
10
|
+
SESSION_JSON_MARKER = 'C3:SESSION:JSON'
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def is_worktree(cwd: str) -> bool:
|
|
14
|
+
git_path = os.path.join(cwd, '.git')
|
|
15
|
+
return os.path.exists(git_path) and os.path.isfile(git_path)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def create_session_template(date_str: str) -> str:
|
|
19
|
+
return (
|
|
20
|
+
f"SESSION: {date_str}\n"
|
|
21
|
+
f"AGENT: \n"
|
|
22
|
+
f"DURATION: \n"
|
|
23
|
+
f"\n"
|
|
24
|
+
f"## うまくいったアプローチ\n"
|
|
25
|
+
f"\n"
|
|
26
|
+
f"## 試みたが失敗したアプローチ\n"
|
|
27
|
+
f"\n"
|
|
28
|
+
f"## 残タスク\n"
|
|
29
|
+
f"\n"
|
|
30
|
+
f"## 事実ログ(自動生成 / stop.py)\n"
|
|
31
|
+
f"- 記録時刻: \n"
|
|
32
|
+
f"\n"
|
|
33
|
+
f"<!-- {SESSION_JSON_MARKER}\n"
|
|
34
|
+
f"{{\n"
|
|
35
|
+
f' "session": "{date_str}",\n'
|
|
36
|
+
f' "patterns": [],\n'
|
|
37
|
+
f' "successes": [],\n'
|
|
38
|
+
f' "failures": [],\n'
|
|
39
|
+
f' "todos": []\n'
|
|
40
|
+
f"}}\n"
|
|
41
|
+
f"-->\n"
|
|
42
|
+
)
|
|
@@ -15,53 +15,22 @@ sys.stderr.reconfigure(encoding='utf-8')
|
|
|
15
15
|
|
|
16
16
|
_HOOKS_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
17
17
|
_CLAUDE_DIR = os.path.dirname(_HOOKS_DIR)
|
|
18
|
-
SESSIONS_DIR = os.path.join(_CLAUDE_DIR, 'memory', 'sessions')
|
|
19
18
|
PATTERNS_FILE = os.path.join(_CLAUDE_DIR, 'memory', 'patterns.json')
|
|
20
19
|
|
|
20
|
+
from session_utils import SESSION_JSON_MARKER, is_worktree, create_session_template, SESSIONS_DIR
|
|
21
|
+
|
|
21
22
|
EXPIRY_DAYS = 30
|
|
22
23
|
PROMOTION_THRESHOLD = 0.8
|
|
23
24
|
COOLING_DAYS = 3
|
|
24
|
-
SESSION_JSON_MARKER = 'C3:SESSION:JSON'
|
|
25
25
|
MAX_ID_LENGTH = 64
|
|
26
26
|
MAX_DESCRIPTION_LENGTH = 500
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def is_worktree(cwd: str) -> bool:
|
|
30
|
-
git_path = os.path.join(cwd, '.git')
|
|
31
|
-
return os.path.exists(git_path) and os.path.isfile(git_path)
|
|
27
|
+
MAX_LAST_MSG = 500
|
|
32
28
|
|
|
33
29
|
|
|
34
30
|
def get_session_path(date_str: str) -> str:
|
|
35
31
|
return os.path.join(SESSIONS_DIR, f'{date_str}.tmp')
|
|
36
32
|
|
|
37
33
|
|
|
38
|
-
def create_session_template(date_str: str) -> str:
|
|
39
|
-
return (
|
|
40
|
-
f"SESSION: {date_str}\n"
|
|
41
|
-
f"AGENT: \n"
|
|
42
|
-
f"DURATION: \n"
|
|
43
|
-
f"\n"
|
|
44
|
-
f"## うまくいったアプローチ\n"
|
|
45
|
-
f"\n"
|
|
46
|
-
f"## 試みたが失敗したアプローチ\n"
|
|
47
|
-
f"\n"
|
|
48
|
-
f"## 残タスク\n"
|
|
49
|
-
f"\n"
|
|
50
|
-
f"## 事実ログ(自動生成 / stop.py)\n"
|
|
51
|
-
f"- 記録時刻: \n"
|
|
52
|
-
f"\n"
|
|
53
|
-
f"<!-- {SESSION_JSON_MARKER}\n"
|
|
54
|
-
f"{{\n"
|
|
55
|
-
f' "session": "{date_str}",\n'
|
|
56
|
-
f' "patterns": [],\n'
|
|
57
|
-
f' "successes": [],\n'
|
|
58
|
-
f' "failures": [],\n'
|
|
59
|
-
f' "todos": []\n'
|
|
60
|
-
f"}}\n"
|
|
61
|
-
f"-->\n"
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
|
|
65
34
|
def ensure_session_file(date_str: str) -> None:
|
|
66
35
|
os.makedirs(SESSIONS_DIR, exist_ok=True)
|
|
67
36
|
path = get_session_path(date_str)
|
|
@@ -74,6 +43,30 @@ def ensure_session_file(date_str: str) -> None:
|
|
|
74
43
|
_update_facts_timestamp(path)
|
|
75
44
|
|
|
76
45
|
|
|
46
|
+
def _append_last_message(path: str, message: str) -> None:
|
|
47
|
+
with open(path, 'r', encoding='utf-8') as f:
|
|
48
|
+
content = f.read()
|
|
49
|
+
|
|
50
|
+
if '- 最終応答:' in content:
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
single_line = ' '.join(message.split())
|
|
54
|
+
# サロゲート文字など UTF-8 非互換文字を除去(JSON デコード時に生成される場合がある)
|
|
55
|
+
single_line = single_line.encode('utf-8', errors='replace').decode('utf-8')
|
|
56
|
+
truncated = single_line[:MAX_LAST_MSG]
|
|
57
|
+
if len(single_line) > MAX_LAST_MSG:
|
|
58
|
+
truncated += '…(省略)'
|
|
59
|
+
|
|
60
|
+
updated = re.sub(
|
|
61
|
+
r'(- 記録時刻: [^\n]*)',
|
|
62
|
+
lambda m: m.group(0) + f'\n- 最終応答: {truncated}',
|
|
63
|
+
content
|
|
64
|
+
)
|
|
65
|
+
if updated != content:
|
|
66
|
+
with open(path, 'w', encoding='utf-8') as f:
|
|
67
|
+
f.write(updated)
|
|
68
|
+
|
|
69
|
+
|
|
77
70
|
def _update_facts_timestamp(path: str) -> None:
|
|
78
71
|
with open(path, 'r', encoding='utf-8') as f:
|
|
79
72
|
content = f.read()
|
|
@@ -209,9 +202,14 @@ def update_patterns(date_str: str) -> None:
|
|
|
209
202
|
|
|
210
203
|
def main():
|
|
211
204
|
try:
|
|
212
|
-
json.loads(sys.stdin.read())
|
|
205
|
+
payload = json.loads(sys.stdin.read())
|
|
213
206
|
except (json.JSONDecodeError, ValueError):
|
|
214
|
-
|
|
207
|
+
payload = {}
|
|
208
|
+
|
|
209
|
+
# stop_hook_active=true は Stop hook が decision:block を返した後の 2 回目呼び出し。
|
|
210
|
+
# セッション処理は初回のみ実行する。
|
|
211
|
+
if payload.get('stop_hook_active'):
|
|
212
|
+
sys.exit(0)
|
|
215
213
|
|
|
216
214
|
cwd = os.getcwd()
|
|
217
215
|
if is_worktree(cwd):
|
|
@@ -219,6 +217,11 @@ def main():
|
|
|
219
217
|
|
|
220
218
|
today_str = date.today().strftime('%Y%m%d')
|
|
221
219
|
ensure_session_file(today_str)
|
|
220
|
+
|
|
221
|
+
last_msg = payload.get('last_assistant_message', '').strip()
|
|
222
|
+
if last_msg:
|
|
223
|
+
_append_last_message(get_session_path(today_str), last_msg)
|
|
224
|
+
|
|
222
225
|
update_patterns(today_str)
|
|
223
226
|
|
|
224
227
|
|
|
@@ -8,17 +8,32 @@
|
|
|
8
8
|
"Bash(python .claude/hooks/pre_compact.py*)",
|
|
9
9
|
"Bash(python .claude/hooks/validate_skill_change.py*)",
|
|
10
10
|
"Bash(python .claude/hooks/statusline.py*)",
|
|
11
|
+
"Bash(python \"$CLAUDE_PROJECT_DIR/.claude/hooks/clear_file_history.py\"*)",
|
|
12
|
+
"Bash(python \"$CLAUDE_PROJECT_DIR/.claude/hooks/enable_sandbox.py\"*)",
|
|
13
|
+
"Bash(python \"$CLAUDE_PROJECT_DIR/.claude/hooks/stop.py\"*)",
|
|
14
|
+
"Bash(python \"$CLAUDE_PROJECT_DIR/.claude/hooks/pre_tool.py\"*)",
|
|
15
|
+
"Bash(python \"$CLAUDE_PROJECT_DIR/.claude/hooks/pre_compact.py\"*)",
|
|
16
|
+
"Bash(python \"$CLAUDE_PROJECT_DIR/.claude/hooks/validate_skill_change.py\"*)",
|
|
17
|
+
"Bash(python \"$CLAUDE_PROJECT_DIR/.claude/hooks/statusline.py\"*)",
|
|
11
18
|
"Read(**)",
|
|
12
19
|
"Glob(**)",
|
|
13
20
|
"Grep(**)",
|
|
14
21
|
"Edit(.claude/reports/**)",
|
|
22
|
+
"Edit(.claude/memory/sessions/**)",
|
|
23
|
+
"Edit(.claude/memory/**)",
|
|
24
|
+
"Edit(.claude/rules/**)",
|
|
25
|
+
"Edit(.claude/rules/promoted/**)",
|
|
26
|
+
"Edit(.claude/skills/**)",
|
|
27
|
+
"Edit(.claude/settings.json)",
|
|
15
28
|
"Write(.claude/reports/**)",
|
|
29
|
+
"Write(.claude/reports/archive/**)",
|
|
16
30
|
"Write(.claude/tmp/**)",
|
|
17
31
|
"Write(.claude/memory/**)",
|
|
18
|
-
"Edit(.claude/memory/sessions/**)",
|
|
19
32
|
"Write(.claude/memory/sessions/**)",
|
|
33
|
+
"Write(.claude/rules/**)",
|
|
20
34
|
"Write(.claude/rules/promoted/**)",
|
|
21
|
-
"Write(.claude/skills
|
|
35
|
+
"Write(.claude/skills/**)",
|
|
36
|
+
"Write(.claude/settings.json)",
|
|
22
37
|
"Bash(git status*)",
|
|
23
38
|
"Bash(git diff*)",
|
|
24
39
|
"Bash(git log*)",
|
|
@@ -47,7 +62,7 @@
|
|
|
47
62
|
},
|
|
48
63
|
"statusLine": {
|
|
49
64
|
"type": "command",
|
|
50
|
-
"command": "python
|
|
65
|
+
"command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/statusline.py\""
|
|
51
66
|
},
|
|
52
67
|
"hooks": {
|
|
53
68
|
"PreToolUse": [
|
|
@@ -56,7 +71,7 @@
|
|
|
56
71
|
"hooks": [
|
|
57
72
|
{
|
|
58
73
|
"type": "command",
|
|
59
|
-
"command": "python
|
|
74
|
+
"command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/pre_tool.py\""
|
|
60
75
|
}
|
|
61
76
|
]
|
|
62
77
|
},
|
|
@@ -65,7 +80,7 @@
|
|
|
65
80
|
"hooks": [
|
|
66
81
|
{
|
|
67
82
|
"type": "command",
|
|
68
|
-
"command": "python
|
|
83
|
+
"command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/worktree_guard.py\""
|
|
69
84
|
}
|
|
70
85
|
]
|
|
71
86
|
},
|
|
@@ -74,7 +89,7 @@
|
|
|
74
89
|
"hooks": [
|
|
75
90
|
{
|
|
76
91
|
"type": "command",
|
|
77
|
-
"command": "python
|
|
92
|
+
"command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/worktree_guard.py\""
|
|
78
93
|
}
|
|
79
94
|
]
|
|
80
95
|
}
|
|
@@ -85,7 +100,7 @@
|
|
|
85
100
|
"hooks": [
|
|
86
101
|
{
|
|
87
102
|
"type": "command",
|
|
88
|
-
"command": "python
|
|
103
|
+
"command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/validate_skill_change.py\""
|
|
89
104
|
}
|
|
90
105
|
]
|
|
91
106
|
},
|
|
@@ -94,7 +109,7 @@
|
|
|
94
109
|
"hooks": [
|
|
95
110
|
{
|
|
96
111
|
"type": "command",
|
|
97
|
-
"command": "python
|
|
112
|
+
"command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/validate_skill_change.py\""
|
|
98
113
|
}
|
|
99
114
|
]
|
|
100
115
|
}
|
|
@@ -105,7 +120,7 @@
|
|
|
105
120
|
"hooks": [
|
|
106
121
|
{
|
|
107
122
|
"type": "command",
|
|
108
|
-
"command": "python
|
|
123
|
+
"command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/pre_compact.py\""
|
|
109
124
|
}
|
|
110
125
|
]
|
|
111
126
|
}
|
|
@@ -116,18 +131,7 @@
|
|
|
116
131
|
"hooks": [
|
|
117
132
|
{
|
|
118
133
|
"type": "command",
|
|
119
|
-
"command": "python
|
|
120
|
-
}
|
|
121
|
-
]
|
|
122
|
-
}
|
|
123
|
-
],
|
|
124
|
-
"UserPromptSubmit": [
|
|
125
|
-
{
|
|
126
|
-
"matcher": "",
|
|
127
|
-
"hooks": [
|
|
128
|
-
{
|
|
129
|
-
"type": "command",
|
|
130
|
-
"command": "python .claude/hooks/statusline.py"
|
|
134
|
+
"command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/stop.py\""
|
|
131
135
|
}
|
|
132
136
|
]
|
|
133
137
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(python .claude/hooks/clear_file_history.py*)",
|
|
5
|
+
"Bash(python .claude/hooks/enable_sandbox.py*)",
|
|
6
|
+
"Bash(python .claude/hooks/stop.py*)",
|
|
7
|
+
"Bash(python .claude/hooks/pre_tool.py*)",
|
|
8
|
+
"Bash(python .claude/hooks/pre_compact.py*)",
|
|
9
|
+
"Bash(python .claude/hooks/validate_skill_change.py*)",
|
|
10
|
+
"Bash(python .claude/hooks/statusline.py*)",
|
|
11
|
+
"Bash(python *)",
|
|
12
|
+
"Bash(pytest *)",
|
|
13
|
+
"Bash(xargs wc *)",
|
|
14
|
+
"Bash(git add*)",
|
|
15
|
+
"Bash(git commit*)",
|
|
16
|
+
"Bash(git status*)",
|
|
17
|
+
"Bash(git diff*)",
|
|
18
|
+
"Bash(git log*)",
|
|
19
|
+
"Bash(mkdir*)",
|
|
20
|
+
"Edit(**)",
|
|
21
|
+
"Glob(**)",
|
|
22
|
+
"Grep(**)",
|
|
23
|
+
"Read(**)",
|
|
24
|
+
"Write(**)",
|
|
25
|
+
"WebFetch(domain:github.com)",
|
|
26
|
+
"WebFetch(domain:pypi.org)",
|
|
27
|
+
"Bash(grep \"\\\\.py$\")",
|
|
28
|
+
"WebFetch(domain:raw.githubusercontent.com)",
|
|
29
|
+
"Bash(pip-audit)",
|
|
30
|
+
"Bash(c3 po *)"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 実装済みコードの code-reviewer・security-reviewer によるレビュー(フェーズ E)を実行する。
|
|
3
|
+
disable-model-invocation: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# code-review
|
|
7
|
+
|
|
8
|
+
実装済みコードのレビューを行う。
|
|
9
|
+
|
|
10
|
+
## 必ず守ること
|
|
11
|
+
|
|
12
|
+
1. **最初に必ず** `.claude/skills/dev-workflow/SKILL.md` を Read する。記憶・推測で進めない
|
|
13
|
+
2. **フェーズ E(レビュー)** から実行する
|
|
14
|
+
3. dev-workflow/SKILL.md の AskUserQuestion・Edit・セッションファイル更新の手順を省略しない
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: ヒアリング→設計→計画→実装→レビューの全フェーズワークフロー。/start・/develop・/code-review コマンドが内部参照する。
|
|
3
|
+
disable-model-invocation: false
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
1
7
|
# Dev Workflow
|
|
2
8
|
|
|
3
9
|
要件定義から実装・レビューまでを複数エージェントで連携させるフルワークフロー。
|
|
@@ -227,8 +233,8 @@ AskUserQuestion ツール:
|
|
|
227
233
|
plan-report の冒頭を Read し、YAML フロントマター(`---` で始まり `po_plan_version: "0.1"` を含む)の有無を確認する。
|
|
228
234
|
|
|
229
235
|
**フロントマターありの場合:**
|
|
230
|
-
1. **最初に必ず** `.claude/skills/wave-execution.md` を Read する(記憶・推測で進めない)
|
|
231
|
-
2. `wave-execution.md` の手順に完全に従って wave 単位で実装を進める
|
|
236
|
+
1. **最初に必ず** `.claude/skills/wave-execution/SKILL.md` を Read する(記憶・推測で進めない)
|
|
237
|
+
2. `wave-execution/SKILL.md` の手順に完全に従って wave 単位で実装を進める
|
|
232
238
|
3. 全 wave 完了後はフェーズ E(レビュー)へ進む(wave に reviewer タスクが含まれていれば E をスキップ可能と案内する)
|
|
233
239
|
|
|
234
240
|
**フロントマターなしの場合(legacy フォールバック):**
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: plan-report に基づいて実装フェーズ(フェーズ D)を実行する。po_plan_version があれば PO 並列モード、なければ逐次 TDD を実行する。
|
|
3
|
+
disable-model-invocation: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# develop
|
|
7
|
+
|
|
8
|
+
plan-report に基づいて実装フェーズを実行する。
|
|
9
|
+
|
|
10
|
+
## 必ず守ること
|
|
11
|
+
|
|
12
|
+
1. **最初に必ず** `.claude/skills/dev-workflow/SKILL.md` を Read する。記憶・推測で進めない
|
|
13
|
+
2. **フェーズ D(実装)** から実行する
|
|
14
|
+
3. dev-workflow/SKILL.md の AskUserQuestion・Edit・セッションファイル更新の手順を省略しない
|
|
15
|
+
4. D-0 で plan-report に YAML フロントマター(`po_plan_version`)が検出された場合は、続けて **必ず** `.claude/skills/wave-execution/SKILL.md` を Read してその手順に従う(C3 メイン + PO スポット並列モード)
|
|
16
|
+
5. フロントマターが無い場合は legacy の D-1〜D-5 ceremony(tester→developer→tester の TDD 逐次実行)にフォールバックする
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
description: 複数プロジェクトから共通コードを解析・抽出してライブラリ設計案とスケルトンコードを生成する。
|
|
3
|
+
disable-model-invocation: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# extract-lib
|
|
2
7
|
|
|
3
8
|
複数プロジェクトのコードを横断解析し、共通要素を抽出してライブラリ設計・スケルトン生成を行う。
|
|
4
9
|
|
|
@@ -288,5 +293,5 @@ Agent ツールでスケルトンコード生成を行う:
|
|
|
288
293
|
次のステップ:
|
|
289
294
|
1. レポートの設計案を確認し、必要に応じて調整する
|
|
290
295
|
2. 各プロジェクトの該当箇所をライブラリに置き換える
|
|
291
|
-
3. /review でライブラリのコードレビューを実施する
|
|
296
|
+
3. /code-review でライブラリのコードレビューを実施する
|
|
292
297
|
```
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
description: patterns.json の昇格候補を rules/promoted/ または skills/promoted-YYYYMMDD-{id}/ に昇格させる。信用度が高いパターンをルール・スキルとして永続化する。
|
|
3
|
+
disable-model-invocation: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# promote-pattern
|
|
2
7
|
|
|
3
|
-
`patterns.json` の昇格候補を `rules/promoted/` または `skills/promoted/` に昇格させる。
|
|
8
|
+
`patterns.json` の昇格候補を `rules/promoted/` または `skills/promoted-YYYYMMDD-{id}/` に昇格させる。
|
|
4
9
|
|
|
5
10
|
---
|
|
6
11
|
|
|
@@ -47,7 +52,7 @@ AskUserQuestion ツールで候補を複数選択式で提示する:
|
|
|
47
52
|
"question": "「{description}」をどちらに昇格しますか?",
|
|
48
53
|
"options": [
|
|
49
54
|
{ "label": "rule", "description": "rules/promoted/ — 背景知識・制約として登録(「こうしろ / これを知っておけ」系)" },
|
|
50
|
-
{ "label": "skill", "description": "skills/promoted/ —
|
|
55
|
+
{ "label": "skill", "description": "skills/promoted-YYYYMMDD-{id}/ — オーケストレーション手順として登録(「この順番で動かせ」系)。Claude が自動的に使用する" }
|
|
51
56
|
]
|
|
52
57
|
}]
|
|
53
58
|
}
|
|
@@ -75,10 +80,12 @@ trust_score: {スコア}
|
|
|
75
80
|
{ルール本文。「何をすべきか / 何を知っておくべきか」を簡潔に記述する}
|
|
76
81
|
```
|
|
77
82
|
|
|
78
|
-
**skill の保存先:** `.claude/skills/promoted
|
|
83
|
+
**skill の保存先:** `.claude/skills/promoted-YYYYMMDD-{id}/SKILL.md`
|
|
79
84
|
|
|
80
85
|
```markdown
|
|
81
86
|
---
|
|
87
|
+
name: promoted-YYYYMMDD-{id}
|
|
88
|
+
description: {昇格理由と期待効果を1文で。例: "wave 実行でのペルソナ採用パターン。tdd-develop を単独 wave で実行する際に自動適用される"}
|
|
82
89
|
promoted_from: {pattern id}
|
|
83
90
|
promoted_date: YYYY-MM-DD
|
|
84
91
|
trust_score: {スコア}
|
|
@@ -87,7 +94,7 @@ trust_score: {スコア}
|
|
|
87
94
|
# {タイトル}
|
|
88
95
|
|
|
89
96
|
## 使うタイミング
|
|
90
|
-
{どんな状況でこのスキルを使うか}
|
|
97
|
+
{どんな状況でこのスキルを使うか — description の詳細版}
|
|
91
98
|
|
|
92
99
|
## 手順
|
|
93
100
|
{エージェント間のオーケストレーション手順をステップで記述する}
|
|
@@ -97,15 +104,12 @@ trust_score: {スコア}
|
|
|
97
104
|
|
|
98
105
|
## Step 5: index.md に追記する
|
|
99
106
|
|
|
100
|
-
**rule
|
|
107
|
+
**rule の場合のみ** — `.claude/rules/promoted/index.md` の `<!-- C3:PROMOTED_RULES:BEGIN -->` と `<!-- C3:PROMOTED_RULES:END -->` の間に追記:
|
|
101
108
|
```
|
|
102
109
|
- **{タイトル}** (`.claude/rules/promoted/YYYYMMDD-{id}.md`) — {description を1行で}
|
|
103
110
|
```
|
|
104
111
|
|
|
105
|
-
**skill の場合** —
|
|
106
|
-
```
|
|
107
|
-
- **{タイトル}** (`.claude/skills/promoted/YYYYMMDD-{id}.md`) — {description を1行で}
|
|
108
|
-
```
|
|
112
|
+
**skill の場合** — index.md への追記は不要。Claude Code がスキルを自動検出する。
|
|
109
113
|
|
|
110
114
|
---
|
|
111
115
|
|
|
@@ -113,12 +117,20 @@ trust_score: {スコア}
|
|
|
113
117
|
|
|
114
118
|
昇格したパターンの entry に以下を追加する:
|
|
115
119
|
|
|
120
|
+
rule の場合:
|
|
116
121
|
```json
|
|
117
122
|
"promoted": true,
|
|
118
123
|
"promoted_date": "YYYYMMDD",
|
|
119
124
|
"promoted_to": ".claude/rules/promoted/YYYYMMDD-{id}.md"
|
|
120
125
|
```
|
|
121
126
|
|
|
127
|
+
skill の場合:
|
|
128
|
+
```json
|
|
129
|
+
"promoted": true,
|
|
130
|
+
"promoted_date": "YYYYMMDD",
|
|
131
|
+
"promoted_to": ".claude/skills/promoted-YYYYMMDD-{id}/SKILL.md"
|
|
132
|
+
```
|
|
133
|
+
|
|
122
134
|
複数昇格した場合は Step 4〜6 を全パターン分まとめて処理してから Step 7 へ進む。
|
|
123
135
|
|
|
124
136
|
---
|
|
@@ -127,9 +139,8 @@ trust_score: {スコア}
|
|
|
127
139
|
|
|
128
140
|
```
|
|
129
141
|
昇格完了({N}件):
|
|
130
|
-
✅ {description} → .claude/rules/promoted/YYYYMMDD-{id}.md
|
|
131
|
-
✅ {description} → .claude/skills/promoted
|
|
142
|
+
✅ {description} → .claude/rules/promoted/YYYYMMDD-{id}.md [trust: {スコア}]
|
|
143
|
+
✅ {description} → .claude/skills/promoted-YYYYMMDD-{id}/SKILL.md [trust: {スコア}]
|
|
132
144
|
|
|
133
|
-
|
|
134
|
-
次回セッションからこれらのルール・スキルが自動で読み込まれます。
|
|
145
|
+
スキルは Claude が関連する場面で自動的に使用します。
|
|
135
146
|
```
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
description: 技術スタックと独自規約をヒアリングして project-setup エージェントに coding-standards.md と project-conventions.md を生成させる。プロジェクト開始時に使用する。
|
|
3
|
+
disable-model-invocation: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# setup
|
|
2
7
|
|
|
3
8
|
プロジェクトのコーディング規約を設定する。
|
|
4
9
|
ヒアリングは親 Claude が担当し、収集後に project-setup エージェントを起動する。
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
description: 開発ワークフローの入口。既存レポートの整理後、ヒアリング・設計・計画・実装のどこから始めるかを選んで dev-workflow を実行する。
|
|
3
|
+
disable-model-invocation: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# start
|
|
2
7
|
|
|
3
8
|
開発ワークフローの入口。
|
|
4
9
|
|
|
@@ -76,9 +81,9 @@ AskUserQuestion ツールで以下を提示する:
|
|
|
76
81
|
|
|
77
82
|
---
|
|
78
83
|
|
|
79
|
-
## Step 2: dev-workflow.md を Read してフェーズを実行する
|
|
84
|
+
## Step 2: dev-workflow/SKILL.md を Read してフェーズを実行する
|
|
80
85
|
|
|
81
|
-
**最初に必ず** `.claude/skills/dev-workflow.md` を Read する。記憶・推測で進めず、dev-workflow.md の AskUserQuestion・Edit・セッションファイル更新の手順を省略しないこと。
|
|
86
|
+
**最初に必ず** `.claude/skills/dev-workflow/SKILL.md` を Read する。記憶・推測で進めず、dev-workflow/SKILL.md の AskUserQuestion・Edit・セッションファイル更新の手順を省略しないこと。
|
|
82
87
|
|
|
83
88
|
選択した開始地点に対応するフェーズから実行する:
|
|
84
89
|
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: PO(Parallel Orchestra)を用いた wave 単位の並列実装実行手順。dev-workflow がフェーズ D で条件付き参照する。
|
|
3
|
+
disable-model-invocation: true
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
1
7
|
# Wave Execution
|
|
2
8
|
|
|
3
9
|
`/develop` のフェーズ D で plan-report に YAML フロントマター(`po_plan_version: "0.1"`)が含まれるときに Read される手順。
|
|
@@ -13,7 +19,7 @@ C3 の親 Claude が plan-report の DAG を **wave 単位**で歩く。
|
|
|
13
19
|
## 前提条件
|
|
14
20
|
|
|
15
21
|
- `claude-code-conductor` がインストール済みで `c3` コマンドが PATH 上にあること
|
|
16
|
-
- plan-report が `.claude/reports/plan-report-*.md` の形式で配置され、YAML フロントマターを持つこと(フロントマターが無ければ `dev-workflow.md` の D-1〜D-5 ceremony へフォールバック)
|
|
22
|
+
- plan-report が `.claude/reports/plan-report-*.md` の形式で配置され、YAML フロントマターを持つこと(フロントマターが無ければ `dev-workflow/SKILL.md` の D-1〜D-5 ceremony へフォールバック)
|
|
17
23
|
|
|
18
24
|
---
|
|
19
25
|
|
|
@@ -69,7 +75,7 @@ PO は worktree からの auto-merge で main に成果物を取り込む仕様
|
|
|
69
75
|
> 並列実行を使うには `pip install parallel-orchestra` を実行してください。
|
|
70
76
|
> 詳細: https://pypi.org/project/parallel-orchestra/
|
|
71
77
|
|
|
72
|
-
親 Claude は逐次実行(`dev-workflow.md` の D-1〜D-5)に切り替えるか、PO をインストールして `/develop` を再実行するかをユーザーに選んでもらう。
|
|
78
|
+
親 Claude は逐次実行(`dev-workflow/SKILL.md` の D-1〜D-5)に切り替えるか、PO をインストールして `/develop` を再実行するかをユーザーに選んでもらう。
|
|
73
79
|
|
|
74
80
|
---
|
|
75
81
|
|
|
@@ -155,8 +161,8 @@ AskUserQuestion ツール:
|
|
|
155
161
|
**ペルソナ採用パターン**で実行する。Agent ツールで起動するとサブエージェント depth 1 制限により内部の tester/developer サブエージェントが spawn できないため、親 Claude が直接 tdd-develop ペルソナで動く。
|
|
156
162
|
|
|
157
163
|
1. `.claude/agents/tdd-develop.md` を Read してペルソナを採用する
|
|
158
|
-
2. `.claude/skills/worktree-tdd-workflow.md` を Read して TDD ループ手順(tester→developer→tester)を取得する
|
|
159
|
-
3. タスクの `prompt` を実装内容として、worktree-tdd-workflow.md の Step 1〜4 を **親 Claude が直接** 実行する。tester / developer は Agent ツールでスポーン可能(depth 1 で完結する)
|
|
164
|
+
2. `.claude/skills/worktree-tdd-workflow/SKILL.md` を Read して TDD ループ手順(tester→developer→tester)を取得する
|
|
165
|
+
3. タスクの `prompt` を実装内容として、worktree-tdd-workflow/SKILL.md の Step 1〜4 を **親 Claude が直接** 実行する。tester / developer は Agent ツールでスポーン可能(depth 1 で完結する)
|
|
160
166
|
4. ループ完了後、結果を 2-D の集約に渡す
|
|
161
167
|
|
|
162
168
|
##### A-2: `agent` がそれ以外(`code-reviewer` / `security-reviewer` / `developer` / `tester` 等)
|
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.0] - 2026-05-04
|
|
4
|
+
|
|
5
|
+
### Breaking Changes
|
|
6
|
+
- **Skill renamed**: `/review` → `/code-review` — avoids conflict with the
|
|
7
|
+
official Claude Code `/review [PR]` command (which reviews pull requests).
|
|
8
|
+
C3's `/code-review` runs `code-reviewer` + `security-reviewer` agents
|
|
9
|
+
as dev-workflow phase E.
|
|
10
|
+
- **Skill renamed**: `/mcp` → `/mcp-config` — avoids conflict with the
|
|
11
|
+
official Claude Code `/mcp` command (which manages live MCP connections).
|
|
12
|
+
C3's `/mcp-config` manages `mcpServers` entries in `.claude/settings.json`.
|
|
13
|
+
- **Skill structure**: `commands/` directory migrated to `skills/` following
|
|
14
|
+
the Claude Code 2026 skills standard. All skills are now under
|
|
15
|
+
`.claude/skills/{name}/SKILL.md` with YAML frontmatter.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- `stop.py`: Records `last_assistant_message` from Stop hook payload into the
|
|
19
|
+
session file's 事実ログ section as `- 最終応答: ...` (truncated at 500 chars).
|
|
20
|
+
The next session's init-session can now read what Claude last accomplished.
|
|
21
|
+
- `session_utils.py`: New shared module exporting `SESSIONS_DIR`,
|
|
22
|
+
`SESSION_JSON_MARKER`, `is_worktree()`, and `create_session_template()`.
|
|
23
|
+
Eliminates duplicate definitions across `stop.py` and `pre_compact.py`.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- `settings.local.json` had a duplicate `hooks` section identical to
|
|
27
|
+
`settings.json`, causing all hooks to fire twice per event. Removed.
|
|
28
|
+
- Hook commands now use `"$CLAUDE_PROJECT_DIR/.claude/hooks/…"` (absolute
|
|
29
|
+
path via env var) so hooks remain findable even after `cd` changes CWD.
|
|
30
|
+
The `cd` block in `pre_tool.py` has been removed as it is no longer needed.
|
|
31
|
+
- `UserPromptSubmit` hook for `statusline.py` removed — the hook input has no
|
|
32
|
+
`context_window` field, so it always displayed `0%`. The `statusLine`
|
|
33
|
+
setting handles display correctly on its own.
|
|
34
|
+
- `stop.py`: Reads and respects `stop_hook_active` flag — skips processing
|
|
35
|
+
on re-entrant Stop calls to prevent duplicate session updates.
|
|
36
|
+
- `pre_compact.py`: Uses `__file__`-based paths instead of `os.getcwd()` so
|
|
37
|
+
the session file is always found regardless of working directory.
|
|
38
|
+
- `pre_compact.py`: Records `trigger` (manual/auto) and `context_items_before`
|
|
39
|
+
in checkpoint output for richer context.
|
|
40
|
+
- `stop.py`: Sanitizes surrogate characters (`\udc80`–`\udcff`) in
|
|
41
|
+
`last_assistant_message` before writing to avoid `UnicodeEncodeError`.
|
|
42
|
+
- `settings.json`: Added missing `Write`/`Edit` permissions for
|
|
43
|
+
`.claude/reports/archive/**`, `.claude/rules/**`, `.claude/settings.json`,
|
|
44
|
+
`Edit(.claude/memory/**)`, `Edit(.claude/rules/**)`, `Edit(.claude/skills/**)`.
|
|
45
|
+
- Bash permissions for hook scripts now include both relative-path and
|
|
46
|
+
`$CLAUDE_PROJECT_DIR`-prefixed forms for full coverage.
|
|
47
|
+
|
|
3
48
|
## [0.3.4] - 2026-05-02
|
|
4
49
|
|
|
5
50
|
### Security
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-code-conductor
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
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
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# /develop コマンド
|
|
2
|
-
|
|
3
|
-
plan-report に基づいて実装フェーズを実行する。
|
|
4
|
-
|
|
5
|
-
## 必ず守ること
|
|
6
|
-
|
|
7
|
-
1. **最初に必ず** `.claude/skills/dev-workflow.md` を Read する。記憶・推測で進めない
|
|
8
|
-
2. **フェーズ D(実装)** から実行する
|
|
9
|
-
3. dev-workflow.md の AskUserQuestion・Edit・セッションファイル更新の手順を省略しない
|
|
10
|
-
4. D-0 で plan-report に YAML フロントマター(`po_plan_version`)が検出された場合は、続けて **必ず** `.claude/skills/wave-execution.md` を Read してその手順に従う(C3 メイン + PO スポット並列モード)
|
|
11
|
-
5. フロントマターが無い場合は legacy の D-1〜D-5 ceremony(tester→developer→tester の TDD 逐次実行)にフォールバックする
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""PreCompact hook: append checkpoint marker to today's session file."""
|
|
3
|
-
|
|
4
|
-
import json
|
|
5
|
-
import os
|
|
6
|
-
import sys
|
|
7
|
-
from datetime import datetime, timezone
|
|
8
|
-
|
|
9
|
-
sys.stdout.reconfigure(encoding='utf-8')
|
|
10
|
-
sys.stderr.reconfigure(encoding='utf-8')
|
|
11
|
-
|
|
12
|
-
SESSION_JSON_MARKER = 'C3:SESSION:JSON'
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def is_worktree(cwd: str) -> bool:
|
|
16
|
-
git_path = os.path.join(cwd, '.git')
|
|
17
|
-
return os.path.exists(git_path) and os.path.isfile(git_path)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def create_session_template(date_str: str) -> str:
|
|
21
|
-
return (
|
|
22
|
-
f"SESSION: {date_str}\n"
|
|
23
|
-
f"AGENT: \n"
|
|
24
|
-
f"DURATION: \n"
|
|
25
|
-
f"\n"
|
|
26
|
-
f"## うまくいったアプローチ\n"
|
|
27
|
-
f"\n"
|
|
28
|
-
f"## 試みたが失敗したアプローチ\n"
|
|
29
|
-
f"\n"
|
|
30
|
-
f"## 残タスク\n"
|
|
31
|
-
f"\n"
|
|
32
|
-
f"## 事実ログ(自動生成 / stop.py)\n"
|
|
33
|
-
f"- 記録時刻: \n"
|
|
34
|
-
f"\n"
|
|
35
|
-
f"<!-- {SESSION_JSON_MARKER}\n"
|
|
36
|
-
f"{{\n"
|
|
37
|
-
f' "session": "{date_str}",\n'
|
|
38
|
-
f' "patterns": [],\n'
|
|
39
|
-
f' "successes": [],\n'
|
|
40
|
-
f' "failures": [],\n'
|
|
41
|
-
f' "todos": []\n'
|
|
42
|
-
f"}}\n"
|
|
43
|
-
f"-->\n"
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def main():
|
|
48
|
-
try:
|
|
49
|
-
json.loads(sys.stdin.read())
|
|
50
|
-
except (json.JSONDecodeError, ValueError):
|
|
51
|
-
pass
|
|
52
|
-
|
|
53
|
-
cwd = os.getcwd()
|
|
54
|
-
|
|
55
|
-
if is_worktree(cwd):
|
|
56
|
-
sys.exit(0)
|
|
57
|
-
|
|
58
|
-
session_dir = os.path.join(cwd, '.claude', 'memory', 'sessions')
|
|
59
|
-
os.makedirs(session_dir, exist_ok=True)
|
|
60
|
-
|
|
61
|
-
now = datetime.now(timezone.utc)
|
|
62
|
-
date_str = now.strftime('%Y%m%d')
|
|
63
|
-
session_file = os.path.join(session_dir, f'{date_str}.tmp')
|
|
64
|
-
|
|
65
|
-
try:
|
|
66
|
-
with open(session_file, 'x', encoding='utf-8') as f:
|
|
67
|
-
f.write(create_session_template(date_str))
|
|
68
|
-
except FileExistsError:
|
|
69
|
-
pass # already created by stop.py or another process
|
|
70
|
-
|
|
71
|
-
ts = now.isoformat()
|
|
72
|
-
checkpoint = (
|
|
73
|
-
f'\n'
|
|
74
|
-
f'## [PreCompact checkpoint: {ts}]\n'
|
|
75
|
-
f'コンテキストウィンドウ圧縮が発生しました。\n'
|
|
76
|
-
f'このポイント以前の詳細な文脈は失われています。\n'
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
with open(session_file, 'a', encoding='utf-8') as f:
|
|
80
|
-
f.write(checkpoint)
|
|
81
|
-
|
|
82
|
-
print(f'[PreCompact] セッション状態を {session_file} に保存しました', file=sys.stderr)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if __name__ == '__main__':
|
|
86
|
-
main()
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Bash(python .claude/hooks/clear_file_history.py*)",
|
|
5
|
-
"Bash(python .claude/hooks/enable_sandbox.py*)",
|
|
6
|
-
"Bash(python .claude/hooks/stop.py*)",
|
|
7
|
-
"Bash(python .claude/hooks/pre_tool.py*)",
|
|
8
|
-
"Bash(python .claude/hooks/pre_compact.py*)",
|
|
9
|
-
"Bash(python .claude/hooks/validate_skill_change.py*)",
|
|
10
|
-
"Bash(python .claude/hooks/statusline.py*)",
|
|
11
|
-
"Bash(python -m pytest tests/test_task_manager.py -v)",
|
|
12
|
-
"Bash(python *)",
|
|
13
|
-
"Bash(pytest *)",
|
|
14
|
-
"Bash(xargs wc *)",
|
|
15
|
-
"Bash(git add*)",
|
|
16
|
-
"Bash(git commit*)",
|
|
17
|
-
"Bash(git status*)",
|
|
18
|
-
"Bash(git diff*)",
|
|
19
|
-
"Bash(git log*)",
|
|
20
|
-
"Bash(pytest*)",
|
|
21
|
-
"Bash(python -m pytest*)",
|
|
22
|
-
"Bash(mkdir*)",
|
|
23
|
-
"Edit(**)",
|
|
24
|
-
"Edit(.claude/reports/**)",
|
|
25
|
-
"Edit(.claude/memory/sessions/**)",
|
|
26
|
-
"Glob(**)",
|
|
27
|
-
"Grep(**)",
|
|
28
|
-
"Read(**)",
|
|
29
|
-
"Write(**)",
|
|
30
|
-
"Write(.claude/tmp/**)",
|
|
31
|
-
"Write(.claude/memory/**)",
|
|
32
|
-
"Write(.claude/reports/**)",
|
|
33
|
-
"Write(.claude/memory/sessions/**)",
|
|
34
|
-
"Write(.claude/rules/promoted/**)",
|
|
35
|
-
"Write(.claude/skills/promoted/**)",
|
|
36
|
-
"WebFetch(domain:github.com)",
|
|
37
|
-
"WebFetch(domain:pypi.org)",
|
|
38
|
-
"Bash(grep \"\\\\.py$\")",
|
|
39
|
-
"WebFetch(domain:raw.githubusercontent.com)",
|
|
40
|
-
"Bash(pip-audit)",
|
|
41
|
-
"Bash(c3 po *)"
|
|
42
|
-
]
|
|
43
|
-
},
|
|
44
|
-
"hooks": {
|
|
45
|
-
"PreToolUse": [
|
|
46
|
-
{
|
|
47
|
-
"matcher": "Bash",
|
|
48
|
-
"hooks": [
|
|
49
|
-
{
|
|
50
|
-
"type": "command",
|
|
51
|
-
"command": "python .claude/hooks/pre_tool.py"
|
|
52
|
-
}
|
|
53
|
-
]
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
"matcher": "Write",
|
|
57
|
-
"hooks": [
|
|
58
|
-
{
|
|
59
|
-
"type": "command",
|
|
60
|
-
"command": "python .claude/hooks/worktree_guard.py"
|
|
61
|
-
}
|
|
62
|
-
]
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
"matcher": "Edit",
|
|
66
|
-
"hooks": [
|
|
67
|
-
{
|
|
68
|
-
"type": "command",
|
|
69
|
-
"command": "python .claude/hooks/worktree_guard.py"
|
|
70
|
-
}
|
|
71
|
-
]
|
|
72
|
-
}
|
|
73
|
-
],
|
|
74
|
-
"PostToolUse": [
|
|
75
|
-
{
|
|
76
|
-
"matcher": "Write",
|
|
77
|
-
"hooks": [
|
|
78
|
-
{
|
|
79
|
-
"type": "command",
|
|
80
|
-
"command": "python .claude/hooks/validate_skill_change.py"
|
|
81
|
-
}
|
|
82
|
-
]
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
"matcher": "Edit",
|
|
86
|
-
"hooks": [
|
|
87
|
-
{
|
|
88
|
-
"type": "command",
|
|
89
|
-
"command": "python .claude/hooks/validate_skill_change.py"
|
|
90
|
-
}
|
|
91
|
-
]
|
|
92
|
-
}
|
|
93
|
-
],
|
|
94
|
-
"PreCompact": [
|
|
95
|
-
{
|
|
96
|
-
"matcher": "",
|
|
97
|
-
"hooks": [
|
|
98
|
-
{
|
|
99
|
-
"type": "command",
|
|
100
|
-
"command": "python .claude/hooks/pre_compact.py"
|
|
101
|
-
}
|
|
102
|
-
]
|
|
103
|
-
}
|
|
104
|
-
],
|
|
105
|
-
"Stop": [
|
|
106
|
-
{
|
|
107
|
-
"matcher": "",
|
|
108
|
-
"hooks": [
|
|
109
|
-
{
|
|
110
|
-
"type": "command",
|
|
111
|
-
"command": "python .claude/hooks/stop.py"
|
|
112
|
-
}
|
|
113
|
-
]
|
|
114
|
-
}
|
|
115
|
-
],
|
|
116
|
-
"UserPromptSubmit": [
|
|
117
|
-
{
|
|
118
|
-
"matcher": "",
|
|
119
|
-
"hooks": [
|
|
120
|
-
{
|
|
121
|
-
"type": "command",
|
|
122
|
-
"command": "python .claude/hooks/statusline.py"
|
|
123
|
-
}
|
|
124
|
-
]
|
|
125
|
-
}
|
|
126
|
-
]
|
|
127
|
-
}
|
|
128
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/agents/security-reviewer.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/hooks/clear_file_history.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/hooks/validate_skill_change.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_conductor-0.3.4 → claude_code_conductor-0.4.0}/.claude/rules/code-review-checklist.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|