moai-adk 0.8.0__py3-none-any.whl → 0.15.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 (207) hide show
  1. moai_adk/cli/commands/init.py +14 -2
  2. moai_adk/cli/commands/update.py +229 -60
  3. moai_adk/core/config/migration.py +1 -1
  4. moai_adk/core/issue_creator.py +313 -0
  5. moai_adk/core/project/detector.py +201 -12
  6. moai_adk/core/project/initializer.py +62 -1
  7. moai_adk/core/project/phase_executor.py +48 -6
  8. moai_adk/core/tags/__init__.py +86 -0
  9. moai_adk/core/tags/ci_validator.py +463 -0
  10. moai_adk/core/tags/cli.py +283 -0
  11. moai_adk/core/tags/generator.py +109 -0
  12. moai_adk/core/tags/inserter.py +99 -0
  13. moai_adk/core/tags/mapper.py +126 -0
  14. moai_adk/core/tags/parser.py +76 -0
  15. moai_adk/core/tags/pre_commit_validator.py +393 -0
  16. moai_adk/core/tags/reporter.py +956 -0
  17. moai_adk/core/tags/tags.py +149 -0
  18. moai_adk/core/tags/validator.py +897 -0
  19. moai_adk/core/template_engine.py +268 -0
  20. moai_adk/templates/.claude/agents/alfred/backend-expert.md +319 -0
  21. moai_adk/templates/.claude/agents/alfred/cc-manager.md +25 -2
  22. moai_adk/templates/.claude/agents/alfred/debug-helper.md +24 -12
  23. moai_adk/templates/.claude/agents/alfred/devops-expert.md +464 -0
  24. moai_adk/templates/.claude/agents/alfred/doc-syncer.md +20 -13
  25. moai_adk/templates/.claude/agents/alfred/frontend-expert.md +357 -0
  26. moai_adk/templates/.claude/agents/alfred/git-manager.md +47 -16
  27. moai_adk/templates/.claude/agents/alfred/implementation-planner.md +95 -15
  28. moai_adk/templates/.claude/agents/alfred/project-manager.md +78 -12
  29. moai_adk/templates/.claude/agents/alfred/quality-gate.md +28 -5
  30. moai_adk/templates/.claude/agents/alfred/skill-factory.md +30 -2
  31. moai_adk/templates/.claude/agents/alfred/spec-builder.md +133 -13
  32. moai_adk/templates/.claude/agents/alfred/tag-agent.md +104 -8
  33. moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +133 -16
  34. moai_adk/templates/.claude/agents/alfred/trust-checker.md +27 -4
  35. moai_adk/templates/.claude/agents/alfred/ui-ux-expert.md +571 -0
  36. moai_adk/templates/.claude/commands/alfred/0-project.md +466 -125
  37. moai_adk/templates/.claude/commands/alfred/1-plan.md +208 -71
  38. moai_adk/templates/.claude/commands/alfred/2-run.md +276 -55
  39. moai_adk/templates/.claude/commands/alfred/3-sync.md +439 -53
  40. moai_adk/templates/.claude/commands/alfred/9-feedback.md +149 -0
  41. moai_adk/templates/.claude/hooks/alfred/core/project.py +361 -29
  42. moai_adk/templates/.claude/hooks/alfred/core/timeout.py +136 -0
  43. moai_adk/templates/.claude/hooks/alfred/core/ttl_cache.py +108 -0
  44. moai_adk/templates/.claude/hooks/alfred/core/version_cache.py +198 -0
  45. moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +14 -6
  46. moai_adk/templates/.claude/hooks/alfred/post_tool__log_changes.py +94 -0
  47. moai_adk/templates/.claude/hooks/alfred/pre_tool__auto_checkpoint.py +100 -0
  48. moai_adk/templates/.claude/hooks/alfred/session_end__cleanup.py +94 -0
  49. moai_adk/templates/.claude/hooks/alfred/session_start__show_project_info.py +94 -0
  50. moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/__init__.py +2 -2
  51. moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/checkpoint.py +3 -3
  52. moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/context.py +5 -5
  53. moai_adk/templates/.claude/hooks/alfred/shared/core/project.py +749 -0
  54. moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/tags.py +55 -23
  55. moai_adk/templates/.claude/hooks/alfred/shared/core/version_cache.py +198 -0
  56. moai_adk/templates/.claude/hooks/alfred/shared/handlers/__init__.py +21 -0
  57. moai_adk/templates/.claude/hooks/alfred/shared/handlers/notification.py +154 -0
  58. moai_adk/templates/.claude/hooks/alfred/{handlers → shared/handlers}/session.py +28 -15
  59. moai_adk/templates/.claude/hooks/alfred/{handlers → shared/handlers}/tool.py +3 -6
  60. moai_adk/templates/.claude/hooks/alfred/{handlers → shared/handlers}/user.py +19 -0
  61. moai_adk/templates/.claude/hooks/alfred/user_prompt__jit_load_docs.py +112 -0
  62. moai_adk/templates/.claude/hooks/alfred/utils/__init__.py +1 -0
  63. moai_adk/templates/.claude/hooks/alfred/utils/timeout.py +161 -0
  64. moai_adk/templates/.claude/settings.json +5 -5
  65. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/SKILL.md +70 -0
  66. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/examples.md +62 -0
  67. moai_adk/templates/{.moai/memory/CLAUDE-AGENTS-GUIDE.md → .claude/skills/moai-alfred-agent-guide/reference.md} +34 -0
  68. moai_adk/templates/.claude/skills/moai-alfred-config-schema/SKILL.md +56 -0
  69. moai_adk/templates/.claude/skills/moai-alfred-config-schema/examples.md +28 -0
  70. moai_adk/templates/.claude/skills/moai-alfred-context-budget/SKILL.md +62 -0
  71. moai_adk/templates/.claude/skills/moai-alfred-context-budget/examples.md +28 -0
  72. moai_adk/templates/.claude/skills/moai-alfred-context-budget/reference.md +405 -0
  73. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/SKILL.md +51 -0
  74. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/examples.md +355 -0
  75. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/reference.md +239 -0
  76. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/SKILL.md +323 -0
  77. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/examples.md +286 -0
  78. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/reference.md +126 -0
  79. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/SKILL.md +74 -0
  80. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/examples.md +4 -0
  81. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/reference.md +269 -0
  82. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/SKILL.md +19 -0
  83. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/examples.md +4 -0
  84. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/reference.md +150 -0
  85. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/SKILL.md +198 -0
  86. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/examples.md +431 -0
  87. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/reference.md +141 -0
  88. moai_adk/templates/.claude/skills/moai-alfred-practices/SKILL.md +89 -0
  89. moai_adk/templates/.claude/skills/moai-alfred-practices/examples.md +122 -0
  90. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/SKILL.md +508 -0
  91. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/examples.md +481 -0
  92. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/reference.md +100 -0
  93. moai_adk/templates/.claude/skills/moai-alfred-reporting/SKILL.md +273 -0
  94. moai_adk/templates/.claude/skills/moai-alfred-rules/SKILL.md +77 -0
  95. moai_adk/templates/.claude/skills/moai-alfred-rules/examples.md +265 -0
  96. moai_adk/templates/.claude/skills/moai-alfred-session-state/SKILL.md +19 -0
  97. moai_adk/templates/.claude/skills/moai-alfred-session-state/examples.md +4 -0
  98. moai_adk/templates/.claude/skills/moai-alfred-session-state/reference.md +84 -0
  99. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/README.md +137 -0
  100. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/SKILL.md +219 -0
  101. moai_adk/templates/.claude/skills/{moai-spec-authoring → moai-alfred-spec-authoring}/examples/validate-spec.sh +3 -3
  102. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/examples.md +541 -0
  103. moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/reference.md +622 -0
  104. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/SKILL.md +115 -0
  105. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/examples.md +4 -0
  106. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/reference.md +348 -0
  107. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/SKILL.md +19 -0
  108. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/examples.md +4 -0
  109. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/reference.md +211 -0
  110. moai_adk/templates/.claude/skills/moai-alfred-workflow/SKILL.md +288 -0
  111. moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/SKILL.md +19 -0
  112. moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/examples.md +4 -0
  113. moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/SKILL.md +3 -3
  114. moai_adk/templates/.claude/skills/moai-design-systems/SKILL.md +802 -0
  115. moai_adk/templates/.claude/skills/moai-design-systems/examples.md +1238 -0
  116. moai_adk/templates/.claude/skills/moai-design-systems/reference.md +673 -0
  117. moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +17 -13
  118. moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +9 -6
  119. moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +15 -12
  120. moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +14 -12
  121. moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +14 -11
  122. moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +10 -8
  123. moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +15 -12
  124. moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +13 -11
  125. moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +16 -10
  126. moai_adk/templates/.claude/skills/moai-project-documentation.md +622 -0
  127. moai_adk/templates/.git-hooks/pre-push +143 -0
  128. moai_adk/templates/.github/workflows/c-tag-validation.yml +11 -0
  129. moai_adk/templates/.github/workflows/cpp-tag-validation.yml +11 -0
  130. moai_adk/templates/.github/workflows/csharp-tag-validation.yml +11 -0
  131. moai_adk/templates/.github/workflows/dart-tag-validation.yml +11 -0
  132. moai_adk/templates/.github/workflows/go-tag-validation.yml +130 -0
  133. moai_adk/templates/.github/workflows/java-tag-validation.yml +11 -0
  134. moai_adk/templates/.github/workflows/javascript-tag-validation.yml +135 -0
  135. moai_adk/templates/.github/workflows/kotlin-tag-validation.yml +11 -0
  136. moai_adk/templates/.github/workflows/moai-gitflow.yml +166 -3
  137. moai_adk/templates/.github/workflows/moai-release-create.yml +100 -0
  138. moai_adk/templates/.github/workflows/moai-release-pipeline.yml +188 -0
  139. moai_adk/templates/.github/workflows/php-tag-validation.yml +11 -0
  140. moai_adk/templates/.github/workflows/python-tag-validation.yml +118 -0
  141. moai_adk/templates/.github/workflows/release.yml +118 -0
  142. moai_adk/templates/.github/workflows/ruby-tag-validation.yml +11 -0
  143. moai_adk/templates/.github/workflows/rust-tag-validation.yml +11 -0
  144. moai_adk/templates/.github/workflows/shell-tag-validation.yml +11 -0
  145. moai_adk/templates/.github/workflows/spec-issue-sync.yml +206 -35
  146. moai_adk/templates/.github/workflows/swift-tag-validation.yml +11 -0
  147. moai_adk/templates/.github/workflows/tag-report.yml +269 -0
  148. moai_adk/templates/.github/workflows/tag-validation.yml +186 -0
  149. moai_adk/templates/.github/workflows/typescript-tag-validation.yml +154 -0
  150. moai_adk/templates/.moai/config.json +21 -2
  151. moai_adk/templates/CLAUDE.md +972 -78
  152. moai_adk/templates/workflows/go-tag-validation.yml +30 -0
  153. moai_adk/templates/workflows/javascript-tag-validation.yml +41 -0
  154. moai_adk/templates/workflows/python-tag-validation.yml +42 -0
  155. moai_adk/templates/workflows/typescript-tag-validation.yml +31 -0
  156. moai_adk/utils/banner.py +5 -5
  157. {moai_adk-0.8.0.dist-info → moai_adk-0.15.0.dist-info}/METADATA +1518 -161
  158. {moai_adk-0.8.0.dist-info → moai_adk-0.15.0.dist-info}/RECORD +183 -100
  159. moai_adk/templates/.claude/hooks/alfred/HOOK_SCHEMA_VALIDATION.md +0 -313
  160. moai_adk/templates/.claude/hooks/alfred/README.md +0 -230
  161. moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +0 -174
  162. moai_adk/templates/.claude/hooks/alfred/handlers/notification.py +0 -25
  163. moai_adk/templates/.claude/hooks/alfred/test_hook_output.py +0 -175
  164. moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +0 -640
  165. moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +0 -696
  166. moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +0 -474
  167. moai_adk/templates/.claude/skills/moai-spec-authoring/README.md +0 -137
  168. moai_adk/templates/.claude/skills/moai-spec-authoring/SKILL.md +0 -218
  169. moai_adk/templates/.claude/skills/moai-spec-authoring/examples.md +0 -541
  170. moai_adk/templates/.claude/skills/moai-spec-authoring/reference.md +0 -622
  171. moai_adk/templates/.github/ISSUE_TEMPLATE/spec.yml +0 -176
  172. moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +0 -69
  173. moai_adk/templates/.moai/memory/DEVELOPMENT-GUIDE.md +0 -344
  174. moai_adk/templates/.moai/memory/GITFLOW-PROTECTION-POLICY.md +0 -220
  175. moai_adk/templates/.moai/memory/SPEC-METADATA.md +0 -356
  176. moai_adk/templates/.moai/memory/config-schema.md +0 -444
  177. moai_adk/templates/.moai/memory/gitflow-protection-policy.md +0 -220
  178. moai_adk/templates/.moai/memory/spec-metadata.md +0 -356
  179. moai_adk/templates/.moai/project/product.md +0 -161
  180. moai_adk/templates/.moai/project/structure.md +0 -156
  181. moai_adk/templates/.moai/project/tech.md +0 -227
  182. moai_adk/templates/__init__.py +0 -2
  183. /moai_adk/templates/{.moai/memory/CONFIG-SCHEMA.md → .claude/skills/moai-alfred-config-schema/reference.md} +0 -0
  184. /moai_adk/templates/{.moai/memory/CLAUDE-PRACTICES.md → .claude/skills/moai-alfred-practices/reference.md} +0 -0
  185. /moai_adk/templates/{.moai/memory/CLAUDE-RULES.md → .claude/skills/moai-alfred-rules/reference.md} +0 -0
  186. /moai_adk/templates/{.moai/memory/SKILLS-DESCRIPTION-POLICY.md → .claude/skills/moai-cc-skill-descriptions/reference.md} +0 -0
  187. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/CHECKLIST.md +0 -0
  188. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/EXAMPLES.md +0 -0
  189. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/INTERACTIVE-DISCOVERY.md +0 -0
  190. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/METADATA.md +0 -0
  191. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/PARALLEL-ANALYSIS-REPORT.md +0 -0
  192. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/PYTHON-VERSION-MATRIX.md +0 -0
  193. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/SKILL-FACTORY-WORKFLOW.md +0 -0
  194. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/SKILL-UPDATE-ADVISOR.md +0 -0
  195. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/STEP-BY-STEP-GUIDE.md +0 -0
  196. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/STRUCTURE.md +0 -0
  197. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/WEB-RESEARCH.md +0 -0
  198. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/reference.md +0 -0
  199. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/scripts/generate-structure.sh +0 -0
  200. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/scripts/validate-skill.sh +0 -0
  201. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/templates/SKILL_TEMPLATE.md +0 -0
  202. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/templates/examples-template.md +0 -0
  203. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/templates/reference-template.md +0 -0
  204. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/templates/scripts-template.sh +0 -0
  205. {moai_adk-0.8.0.dist-info → moai_adk-0.15.0.dist-info}/WHEEL +0 -0
  206. {moai_adk-0.8.0.dist-info → moai_adk-0.15.0.dist-info}/entry_points.txt +0 -0
  207. {moai_adk-0.8.0.dist-info → moai_adk-0.15.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,174 +0,0 @@
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
- A main entry point that routes Claude Code events to the appropriate handlers.
6
-
7
- 🏗️ Architecture:
8
- ┌─────────────────────────────────────────────────────────────┐
9
- │ alfred_hooks.py (Router) │
10
- ├─────────────────────────────────────────────────────────────┤
11
- │ - CLI argument parsing │
12
- │ - JSON I/O (stdin/stdout) │
13
- │ - Event routing to handlers │
14
- └─────────────────────────────────────────────────────────────┘
15
-
16
- ┌─────────────────────────────────────────────────────────────┐
17
- │ handlers/ (Event Handlers) │
18
- ├─────────────────────────────────────────────────────────────┤
19
- │ - session.py: SessionStart, SessionEnd │
20
- │ - user.py: UserPromptSubmit │
21
- │ - tool.py: PreToolUse, PostToolUse │
22
- │ - notification.py: Notification, Stop, SubagentStop │
23
- └─────────────────────────────────────────────────────────────┘
24
-
25
- ┌─────────────────────────────────────────────────────────────┐
26
- │ core/ (Business Logic) │
27
- ├─────────────────────────────────────────────────────────────┤
28
- │ - project.py: Language detection, Git info, SPEC progress │
29
- │ - context.py: JIT Retrieval, workflow context │
30
- │ - checkpoint.py: Event-Driven Checkpoint system │
31
- │ - tags.py: TAG search/verification, library version cache │
32
- └─────────────────────────────────────────────────────────────┘
33
-
34
- 🛠️ Usage:
35
- python alfred_hooks.py <event_name> < payload.json
36
-
37
- 📣 Supported Events:
38
- - SessionStart: Start Session (display project status)
39
- - UserPromptSubmit: Prompt submission (JIT document loading)
40
- - PreToolUse: Before using the tool (automatically creates checkpoint)
41
- - SessionEnd, PostToolUse, Notification, Stop, SubagentStop
42
-
43
- 🚦 Exit Codes:
44
- - 0: Success
45
- - 1: Error (no arguments, JSON parsing failure, exception thrown)
46
-
47
- 🧪 TDD History:
48
- - RED: Module separation design, event routing test
49
- - GREEN: 1233 LOC → 9 items Module separation implementation (SRP compliance)
50
- - REFACTOR: Import optimization, enhanced error handling
51
-
52
- Setup sys.path for package imports
53
- """
54
-
55
- import json
56
- import sys
57
- from pathlib import Path
58
- from typing import Any
59
-
60
- from core import HookResult
61
- from handlers import (
62
- handle_notification,
63
- handle_post_tool_use,
64
- handle_pre_tool_use,
65
- handle_session_end,
66
- handle_session_start,
67
- handle_stop,
68
- handle_subagent_stop,
69
- handle_user_prompt_submit,
70
- )
71
-
72
- # Add the hooks directory to sys.path to enable package imports
73
- HOOKS_DIR = Path(__file__).parent
74
- if str(HOOKS_DIR) not in sys.path:
75
- sys.path.insert(0, str(HOOKS_DIR))
76
-
77
-
78
- def main() -> None:
79
- """Main entry point - Claude Code Hook script
80
-
81
- Receives the event name as a CLI argument and reads the JSON payload through stdin.
82
- Calls the handler appropriate for the event and outputs the results to stdout as JSON.
83
-
84
- 🛠️ Usage:
85
- python alfred_hooks.py <event_name> < payload.json
86
-
87
- 📣 Supported Events:
88
- - SessionStart: Start Session (display project status)
89
- - UserPromptSubmit: Prompt submission (JIT document loading)
90
- - SessionEnd, PreToolUse, PostToolUse, Notification, Stop, SubagentStop
91
-
92
- 🚦 Exit Codes:
93
- - 0: Success
94
- - 1: Error (no arguments, JSON parsing failure, exception thrown)
95
-
96
- 📝 Examples:
97
- $ echo '{"cwd": "."}' | python alfred_hooks.py SessionStart
98
- {"message": "🚀 MoAI-ADK Session Started\\n...", ...}
99
-
100
- 🗒️ Notes:
101
- - Claude Code is automatically called (no need for direct user execution)
102
- - JSON I/O processing through stdin/stdout
103
- - Print error message to stderr
104
- - UserPromptSubmit uses a special output schema (hookEventName + additionalContext)
105
-
106
- 🧪 TDD History:
107
- - RED: Event routing, JSON I/O, error handling testing
108
- - GREEN: Handler map-based routing implementation
109
- - REFACTOR: Error message clarification, exit code standardization, UserPromptSubmit schema separation
110
- """
111
- # Check for event argument
112
- if len(sys.argv) < 2:
113
- print("Usage: alfred_hooks.py <event>", file=sys.stderr)
114
- sys.exit(1)
115
-
116
- event_name = sys.argv[1]
117
-
118
- try:
119
- # Read JSON from stdin
120
- input_data = sys.stdin.read()
121
- # Handle empty stdin gracefully (return empty dict)
122
- if not input_data or not input_data.strip():
123
- data = {}
124
- else:
125
- data = json.loads(input_data)
126
-
127
- cwd = data.get("cwd", ".")
128
-
129
- # Route to appropriate handler
130
- handlers = {
131
- "SessionStart": handle_session_start,
132
- "UserPromptSubmit": handle_user_prompt_submit,
133
- "SessionEnd": handle_session_end,
134
- "PreToolUse": handle_pre_tool_use,
135
- "PostToolUse": handle_post_tool_use,
136
- "Notification": handle_notification,
137
- "Stop": handle_stop,
138
- "SubagentStop": handle_subagent_stop,
139
- }
140
-
141
- handler = handlers.get(event_name)
142
- result = handler({"cwd": cwd, **data}) if handler else HookResult()
143
-
144
- # Output Hook result as JSON
145
- # Note: UserPromptSubmit uses to_user_prompt_submit_dict() for special schema
146
- if event_name == "UserPromptSubmit":
147
- print(json.dumps(result.to_user_prompt_submit_dict()))
148
- else:
149
- print(json.dumps(result.to_dict()))
150
-
151
- sys.exit(0)
152
-
153
- except json.JSONDecodeError as e:
154
- # Return valid Hook response even on JSON parse error
155
- error_response: dict[str, Any] = {
156
- "continue": True,
157
- "hookSpecificOutput": {"error": f"JSON parse error: {e}"}
158
- }
159
- print(json.dumps(error_response))
160
- print(f"JSON parse error: {e}", file=sys.stderr)
161
- sys.exit(1)
162
- except Exception as e:
163
- # Return valid Hook response even on unexpected error
164
- error_response: dict[str, Any] = {
165
- "continue": True,
166
- "hookSpecificOutput": {"error": f"Hook error: {e}"}
167
- }
168
- print(json.dumps(error_response))
169
- print(f"Unexpected error: {e}", file=sys.stderr)
170
- sys.exit(1)
171
-
172
-
173
- if __name__ == "__main__":
174
- main()
@@ -1,25 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Notification and control handlers
3
-
4
- Notification, Stop, SubagentStop event handling
5
- """
6
-
7
- from core import HookPayload, HookResult
8
-
9
-
10
- def handle_notification(payload: HookPayload) -> HookResult:
11
- """Notification event handler (default implementation)"""
12
- return HookResult()
13
-
14
-
15
- def handle_stop(payload: HookPayload) -> HookResult:
16
- """Stop event handler (default implementation)"""
17
- return HookResult()
18
-
19
-
20
- def handle_subagent_stop(payload: HookPayload) -> HookResult:
21
- """SubagentStop event handler (default implementation)"""
22
- return HookResult()
23
-
24
-
25
- __all__ = ["handle_notification", "handle_stop", "handle_subagent_stop"]
@@ -1,175 +0,0 @@
1
- #!/usr/bin/env -S uv run --script
2
- # /// script
3
- # requires-python = ">=3.11"
4
- # ///
5
- """Test Hook Output Validation
6
-
7
- 자동 테스트: Claude Code Hook JSON 스키마 검증
8
-
9
- - SessionStart Hook JSON 출력 검증
10
- - UserPromptSubmit Hook 특수 스키마 검증
11
- - 모든 Hook 이벤트 스키마 일관성 검증
12
-
13
- 실행:
14
- uv run test_hook_output.py
15
- """
16
-
17
- import json
18
- import sys
19
- from pathlib import Path
20
-
21
- # Add hooks directory to sys.path
22
- HOOKS_DIR = Path(__file__).parent
23
- if str(HOOKS_DIR) not in sys.path:
24
- sys.path.insert(0, str(HOOKS_DIR))
25
-
26
- from core import HookResult # noqa: E402
27
-
28
-
29
- def test_basic_output():
30
- """Test 1: Basic output with only continue flag"""
31
- result = HookResult(continue_execution=True)
32
- output = result.to_dict()
33
-
34
- assert output == {"continue": True}, f"Expected {{'continue': True}}, got {output}"
35
- print("✅ Test 1: Basic output - PASSED")
36
-
37
-
38
- def test_system_message_top_level():
39
- """Test 2: systemMessage at TOP-LEVEL (not in hookSpecificOutput)"""
40
- result = HookResult(system_message="Test message")
41
- output = result.to_dict()
42
-
43
- assert "systemMessage" in output, "systemMessage not found in output"
44
- assert output["systemMessage"] == "Test message"
45
- assert "hookSpecificOutput" not in output, "hookSpecificOutput should not be in to_dict() output"
46
- print("✅ Test 2: systemMessage (top-level) - PASSED")
47
-
48
-
49
- def test_decision_with_reason():
50
- """Test 3: decision + reason (block pattern)"""
51
- result = HookResult(decision="block", reason="Dangerous operation")
52
- output = result.to_dict()
53
-
54
- assert output.get("decision") == "block"
55
- assert output.get("reason") == "Dangerous operation"
56
- assert "continue" not in output, "continue should not appear when decision is set"
57
- print("✅ Test 3: decision + reason - PASSED")
58
-
59
-
60
- def test_user_prompt_submit_schema():
61
- """Test 4: UserPromptSubmit special schema"""
62
- result = HookResult(context_files=["tests/", "docs/"])
63
- output = result.to_user_prompt_submit_dict()
64
-
65
- assert "hookSpecificOutput" in output
66
- assert output["hookSpecificOutput"]["hookEventName"] == "UserPromptSubmit"
67
- assert "additionalContext" in output["hookSpecificOutput"]
68
- assert "📎 Context: tests/" in output["hookSpecificOutput"]["additionalContext"]
69
- print("✅ Test 4: UserPromptSubmit schema - PASSED")
70
-
71
-
72
- def test_permission_decision():
73
- """Test 5: permissionDecision field"""
74
- result = HookResult(permission_decision="deny")
75
- output = result.to_dict()
76
-
77
- assert output.get("permissionDecision") == "deny"
78
- assert "continue" in output # continue should still be present
79
- print("✅ Test 5: permissionDecision - PASSED")
80
-
81
-
82
- def test_session_start_typical_output():
83
- """Test 6: Typical SessionStart output"""
84
- result = HookResult(
85
- continue_execution=True,
86
- system_message="🚀 MoAI-ADK Session Started\n Language: python\n Branch: develop"
87
- )
88
- output = result.to_dict()
89
-
90
- # Validate schema
91
- assert "continue" in output or "decision" in output, "Missing continue or decision"
92
- assert output.get("systemMessage", "").startswith("🚀 MoAI-ADK")
93
-
94
- # Ensure internal fields are NOT in output
95
- assert "context_files" not in output, "Internal field context_files leaked to output"
96
- assert "suggestions" not in output, "Internal field suggestions leaked to output"
97
- assert "exit_code" not in output, "Internal field exit_code leaked to output"
98
-
99
- print("✅ Test 6: SessionStart typical output - PASSED")
100
-
101
-
102
- def test_json_serializable():
103
- """Test 7: Output is JSON serializable"""
104
- result = HookResult(
105
- system_message="Test",
106
- decision="approve",
107
- reason="Valid operation"
108
- )
109
- output = result.to_dict()
110
-
111
- try:
112
- json_str = json.dumps(output)
113
- parsed = json.loads(json_str)
114
- assert parsed == output
115
- print("✅ Test 7: JSON serializable - PASSED")
116
- except Exception as e:
117
- print(f"❌ Test 7: JSON serialization FAILED: {e}")
118
- sys.exit(1)
119
-
120
-
121
- def test_user_prompt_submit_with_system_message():
122
- """Test 8: UserPromptSubmit with both context and system message"""
123
- result = HookResult(
124
- context_files=["src/"],
125
- system_message="Loading context..."
126
- )
127
- output = result.to_user_prompt_submit_dict()
128
-
129
- assert "hookSpecificOutput" in output
130
- assert "Loading context..." in output["hookSpecificOutput"]["additionalContext"]
131
- assert "📎 Context: src/" in output["hookSpecificOutput"]["additionalContext"]
132
- print("✅ Test 8: UserPromptSubmit with system_message - PASSED")
133
-
134
-
135
- def main():
136
- """Run all tests"""
137
- print("\n" + "="*60)
138
- print("🧪 Claude Code Hook Output Validation Tests")
139
- print("="*60 + "\n")
140
-
141
- tests = [
142
- test_basic_output,
143
- test_system_message_top_level,
144
- test_decision_with_reason,
145
- test_user_prompt_submit_schema,
146
- test_permission_decision,
147
- test_session_start_typical_output,
148
- test_json_serializable,
149
- test_user_prompt_submit_with_system_message,
150
- ]
151
-
152
- failed = 0
153
- for test in tests:
154
- try:
155
- test()
156
- except AssertionError as e:
157
- print(f"❌ {test.__name__}: FAILED - {e}")
158
- failed += 1
159
- except Exception as e:
160
- print(f"❌ {test.__name__}: ERROR - {e}")
161
- failed += 1
162
-
163
- print("\n" + "="*60)
164
- if failed == 0:
165
- print(f"✅ ALL {len(tests)} TESTS PASSED")
166
- print("="*60 + "\n")
167
- sys.exit(0)
168
- else:
169
- print(f"❌ {failed}/{len(tests)} TESTS FAILED")
170
- print("="*60 + "\n")
171
- sys.exit(1)
172
-
173
-
174
- if __name__ == "__main__":
175
- main()