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.
- moai_adk/cli/commands/init.py +14 -2
- moai_adk/cli/commands/update.py +229 -60
- moai_adk/core/config/migration.py +1 -1
- moai_adk/core/issue_creator.py +313 -0
- moai_adk/core/project/detector.py +201 -12
- moai_adk/core/project/initializer.py +62 -1
- moai_adk/core/project/phase_executor.py +48 -6
- moai_adk/core/tags/__init__.py +86 -0
- moai_adk/core/tags/ci_validator.py +463 -0
- moai_adk/core/tags/cli.py +283 -0
- moai_adk/core/tags/generator.py +109 -0
- moai_adk/core/tags/inserter.py +99 -0
- moai_adk/core/tags/mapper.py +126 -0
- moai_adk/core/tags/parser.py +76 -0
- moai_adk/core/tags/pre_commit_validator.py +393 -0
- moai_adk/core/tags/reporter.py +956 -0
- moai_adk/core/tags/tags.py +149 -0
- moai_adk/core/tags/validator.py +897 -0
- moai_adk/core/template_engine.py +268 -0
- moai_adk/templates/.claude/agents/alfred/backend-expert.md +319 -0
- moai_adk/templates/.claude/agents/alfred/cc-manager.md +25 -2
- moai_adk/templates/.claude/agents/alfred/debug-helper.md +24 -12
- moai_adk/templates/.claude/agents/alfred/devops-expert.md +464 -0
- moai_adk/templates/.claude/agents/alfred/doc-syncer.md +20 -13
- moai_adk/templates/.claude/agents/alfred/frontend-expert.md +357 -0
- moai_adk/templates/.claude/agents/alfred/git-manager.md +47 -16
- moai_adk/templates/.claude/agents/alfred/implementation-planner.md +95 -15
- moai_adk/templates/.claude/agents/alfred/project-manager.md +78 -12
- moai_adk/templates/.claude/agents/alfred/quality-gate.md +28 -5
- moai_adk/templates/.claude/agents/alfred/skill-factory.md +30 -2
- moai_adk/templates/.claude/agents/alfred/spec-builder.md +133 -13
- moai_adk/templates/.claude/agents/alfred/tag-agent.md +104 -8
- moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +133 -16
- moai_adk/templates/.claude/agents/alfred/trust-checker.md +27 -4
- moai_adk/templates/.claude/agents/alfred/ui-ux-expert.md +571 -0
- moai_adk/templates/.claude/commands/alfred/0-project.md +466 -125
- moai_adk/templates/.claude/commands/alfred/1-plan.md +208 -71
- moai_adk/templates/.claude/commands/alfred/2-run.md +276 -55
- moai_adk/templates/.claude/commands/alfred/3-sync.md +439 -53
- moai_adk/templates/.claude/commands/alfred/9-feedback.md +149 -0
- moai_adk/templates/.claude/hooks/alfred/core/project.py +361 -29
- moai_adk/templates/.claude/hooks/alfred/core/timeout.py +136 -0
- moai_adk/templates/.claude/hooks/alfred/core/ttl_cache.py +108 -0
- moai_adk/templates/.claude/hooks/alfred/core/version_cache.py +198 -0
- moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +14 -6
- moai_adk/templates/.claude/hooks/alfred/post_tool__log_changes.py +94 -0
- moai_adk/templates/.claude/hooks/alfred/pre_tool__auto_checkpoint.py +100 -0
- moai_adk/templates/.claude/hooks/alfred/session_end__cleanup.py +94 -0
- moai_adk/templates/.claude/hooks/alfred/session_start__show_project_info.py +94 -0
- moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/__init__.py +2 -2
- moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/checkpoint.py +3 -3
- moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/context.py +5 -5
- moai_adk/templates/.claude/hooks/alfred/shared/core/project.py +749 -0
- moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/tags.py +55 -23
- moai_adk/templates/.claude/hooks/alfred/shared/core/version_cache.py +198 -0
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/__init__.py +21 -0
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/notification.py +154 -0
- moai_adk/templates/.claude/hooks/alfred/{handlers → shared/handlers}/session.py +28 -15
- moai_adk/templates/.claude/hooks/alfred/{handlers → shared/handlers}/tool.py +3 -6
- moai_adk/templates/.claude/hooks/alfred/{handlers → shared/handlers}/user.py +19 -0
- moai_adk/templates/.claude/hooks/alfred/user_prompt__jit_load_docs.py +112 -0
- moai_adk/templates/.claude/hooks/alfred/utils/__init__.py +1 -0
- moai_adk/templates/.claude/hooks/alfred/utils/timeout.py +161 -0
- moai_adk/templates/.claude/settings.json +5 -5
- moai_adk/templates/.claude/skills/moai-alfred-agent-guide/SKILL.md +70 -0
- moai_adk/templates/.claude/skills/moai-alfred-agent-guide/examples.md +62 -0
- moai_adk/templates/{.moai/memory/CLAUDE-AGENTS-GUIDE.md → .claude/skills/moai-alfred-agent-guide/reference.md} +34 -0
- moai_adk/templates/.claude/skills/moai-alfred-config-schema/SKILL.md +56 -0
- moai_adk/templates/.claude/skills/moai-alfred-config-schema/examples.md +28 -0
- moai_adk/templates/.claude/skills/moai-alfred-context-budget/SKILL.md +62 -0
- moai_adk/templates/.claude/skills/moai-alfred-context-budget/examples.md +28 -0
- moai_adk/templates/.claude/skills/moai-alfred-context-budget/reference.md +405 -0
- moai_adk/templates/.claude/skills/moai-alfred-dev-guide/SKILL.md +51 -0
- moai_adk/templates/.claude/skills/moai-alfred-dev-guide/examples.md +355 -0
- moai_adk/templates/.claude/skills/moai-alfred-dev-guide/reference.md +239 -0
- moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/SKILL.md +323 -0
- moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/examples.md +286 -0
- moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/reference.md +126 -0
- moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/SKILL.md +74 -0
- moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/examples.md +4 -0
- moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/reference.md +269 -0
- moai_adk/templates/.claude/skills/moai-alfred-issue-labels/SKILL.md +19 -0
- moai_adk/templates/.claude/skills/moai-alfred-issue-labels/examples.md +4 -0
- moai_adk/templates/.claude/skills/moai-alfred-issue-labels/reference.md +150 -0
- moai_adk/templates/.claude/skills/moai-alfred-persona-roles/SKILL.md +198 -0
- moai_adk/templates/.claude/skills/moai-alfred-persona-roles/examples.md +431 -0
- moai_adk/templates/.claude/skills/moai-alfred-persona-roles/reference.md +141 -0
- moai_adk/templates/.claude/skills/moai-alfred-practices/SKILL.md +89 -0
- moai_adk/templates/.claude/skills/moai-alfred-practices/examples.md +122 -0
- moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/SKILL.md +508 -0
- moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/examples.md +481 -0
- moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/reference.md +100 -0
- moai_adk/templates/.claude/skills/moai-alfred-reporting/SKILL.md +273 -0
- moai_adk/templates/.claude/skills/moai-alfred-rules/SKILL.md +77 -0
- moai_adk/templates/.claude/skills/moai-alfred-rules/examples.md +265 -0
- moai_adk/templates/.claude/skills/moai-alfred-session-state/SKILL.md +19 -0
- moai_adk/templates/.claude/skills/moai-alfred-session-state/examples.md +4 -0
- moai_adk/templates/.claude/skills/moai-alfred-session-state/reference.md +84 -0
- moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/README.md +137 -0
- moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/SKILL.md +219 -0
- moai_adk/templates/.claude/skills/{moai-spec-authoring → moai-alfred-spec-authoring}/examples/validate-spec.sh +3 -3
- moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/examples.md +541 -0
- moai_adk/templates/.claude/skills/moai-alfred-spec-authoring/reference.md +622 -0
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/SKILL.md +115 -0
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/examples.md +4 -0
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/reference.md +348 -0
- moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/SKILL.md +19 -0
- moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/examples.md +4 -0
- moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/reference.md +211 -0
- moai_adk/templates/.claude/skills/moai-alfred-workflow/SKILL.md +288 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/SKILL.md +19 -0
- moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/examples.md +4 -0
- moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/SKILL.md +3 -3
- moai_adk/templates/.claude/skills/moai-design-systems/SKILL.md +802 -0
- moai_adk/templates/.claude/skills/moai-design-systems/examples.md +1238 -0
- moai_adk/templates/.claude/skills/moai-design-systems/reference.md +673 -0
- moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +17 -13
- moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +9 -6
- moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +15 -12
- moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +14 -12
- moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +14 -11
- moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +10 -8
- moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +15 -12
- moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +13 -11
- moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +16 -10
- moai_adk/templates/.claude/skills/moai-project-documentation.md +622 -0
- moai_adk/templates/.git-hooks/pre-push +143 -0
- moai_adk/templates/.github/workflows/c-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/cpp-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/csharp-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/dart-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/go-tag-validation.yml +130 -0
- moai_adk/templates/.github/workflows/java-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/javascript-tag-validation.yml +135 -0
- moai_adk/templates/.github/workflows/kotlin-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/moai-gitflow.yml +166 -3
- moai_adk/templates/.github/workflows/moai-release-create.yml +100 -0
- moai_adk/templates/.github/workflows/moai-release-pipeline.yml +188 -0
- moai_adk/templates/.github/workflows/php-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/python-tag-validation.yml +118 -0
- moai_adk/templates/.github/workflows/release.yml +118 -0
- moai_adk/templates/.github/workflows/ruby-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/rust-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/shell-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/spec-issue-sync.yml +206 -35
- moai_adk/templates/.github/workflows/swift-tag-validation.yml +11 -0
- moai_adk/templates/.github/workflows/tag-report.yml +269 -0
- moai_adk/templates/.github/workflows/tag-validation.yml +186 -0
- moai_adk/templates/.github/workflows/typescript-tag-validation.yml +154 -0
- moai_adk/templates/.moai/config.json +21 -2
- moai_adk/templates/CLAUDE.md +972 -78
- moai_adk/templates/workflows/go-tag-validation.yml +30 -0
- moai_adk/templates/workflows/javascript-tag-validation.yml +41 -0
- moai_adk/templates/workflows/python-tag-validation.yml +42 -0
- moai_adk/templates/workflows/typescript-tag-validation.yml +31 -0
- moai_adk/utils/banner.py +5 -5
- {moai_adk-0.8.0.dist-info → moai_adk-0.15.0.dist-info}/METADATA +1518 -161
- {moai_adk-0.8.0.dist-info → moai_adk-0.15.0.dist-info}/RECORD +183 -100
- moai_adk/templates/.claude/hooks/alfred/HOOK_SCHEMA_VALIDATION.md +0 -313
- moai_adk/templates/.claude/hooks/alfred/README.md +0 -230
- moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +0 -174
- moai_adk/templates/.claude/hooks/alfred/handlers/notification.py +0 -25
- moai_adk/templates/.claude/hooks/alfred/test_hook_output.py +0 -175
- moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +0 -640
- moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +0 -696
- moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +0 -474
- moai_adk/templates/.claude/skills/moai-spec-authoring/README.md +0 -137
- moai_adk/templates/.claude/skills/moai-spec-authoring/SKILL.md +0 -218
- moai_adk/templates/.claude/skills/moai-spec-authoring/examples.md +0 -541
- moai_adk/templates/.claude/skills/moai-spec-authoring/reference.md +0 -622
- moai_adk/templates/.github/ISSUE_TEMPLATE/spec.yml +0 -176
- moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +0 -69
- moai_adk/templates/.moai/memory/DEVELOPMENT-GUIDE.md +0 -344
- moai_adk/templates/.moai/memory/GITFLOW-PROTECTION-POLICY.md +0 -220
- moai_adk/templates/.moai/memory/SPEC-METADATA.md +0 -356
- moai_adk/templates/.moai/memory/config-schema.md +0 -444
- moai_adk/templates/.moai/memory/gitflow-protection-policy.md +0 -220
- moai_adk/templates/.moai/memory/spec-metadata.md +0 -356
- moai_adk/templates/.moai/project/product.md +0 -161
- moai_adk/templates/.moai/project/structure.md +0 -156
- moai_adk/templates/.moai/project/tech.md +0 -227
- moai_adk/templates/__init__.py +0 -2
- /moai_adk/templates/{.moai/memory/CONFIG-SCHEMA.md → .claude/skills/moai-alfred-config-schema/reference.md} +0 -0
- /moai_adk/templates/{.moai/memory/CLAUDE-PRACTICES.md → .claude/skills/moai-alfred-practices/reference.md} +0 -0
- /moai_adk/templates/{.moai/memory/CLAUDE-RULES.md → .claude/skills/moai-alfred-rules/reference.md} +0 -0
- /moai_adk/templates/{.moai/memory/SKILLS-DESCRIPTION-POLICY.md → .claude/skills/moai-cc-skill-descriptions/reference.md} +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/CHECKLIST.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/EXAMPLES.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/INTERACTIVE-DISCOVERY.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/METADATA.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/PARALLEL-ANALYSIS-REPORT.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/PYTHON-VERSION-MATRIX.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/SKILL-FACTORY-WORKFLOW.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/SKILL-UPDATE-ADVISOR.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/STEP-BY-STEP-GUIDE.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/STRUCTURE.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/WEB-RESEARCH.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/reference.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/scripts/generate-structure.sh +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/scripts/validate-skill.sh +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/templates/SKILL_TEMPLATE.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/templates/examples-template.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/templates/reference-template.md +0 -0
- /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/templates/scripts-template.sh +0 -0
- {moai_adk-0.8.0.dist-info → moai_adk-0.15.0.dist-info}/WHEEL +0 -0
- {moai_adk-0.8.0.dist-info → moai_adk-0.15.0.dist-info}/entry_points.txt +0 -0
- {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()
|