moai-adk 0.3.0__py3-none-any.whl

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.

Potentially problematic release.


This version of moai-adk might be problematic. Click here for more details.

Files changed (87) hide show
  1. moai_adk/__init__.py +8 -0
  2. moai_adk/__main__.py +86 -0
  3. moai_adk/cli/__init__.py +2 -0
  4. moai_adk/cli/commands/__init__.py +16 -0
  5. moai_adk/cli/commands/backup.py +56 -0
  6. moai_adk/cli/commands/doctor.py +184 -0
  7. moai_adk/cli/commands/init.py +284 -0
  8. moai_adk/cli/commands/restore.py +77 -0
  9. moai_adk/cli/commands/status.py +79 -0
  10. moai_adk/cli/commands/update.py +133 -0
  11. moai_adk/cli/main.py +12 -0
  12. moai_adk/cli/prompts/__init__.py +5 -0
  13. moai_adk/cli/prompts/init_prompts.py +159 -0
  14. moai_adk/core/__init__.py +2 -0
  15. moai_adk/core/git/__init__.py +24 -0
  16. moai_adk/core/git/branch.py +26 -0
  17. moai_adk/core/git/branch_manager.py +137 -0
  18. moai_adk/core/git/checkpoint.py +140 -0
  19. moai_adk/core/git/commit.py +68 -0
  20. moai_adk/core/git/event_detector.py +81 -0
  21. moai_adk/core/git/manager.py +127 -0
  22. moai_adk/core/project/__init__.py +2 -0
  23. moai_adk/core/project/backup_utils.py +84 -0
  24. moai_adk/core/project/checker.py +302 -0
  25. moai_adk/core/project/detector.py +105 -0
  26. moai_adk/core/project/initializer.py +174 -0
  27. moai_adk/core/project/phase_executor.py +297 -0
  28. moai_adk/core/project/validator.py +118 -0
  29. moai_adk/core/quality/__init__.py +6 -0
  30. moai_adk/core/quality/trust_checker.py +441 -0
  31. moai_adk/core/quality/validators/__init__.py +6 -0
  32. moai_adk/core/quality/validators/base_validator.py +19 -0
  33. moai_adk/core/template/__init__.py +8 -0
  34. moai_adk/core/template/backup.py +95 -0
  35. moai_adk/core/template/config.py +95 -0
  36. moai_adk/core/template/languages.py +44 -0
  37. moai_adk/core/template/merger.py +117 -0
  38. moai_adk/core/template/processor.py +310 -0
  39. moai_adk/templates/.claude/agents/alfred/cc-manager.md +474 -0
  40. moai_adk/templates/.claude/agents/alfred/code-builder.md +534 -0
  41. moai_adk/templates/.claude/agents/alfred/debug-helper.md +302 -0
  42. moai_adk/templates/.claude/agents/alfred/doc-syncer.md +175 -0
  43. moai_adk/templates/.claude/agents/alfred/git-manager.md +200 -0
  44. moai_adk/templates/.claude/agents/alfred/project-manager.md +152 -0
  45. moai_adk/templates/.claude/agents/alfred/spec-builder.md +256 -0
  46. moai_adk/templates/.claude/agents/alfred/tag-agent.md +247 -0
  47. moai_adk/templates/.claude/agents/alfred/trust-checker.md +332 -0
  48. moai_adk/templates/.claude/commands/alfred/0-project.md +523 -0
  49. moai_adk/templates/.claude/commands/alfred/1-spec.md +531 -0
  50. moai_adk/templates/.claude/commands/alfred/2-build.md +413 -0
  51. moai_adk/templates/.claude/commands/alfred/3-sync.md +552 -0
  52. moai_adk/templates/.claude/hooks/alfred/README.md +238 -0
  53. moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +165 -0
  54. moai_adk/templates/.claude/hooks/alfred/core/__init__.py +79 -0
  55. moai_adk/templates/.claude/hooks/alfred/core/checkpoint.py +271 -0
  56. moai_adk/templates/.claude/hooks/alfred/core/context.py +110 -0
  57. moai_adk/templates/.claude/hooks/alfred/core/project.py +284 -0
  58. moai_adk/templates/.claude/hooks/alfred/core/tags.py +244 -0
  59. moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +23 -0
  60. moai_adk/templates/.claude/hooks/alfred/handlers/compact.py +51 -0
  61. moai_adk/templates/.claude/hooks/alfred/handlers/notification.py +25 -0
  62. moai_adk/templates/.claude/hooks/alfred/handlers/session.py +80 -0
  63. moai_adk/templates/.claude/hooks/alfred/handlers/tool.py +71 -0
  64. moai_adk/templates/.claude/hooks/alfred/handlers/user.py +41 -0
  65. moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +635 -0
  66. moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +691 -0
  67. moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +469 -0
  68. moai_adk/templates/.claude/settings.json +135 -0
  69. moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +68 -0
  70. moai_adk/templates/.github/workflows/moai-gitflow.yml +255 -0
  71. moai_adk/templates/.gitignore +41 -0
  72. moai_adk/templates/.moai/config.json +89 -0
  73. moai_adk/templates/.moai/memory/development-guide.md +367 -0
  74. moai_adk/templates/.moai/memory/spec-metadata.md +277 -0
  75. moai_adk/templates/.moai/project/product.md +121 -0
  76. moai_adk/templates/.moai/project/structure.md +150 -0
  77. moai_adk/templates/.moai/project/tech.md +221 -0
  78. moai_adk/templates/CLAUDE.md +733 -0
  79. moai_adk/templates/__init__.py +2 -0
  80. moai_adk/utils/__init__.py +8 -0
  81. moai_adk/utils/banner.py +42 -0
  82. moai_adk/utils/logger.py +152 -0
  83. moai_adk-0.3.0.dist-info/METADATA +20 -0
  84. moai_adk-0.3.0.dist-info/RECORD +87 -0
  85. moai_adk-0.3.0.dist-info/WHEEL +4 -0
  86. moai_adk-0.3.0.dist-info/entry_points.txt +2 -0
  87. moai_adk-0.3.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,238 @@
1
+ # Alfred Hooks System
2
+
3
+ **Event-Driven Context Management for MoAI-ADK**
4
+
5
+ Alfred Hooks는 Claude Code의 이벤트 시스템과 통합되어 프로젝트 컨텍스트를 자동으로 관리하고, 위험한 작업 전에 checkpoint를 생성하며, JIT (Just-in-Time) 문서 로딩을 제공합니다.
6
+
7
+ ---
8
+
9
+ ## 📐 Architecture
10
+
11
+ ### Modular Design (9 Files, ≤284 LOC each)
12
+
13
+ ```
14
+ .claude/hooks/alfred/
15
+ ├── alfred_hooks.py # Main entry point (CLI router)
16
+ ├── core/ # Core business logic
17
+ │ ├── __init__.py # Type definitions (HookPayload, HookResult)
18
+ │ ├── project.py # Language detection, Git info, SPEC counting
19
+ │ ├── context.py # JIT retrieval, workflow context
20
+ │ ├── checkpoint.py # Event-driven checkpoint creation
21
+ │ └── tags.py # TAG search, verification, caching
22
+ └── handlers/ # Event handlers
23
+ ├── __init__.py # Handler exports
24
+ ├── session.py # SessionStart, SessionEnd
25
+ ├── user.py # UserPromptSubmit
26
+ ├── compact.py # PreCompact
27
+ ├── tool.py # PreToolUse, PostToolUse
28
+ └── notification.py # Notification, Stop, SubagentStop
29
+ ```
30
+
31
+ ### Design Principles
32
+
33
+ - **Single Responsibility**: 각 모듈은 하나의 명확한 책임
34
+ - **Separation of Concerns**: core (비즈니스 로직) vs handlers (이벤트 처리)
35
+ - **CODE-FIRST**: 중간 캐시 없이 코드 직접 스캔 (mtime 기반 무효화)
36
+ - **Context Engineering**: JIT Retrieval로 초기 컨텍스트 부담 최소화
37
+
38
+ ---
39
+
40
+ ## 🎯 Core Modules
41
+
42
+ ### `core/project.py` (284 LOC)
43
+
44
+ **프로젝트 메타데이터 및 언어 감지**
45
+
46
+ ```python
47
+ # Public API
48
+ detect_language(cwd: str) -> str
49
+ get_project_language(cwd: str) -> str
50
+ get_git_info(cwd: str) -> dict[str, Any]
51
+ count_specs(cwd: str) -> dict[str, int]
52
+ ```
53
+
54
+ **Features**:
55
+ - 20개 언어 자동 감지 (Python, TypeScript, Java, Go, Rust, etc.)
56
+ - `.moai/config.json` 우선, fallback to auto-detection
57
+ - Git 정보 조회 (branch, commit, changes)
58
+ - SPEC 진행도 계산 (total, completed, percentage)
59
+
60
+ ### `core/context.py` (110 LOC)
61
+
62
+ **JIT Context Retrieval 및 워크플로우 관리**
63
+
64
+ ```python
65
+ # Public API
66
+ get_jit_context(prompt: str, cwd: str) -> list[str]
67
+ save_phase_context(phase: str, data: Any, ttl: int = 600)
68
+ load_phase_context(phase: str, ttl: int = 600) -> Any | None
69
+ clear_workflow_context()
70
+ ```
71
+
72
+ **Features**:
73
+ - 프롬프트 분석 기반 문서 자동 추천
74
+ - `/alfred:1-spec` → `spec-metadata.md`
75
+ - `/alfred:2-build` → `development-guide.md`
76
+ - 워크플로우 단계별 컨텍스트 캐싱 (TTL 10분)
77
+ - Anthropic Context Engineering 원칙 준수
78
+
79
+ ### `core/checkpoint.py` (244 LOC)
80
+
81
+ **Event-Driven Checkpoint 자동화**
82
+
83
+ ```python
84
+ # Public API
85
+ detect_risky_operation(tool: str, args: dict, cwd: str) -> tuple[bool, str]
86
+ create_checkpoint(cwd: str, operation: str) -> str
87
+ log_checkpoint(cwd: str, branch: str, description: str)
88
+ list_checkpoints(cwd: str, max_count: int = 10) -> list[dict]
89
+ ```
90
+
91
+ **Features**:
92
+ - 위험한 작업 자동 감지:
93
+ - Bash: `rm -rf`, `git merge`, `git reset --hard`
94
+ - Edit/Write: `CLAUDE.md`, `config.json`
95
+ - MultiEdit: ≥10 files
96
+ - Git checkpoint 자동 생성: `checkpoint/before-{operation}-{timestamp}`
97
+ - checkpoint 이력 관리 및 복구 가이드
98
+
99
+ ### `core/tags.py` (244 LOC)
100
+
101
+ **CODE-FIRST TAG 시스템**
102
+
103
+ ```python
104
+ # Public API
105
+ search_tags(pattern: str, scope: list[str], cache_ttl: int = 60) -> list[dict]
106
+ verify_tag_chain(tag_id: str) -> dict[str, Any]
107
+ find_all_tags_by_type(tag_type: str) -> dict[str, list[str]]
108
+ suggest_tag_reuse(keyword: str) -> list[str]
109
+ get_library_version(library: str, cache_ttl: int = 86400) -> str | None
110
+ set_library_version(library: str, version: str)
111
+ ```
112
+
113
+ **Features**:
114
+ - ripgrep 기반 TAG 검색 (JSON 출력 파싱)
115
+ - mtime 기반 캐시 무효화 (CODE-FIRST 보장)
116
+ - TAG 체인 검증 (@SPEC → @TEST → @CODE 완전성 확인)
117
+ - 라이브러리 버전 캐싱 (TTL 24시간)
118
+
119
+ ---
120
+
121
+ ## 🎬 Event Handlers
122
+
123
+ ### `handlers/session.py`
124
+
125
+ **SessionStart, SessionEnd 핸들러**
126
+
127
+ - **SessionStart**: 프로젝트 정보 표시
128
+ - 언어, Git 상태, SPEC 진행도, 최근 checkpoint
129
+ - `systemMessage` 필드로 사용자에게 직접 표시
130
+ - **SessionEnd**: 정리 작업 (stub)
131
+
132
+ ### `handlers/user.py`
133
+
134
+ **UserPromptSubmit 핸들러**
135
+
136
+ - JIT Context 추천 문서 리스트 반환
137
+ - 사용자 프롬프트 패턴 분석 및 관련 문서 로드
138
+
139
+ ### `handlers/compact.py`
140
+
141
+ **PreCompact 핸들러**
142
+
143
+ - 세션 요약 트리거 (>70% 토큰 사용)
144
+ - Compaction 권장 메시지 생성
145
+
146
+ ### `handlers/tool.py`
147
+
148
+ **PreToolUse, PostToolUse 핸들러**
149
+
150
+ - **PreToolUse**: 위험한 작업 감지 시 자동 checkpoint 생성
151
+ - **PostToolUse**: 후처리 작업 (stub)
152
+
153
+ ### `handlers/notification.py`
154
+
155
+ **Notification, Stop, SubagentStop 핸들러**
156
+
157
+ - 기본 구현 (stub, 향후 확장 가능)
158
+
159
+ ---
160
+
161
+ ## 🧪 Testing
162
+
163
+ ### Test Suite
164
+
165
+ ```bash
166
+ # Run all tests
167
+ uv run pytest tests/unit/test_alfred_hooks_*.py -v --no-cov
168
+
169
+ # Run specific module tests
170
+ uv run pytest tests/unit/test_alfred_hooks_core_tags.py -v
171
+ uv run pytest tests/unit/test_alfred_hooks_core_context.py -v
172
+ uv run pytest tests/unit/test_alfred_hooks_core_project.py -v
173
+ ```
174
+
175
+ ### Test Coverage (18 tests)
176
+
177
+ - ✅ **tags.py**: 7 tests (캐시, TAG 검증, 버전 관리)
178
+ - ✅ **context.py**: 5 tests (JIT, 워크플로우 컨텍스트)
179
+ - ✅ **project.py**: 6 tests (언어 감지, Git, SPEC 카운트)
180
+
181
+ ### Test Structure
182
+
183
+ ```python
184
+ # Dynamic module loading for isolated testing
185
+ def _load_{module}_module(module_name: str):
186
+ repo_root = Path(__file__).resolve().parents[2]
187
+ hooks_dir = repo_root / ".claude" / "hooks" / "alfred"
188
+ sys.path.insert(0, str(hooks_dir))
189
+
190
+ module_path = hooks_dir / "core" / "{module}.py"
191
+ spec = importlib.util.spec_from_file_location(module_name, module_path)
192
+ # ...
193
+ ```
194
+
195
+ ---
196
+
197
+ ## 🔄 Migration from moai_hooks.py
198
+
199
+ ### Before (Monolithic)
200
+
201
+ - **1 file**: 1233 LOC
202
+ - **Issues**:
203
+ - 모든 기능이 하나의 파일에 집중
204
+ - 테스트 어려움, 유지보수 복잡
205
+ - 책임 분리 불명확
206
+
207
+ ### After (Modular)
208
+
209
+ - **9 files**: ≤284 LOC each
210
+ - **Benefits**:
211
+ - 명확한 책임 분리 (SRP)
212
+ - 독립적인 모듈 테스트 가능
213
+ - 확장 용이, 유지보수 간편
214
+ - Context Engineering 원칙 준수
215
+
216
+ ### Breaking Changes
217
+
218
+ **없음** - 외부 API는 동일하게 유지됩니다.
219
+
220
+ ---
221
+
222
+ ## 📚 References
223
+
224
+ ### Internal Documents
225
+
226
+ - **CLAUDE.md**: MoAI-ADK 사용자 가이드
227
+ - **.moai/memory/development-guide.md**: SPEC-First TDD 워크플로우
228
+ - **.moai/memory/spec-metadata.md**: SPEC 메타데이터 표준
229
+
230
+ ### External Resources
231
+
232
+ - [Claude Code Hooks Documentation](https://docs.claude.com/en/docs/claude-code)
233
+ - [Anthropic Context Engineering](https://docs.anthropic.com/claude/docs/context-engineering)
234
+
235
+ ---
236
+
237
+ **Last Updated**: 2025-10-16
238
+ **Author**: @Alfred (MoAI-ADK SuperAgent)
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env python3
2
+ # @CODE:HOOKS-REFACTOR-001 | SPEC: SPEC-HOOKS-REFACTOR-001.md
3
+ """Alfred Hooks - Main entry point for MoAI-ADK Claude Code Hooks
4
+
5
+ Claude Code 이벤트를 적절한 핸들러로 라우팅하는 메인 진입점
6
+
7
+ Setup sys.path for package imports
8
+ """
9
+ import sys
10
+ from pathlib import Path
11
+
12
+ # Add the hooks directory to sys.path to enable package imports
13
+ HOOKS_DIR = Path(__file__).parent
14
+ if str(HOOKS_DIR) not in sys.path:
15
+ sys.path.insert(0, str(HOOKS_DIR))
16
+
17
+ # Now we can import from the package
18
+
19
+ """
20
+ Architecture:
21
+ ┌─────────────────────────────────────────────────────────────┐
22
+ │ alfred_hooks.py (Router) │
23
+ ├─────────────────────────────────────────────────────────────┤
24
+ │ - CLI argument parsing │
25
+ │ - JSON I/O (stdin/stdout) │
26
+ │ - Event routing to handlers │
27
+ └─────────────────────────────────────────────────────────────┘
28
+
29
+ ┌─────────────────────────────────────────────────────────────┐
30
+ │ handlers/ (Event Handlers) │
31
+ ├─────────────────────────────────────────────────────────────┤
32
+ │ - session.py: SessionStart, SessionEnd │
33
+ │ - user.py: UserPromptSubmit │
34
+ │ - compact.py: PreCompact │
35
+ │ - tool.py: PreToolUse, PostToolUse │
36
+ │ - notification.py: Notification, Stop, SubagentStop │
37
+ └─────────────────────────────────────────────────────────────┘
38
+
39
+ ┌─────────────────────────────────────────────────────────────┐
40
+ │ core/ (Business Logic) │
41
+ ├─────────────────────────────────────────────────────────────┤
42
+ │ - project.py: Language detection, Git info, SPEC progress │
43
+ │ - context.py: JIT Retrieval, workflow context │
44
+ │ - checkpoint.py: Event-Driven Checkpoint system │
45
+ │ - tags.py: TAG search/verification, library version cache │
46
+ └─────────────────────────────────────────────────────────────┘
47
+
48
+ Usage:
49
+ python alfred_hooks.py <event_name> < payload.json
50
+
51
+ Supported Events:
52
+ - SessionStart: 세션 시작 (프로젝트 상태 표시)
53
+ - UserPromptSubmit: 프롬프트 제출 (JIT 문서 로딩)
54
+ - PreCompact: 컨텍스트 초과 경고 (새 세션 제안)
55
+ - PreToolUse: Tool 사용 전 (Checkpoint 자동 생성)
56
+ - SessionEnd, PostToolUse, Notification, Stop, SubagentStop
57
+
58
+ Exit Codes:
59
+ - 0: 성공
60
+ - 1: 에러 (인수 없음, JSON 파싱 실패, 예외 발생)
61
+
62
+ TDD History:
63
+ - RED: 모듈 분리 설계, 이벤트 라우팅 테스트
64
+ - GREEN: 1233 LOC → 9개 모듈 분리 구현 (SRP 준수)
65
+ - REFACTOR: Import 최적화, 에러 처리 강화
66
+ """
67
+
68
+ import json
69
+
70
+ from core import HookResult
71
+ from handlers import (
72
+ handle_notification,
73
+ handle_post_tool_use,
74
+ handle_pre_compact,
75
+ handle_pre_tool_use,
76
+ handle_session_end,
77
+ handle_session_start,
78
+ handle_stop,
79
+ handle_subagent_stop,
80
+ handle_user_prompt_submit,
81
+ )
82
+
83
+
84
+ def main() -> None:
85
+ """메인 진입점 - Claude Code Hook 스크립트
86
+
87
+ CLI 인수로 이벤트명을 받고, stdin으로 JSON 페이로드를 읽습니다.
88
+ 이벤트에 맞는 핸들러를 호출하고, 결과를 JSON으로 stdout에 출력합니다.
89
+
90
+ Usage:
91
+ python alfred_hooks.py <event_name> < payload.json
92
+
93
+ Supported Events:
94
+ - SessionStart: 세션 시작 (프로젝트 상태 표시)
95
+ - UserPromptSubmit: 프롬프트 제출 (JIT 문서 로딩)
96
+ - PreCompact: 컨텍스트 초과 경고 (새 세션 제안)
97
+ - SessionEnd, PreToolUse, PostToolUse, Notification, Stop, SubagentStop
98
+
99
+ Exit Codes:
100
+ - 0: 성공
101
+ - 1: 에러 (인수 없음, JSON 파싱 실패, 예외 발생)
102
+
103
+ Examples:
104
+ $ echo '{"cwd": "."}' | python alfred_hooks.py SessionStart
105
+ {"message": "🚀 MoAI-ADK Session Started\\n...", ...}
106
+
107
+ Notes:
108
+ - Claude Code가 자동으로 호출 (사용자 직접 실행 불필요)
109
+ - stdin/stdout으로 JSON I/O 처리
110
+ - stderr로 에러 메시지 출력
111
+ - UserPromptSubmit은 특별한 출력 스키마 사용 (hookEventName + additionalContext)
112
+
113
+ TDD History:
114
+ - RED: 이벤트 라우팅, JSON I/O, 에러 처리 테스트
115
+ - GREEN: 핸들러 맵 기반 라우팅 구현
116
+ - REFACTOR: 에러 메시지 명확화, exit code 표준화, UserPromptSubmit 스키마 분리
117
+ """
118
+ # Check for event argument
119
+ if len(sys.argv) < 2:
120
+ print("Usage: alfred_hooks.py <event>", file=sys.stderr)
121
+ sys.exit(1)
122
+
123
+ event_name = sys.argv[1]
124
+
125
+ try:
126
+ # Read JSON from stdin
127
+ input_data = sys.stdin.read()
128
+ data = json.loads(input_data)
129
+
130
+ cwd = data.get("cwd", ".")
131
+
132
+ # Route to appropriate handler
133
+ handlers = {
134
+ "SessionStart": handle_session_start,
135
+ "UserPromptSubmit": handle_user_prompt_submit,
136
+ "PreCompact": handle_pre_compact,
137
+ "SessionEnd": handle_session_end,
138
+ "PreToolUse": handle_pre_tool_use,
139
+ "PostToolUse": handle_post_tool_use,
140
+ "Notification": handle_notification,
141
+ "Stop": handle_stop,
142
+ "SubagentStop": handle_subagent_stop,
143
+ }
144
+
145
+ handler = handlers.get(event_name)
146
+ result = handler({"cwd": cwd, **data}) if handler else HookResult()
147
+
148
+ # UserPromptSubmit은 특별한 출력 스키마 사용
149
+ if event_name == "UserPromptSubmit":
150
+ print(json.dumps(result.to_user_prompt_submit_dict()))
151
+ else:
152
+ print(json.dumps(result.to_dict()))
153
+
154
+ sys.exit(0)
155
+
156
+ except json.JSONDecodeError as e:
157
+ print(f"JSON parse error: {e}", file=sys.stderr)
158
+ sys.exit(1)
159
+ except Exception as e:
160
+ print(f"Unexpected error: {e}", file=sys.stderr)
161
+ sys.exit(1)
162
+
163
+
164
+ if __name__ == "__main__":
165
+ main()
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env python3
2
+ """Core module for Alfred Hooks
3
+
4
+ 공통 타입 정의 및 유틸리티 함수
5
+ """
6
+
7
+ from dataclasses import asdict, dataclass, field
8
+ from typing import Any, NotRequired, TypedDict
9
+
10
+
11
+ class HookPayload(TypedDict):
12
+ """Claude Code Hook 이벤트 페이로드 타입 정의
13
+
14
+ Claude Code가 Hook 스크립트에 전달하는 데이터 구조.
15
+ 이벤트에 따라 필드가 다를 수 있으므로 NotRequired 사용.
16
+ """
17
+
18
+ cwd: str
19
+ userPrompt: NotRequired[str] # UserPromptSubmit 이벤트만 포함
20
+ tool: NotRequired[str] # PreToolUse/PostToolUse 이벤트
21
+ arguments: NotRequired[dict[str, Any]] # Tool arguments
22
+
23
+
24
+ @dataclass
25
+ class HookResult:
26
+ """Hook 실행 결과"""
27
+
28
+ message: str | None = None
29
+ systemMessage: str | None = None # 사용자에게 직접 표시되는 메시지
30
+ blocked: bool = False
31
+ contextFiles: list[str] = field(default_factory=list)
32
+ suggestions: list[str] = field(default_factory=list)
33
+ exitCode: int = 0
34
+
35
+ def to_dict(self) -> dict[str, Any]:
36
+ """일반 Hook용 딕셔너리 변환"""
37
+ return asdict(self)
38
+
39
+ def to_user_prompt_submit_dict(self) -> dict[str, Any]:
40
+ """UserPromptSubmit Hook 전용 출력 형식
41
+
42
+ Claude Code는 UserPromptSubmit에 대해 특별한 스키마를 요구:
43
+ {
44
+ "hookEventName": "UserPromptSubmit",
45
+ "additionalContext": "string (required)"
46
+ }
47
+
48
+ Returns:
49
+ Claude Code UserPromptSubmit Hook 스키마에 맞는 딕셔너리
50
+
51
+ Examples:
52
+ >>> result = HookResult(contextFiles=["tests/"])
53
+ >>> result.to_user_prompt_submit_dict()
54
+ {'hookEventName': 'UserPromptSubmit', 'additionalContext': '📎 Context: tests/'}
55
+ """
56
+ # contextFiles를 additionalContext 문자열로 변환
57
+ if self.contextFiles:
58
+ context_str = "\n".join([f"📎 Context: {f}" for f in self.contextFiles])
59
+ else:
60
+ context_str = ""
61
+
62
+ # message가 있으면 추가
63
+ if self.message:
64
+ if context_str:
65
+ context_str = f"{self.message}\n\n{context_str}"
66
+ else:
67
+ context_str = self.message
68
+
69
+ # 빈 문자열이면 기본값 사용
70
+ if not context_str:
71
+ context_str = ""
72
+
73
+ return {
74
+ "hookEventName": "UserPromptSubmit",
75
+ "additionalContext": context_str
76
+ }
77
+
78
+
79
+ __all__ = ["HookPayload", "HookResult"]