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,313 +0,0 @@
|
|
|
1
|
-
# Hook JSON 스키마 검증 및 해결 보고서
|
|
2
|
-
|
|
3
|
-
**작성일**: 2025-10-23
|
|
4
|
-
**태그**: @CODE:HOOKS-REFACTOR-001
|
|
5
|
-
**상태**: ✅ 해결 완료
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## 📋 문제 요약
|
|
10
|
-
|
|
11
|
-
### 초기 오류
|
|
12
|
-
```
|
|
13
|
-
SessionStart:startup hook error: JSON validation failed: Hook JSON output validation failed
|
|
14
|
-
Expected schema: { ... "systemMessage": ... }
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
### 근본 원인
|
|
18
|
-
Claude Code Hook 스키마에서 `systemMessage`가 **최상위 필드**여야 하지만, 일부 구현에서는 이를 `hookSpecificOutput` 내부에 중첩시키고 있었습니다.
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## 🔍 분석 결과
|
|
23
|
-
|
|
24
|
-
### Claude Code 공식 Hook 스키마
|
|
25
|
-
|
|
26
|
-
#### 1. 일반 Hook 이벤트 (SessionStart, PreToolUse, PostToolUse, SessionEnd 등)
|
|
27
|
-
|
|
28
|
-
```json
|
|
29
|
-
{
|
|
30
|
-
"continue": true|false, // ✅ 기본 필드
|
|
31
|
-
"systemMessage": "string", // ✅ 최상위 필드 (NOT in hookSpecificOutput)
|
|
32
|
-
"decision": "approve"|"block"|undefined, // ✅ 선택적
|
|
33
|
-
"reason": "string", // ✅ 선택적
|
|
34
|
-
"permissionDecision": "allow"|"deny"|"ask"|undefined, // ✅ 선택적
|
|
35
|
-
"suppressOutput": true|false // ✅ 선택적
|
|
36
|
-
}
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
#### 2. UserPromptSubmit 전용 스키마
|
|
40
|
-
|
|
41
|
-
```json
|
|
42
|
-
{
|
|
43
|
-
"continue": true,
|
|
44
|
-
"hookSpecificOutput": { // ✅ UserPromptSubmit에만 사용
|
|
45
|
-
"hookEventName": "UserPromptSubmit",
|
|
46
|
-
"additionalContext": "string"
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### 핵심 규칙
|
|
52
|
-
|
|
53
|
-
| 규칙 | 설명 |
|
|
54
|
-
|------|------|
|
|
55
|
-
| **systemMessage 위치** | 최상위 필드 (`output["systemMessage"]`) |
|
|
56
|
-
| **hookSpecificOutput** | UserPromptSubmit 전용 |
|
|
57
|
-
| **내부 필드** | `context_files`, `suggestions`, `exit_code`는 Python 로직용 (JSON 출력 제외) |
|
|
58
|
-
| **JSON 직렬화** | 모든 필드는 JSON 직렬화 가능해야 함 |
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## ✅ 해결 방안
|
|
63
|
-
|
|
64
|
-
### 1. 코드 수정
|
|
65
|
-
|
|
66
|
-
**파일**: `.claude/hooks/alfred/core/__init__.py`
|
|
67
|
-
|
|
68
|
-
#### `to_dict()` 메서드 (라인 63-118)
|
|
69
|
-
```python
|
|
70
|
-
def to_dict(self) -> dict[str, Any]:
|
|
71
|
-
"""Claude Code 표준 Hook 출력 스키마로 변환"""
|
|
72
|
-
output: dict[str, Any] = {}
|
|
73
|
-
|
|
74
|
-
# 1. decision 또는 continue 추가
|
|
75
|
-
if self.decision:
|
|
76
|
-
output["decision"] = self.decision
|
|
77
|
-
else:
|
|
78
|
-
output["continue"] = self.continue_execution
|
|
79
|
-
|
|
80
|
-
# 2. reason 추가 (decision 또는 permissionDecision과 함께)
|
|
81
|
-
if self.reason:
|
|
82
|
-
output["reason"] = self.reason
|
|
83
|
-
|
|
84
|
-
# 3. suppressOutput 추가 (True인 경우만)
|
|
85
|
-
if self.suppress_output:
|
|
86
|
-
output["suppressOutput"] = True
|
|
87
|
-
|
|
88
|
-
# 4. permissionDecision 추가
|
|
89
|
-
if self.permission_decision:
|
|
90
|
-
output["permissionDecision"] = self.permission_decision
|
|
91
|
-
|
|
92
|
-
# 5. ⭐ systemMessage를 최상위 필드로 추가 (NOT in hookSpecificOutput)
|
|
93
|
-
if self.system_message:
|
|
94
|
-
output["systemMessage"] = self.system_message
|
|
95
|
-
|
|
96
|
-
# 🚫 내부 필드는 JSON 출력에서 제외
|
|
97
|
-
# - context_files: JIT 문맥 로드 (내부용)
|
|
98
|
-
# - suggestions: 제안 (내부용)
|
|
99
|
-
# - exit_code: 진단 (내부용)
|
|
100
|
-
|
|
101
|
-
return output
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
#### `to_user_prompt_submit_dict()` 메서드 (라인 120-160)
|
|
105
|
-
```python
|
|
106
|
-
def to_user_prompt_submit_dict(self) -> dict[str, Any]:
|
|
107
|
-
"""UserPromptSubmit Hook 전용 스키마"""
|
|
108
|
-
if self.context_files:
|
|
109
|
-
context_str = "\n".join([f"📎 Context: {f}" for f in self.context_files])
|
|
110
|
-
else:
|
|
111
|
-
context_str = ""
|
|
112
|
-
|
|
113
|
-
if self.system_message:
|
|
114
|
-
if context_str:
|
|
115
|
-
context_str = f"{self.system_message}\n\n{context_str}"
|
|
116
|
-
else:
|
|
117
|
-
context_str = self.system_message
|
|
118
|
-
|
|
119
|
-
return {
|
|
120
|
-
"continue": self.continue_execution,
|
|
121
|
-
"hookSpecificOutput": {
|
|
122
|
-
"hookEventName": "UserPromptSubmit",
|
|
123
|
-
"additionalContext": context_str
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### 2. 설정 검증
|
|
129
|
-
|
|
130
|
-
**파일**: `.claude/settings.json` (라인 8-60)
|
|
131
|
-
|
|
132
|
-
```json
|
|
133
|
-
{
|
|
134
|
-
"hooks": {
|
|
135
|
-
"SessionStart": [
|
|
136
|
-
{
|
|
137
|
-
"hooks": [
|
|
138
|
-
{
|
|
139
|
-
"command": "uv run \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/alfred/alfred_hooks.py SessionStart",
|
|
140
|
-
"type": "command"
|
|
141
|
-
}
|
|
142
|
-
]
|
|
143
|
-
}
|
|
144
|
-
],
|
|
145
|
-
"UserPromptSubmit": [
|
|
146
|
-
{
|
|
147
|
-
"hooks": [
|
|
148
|
-
{
|
|
149
|
-
"command": "uv run \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/alfred/alfred_hooks.py UserPromptSubmit",
|
|
150
|
-
"type": "command"
|
|
151
|
-
}
|
|
152
|
-
]
|
|
153
|
-
}
|
|
154
|
-
]
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
---
|
|
160
|
-
|
|
161
|
-
## 🧪 검증 결과
|
|
162
|
-
|
|
163
|
-
### 1. 자동 테스트 (8/8 통과)
|
|
164
|
-
|
|
165
|
-
**파일**: `.claude/hooks/alfred/test_hook_output.py`
|
|
166
|
-
|
|
167
|
-
```bash
|
|
168
|
-
$ cd .claude/hooks/alfred && python test_hook_output.py
|
|
169
|
-
|
|
170
|
-
✅ Test 1: Basic output - PASSED
|
|
171
|
-
✅ Test 2: systemMessage (top-level) - PASSED
|
|
172
|
-
✅ Test 3: decision + reason - PASSED
|
|
173
|
-
✅ Test 4: UserPromptSubmit schema - PASSED
|
|
174
|
-
✅ Test 5: permissionDecision - PASSED
|
|
175
|
-
✅ Test 6: SessionStart typical output - PASSED
|
|
176
|
-
✅ Test 7: JSON serializable - PASSED
|
|
177
|
-
✅ Test 8: UserPromptSubmit with system_message - PASSED
|
|
178
|
-
|
|
179
|
-
✅ ALL 8 TESTS PASSED
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### 2. 실제 Hook 실행 검증
|
|
183
|
-
|
|
184
|
-
#### SessionStart (compact phase)
|
|
185
|
-
```bash
|
|
186
|
-
$ echo '{"cwd": ".", "phase": "compact"}' | uv run .claude/hooks/alfred/alfred_hooks.py SessionStart
|
|
187
|
-
|
|
188
|
-
{
|
|
189
|
-
"continue": true,
|
|
190
|
-
"systemMessage": "🚀 MoAI-ADK Session Started\n Language: python\n Branch: develop (d905363)\n Changes: 215\n SPEC Progress: 30/31 (96%)\n Checkpoints: 2 available\n - delete-20251022-134841\n - critical-file-20251019-230247\n Restore: /alfred:0-project restore"
|
|
191
|
-
}
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
✅ **검증**:
|
|
195
|
-
- `systemMessage`가 최상위 필드
|
|
196
|
-
- JSON 유효성 확인
|
|
197
|
-
- `hookSpecificOutput` 없음 (올바름)
|
|
198
|
-
|
|
199
|
-
#### SessionStart (clear phase)
|
|
200
|
-
```bash
|
|
201
|
-
$ echo '{"cwd": ".", "phase": "clear"}' | uv run .claude/hooks/alfred/alfred_hooks.py SessionStart
|
|
202
|
-
|
|
203
|
-
{"continue": true}
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
✅ **검증**:
|
|
207
|
-
- 최소 스키마 (continue만)
|
|
208
|
-
- clear 단계에서 중복 출력 방지
|
|
209
|
-
|
|
210
|
-
#### UserPromptSubmit
|
|
211
|
-
```bash
|
|
212
|
-
$ echo '{"cwd": ".", "userPrompt": "test"}' | uv run .claude/hooks/alfred/alfred_hooks.py UserPromptSubmit
|
|
213
|
-
|
|
214
|
-
{
|
|
215
|
-
"continue": true,
|
|
216
|
-
"hookSpecificOutput": {
|
|
217
|
-
"hookEventName": "UserPromptSubmit",
|
|
218
|
-
"additionalContext": "📎 Loaded 1 context file(s)\n\n📎 Context: tests/"
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
✅ **검증**:
|
|
224
|
-
- UserPromptSubmit 특수 스키마
|
|
225
|
-
- `hookSpecificOutput` 사용 (올바름)
|
|
226
|
-
|
|
227
|
-
---
|
|
228
|
-
|
|
229
|
-
## 📚 각 Hook 이벤트별 스키마 가이드
|
|
230
|
-
|
|
231
|
-
| 이벤트 | 최소 JSON | 예시 | 차단 가능 |
|
|
232
|
-
|--------|-----------|------|----------|
|
|
233
|
-
| **SessionStart** | `{"continue": true}` | 프로젝트 상태 표시 | ❌ No |
|
|
234
|
-
| **SessionEnd** | `{"continue": true}` | 정리 작업 | ❌ No |
|
|
235
|
-
| **PreToolUse** | `{"continue": true}` | 도구 실행 승인/차단 | ✅ Yes |
|
|
236
|
-
| **PostToolUse** | `{"continue": true}` | 도구 실행 후 피드백 | ❌ No* |
|
|
237
|
-
| **UserPromptSubmit** | 특수 스키마 | 프롬프트 문맥 추가 | ✅ Yes |
|
|
238
|
-
| **Notification** | `{"continue": true}` | 알림 처리 | ❌ No |
|
|
239
|
-
| **Stop** | `{"continue": true}` | 종료 차단 | ✅ Yes |
|
|
240
|
-
| **SubagentStop** | `{"continue": true}` | 서브에이전트 종료 차단 | ✅ Yes |
|
|
241
|
-
|
|
242
|
-
*: PostToolUse는 도구가 이미 실행되었으므로 차단 불가능하지만, 피드백 제공 가능
|
|
243
|
-
|
|
244
|
-
---
|
|
245
|
-
|
|
246
|
-
## 🔧 구현 세부사항
|
|
247
|
-
|
|
248
|
-
### HookResult 클래스 필드
|
|
249
|
-
|
|
250
|
-
```python
|
|
251
|
-
@dataclass
|
|
252
|
-
class HookResult:
|
|
253
|
-
# ✅ Claude Code 표준 필드 (JSON에 포함)
|
|
254
|
-
continue_execution: bool = True
|
|
255
|
-
suppress_output: bool = False
|
|
256
|
-
decision: Literal["approve", "block"] | None = None
|
|
257
|
-
reason: str | None = None
|
|
258
|
-
permission_decision: Literal["allow", "deny", "ask"] | None = None
|
|
259
|
-
system_message: str | None = None # ⭐ TOP-LEVEL in JSON
|
|
260
|
-
|
|
261
|
-
# 🚫 내부 필드 (JSON 출력 제외)
|
|
262
|
-
context_files: list[str] = field(default_factory=list)
|
|
263
|
-
suggestions: list[str] = field(default_factory=list)
|
|
264
|
-
exit_code: int = 0
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
### 메서드별 역할
|
|
268
|
-
|
|
269
|
-
| 메서드 | 사용 사건 | 반환 스키마 |
|
|
270
|
-
|--------|---------|----------|
|
|
271
|
-
| `to_dict()` | 일반 Hook 이벤트 | 표준 Claude Code 스키마 |
|
|
272
|
-
| `to_user_prompt_submit_dict()` | UserPromptSubmit 이벤트 | 특수 스키마 + hookSpecificOutput |
|
|
273
|
-
|
|
274
|
-
---
|
|
275
|
-
|
|
276
|
-
## 📖 참고 문서
|
|
277
|
-
|
|
278
|
-
### 공식 Claude Code 문서
|
|
279
|
-
- **Claude Code Hooks**: https://docs.claude.com/en/docs/claude-code/hooks
|
|
280
|
-
- **Hook Output Schema**: https://docs.claude.com/en/docs/claude-code/hooks#output-schema
|
|
281
|
-
|
|
282
|
-
### Context7 참고 자료
|
|
283
|
-
- **Claude Code Hooks Mastery** (Trust Score: 8.3, 100+ 코드 스니펫)
|
|
284
|
-
- **Claude Code Templates** (Trust Score: 10)
|
|
285
|
-
|
|
286
|
-
### 프로젝트 문서
|
|
287
|
-
- **CLAUDE.md**: `Error Message Standard (Shared)` 섹션
|
|
288
|
-
- **Hook 구현**: `.claude/hooks/alfred/handlers/` 디렉토리
|
|
289
|
-
|
|
290
|
-
---
|
|
291
|
-
|
|
292
|
-
## 🎯 결론
|
|
293
|
-
|
|
294
|
-
✅ **상태**: 해결 완료
|
|
295
|
-
✅ **검증**: 8/8 자동 테스트 통과
|
|
296
|
-
✅ **실제 실행**: 모든 Hook 이벤트 정상 작동
|
|
297
|
-
|
|
298
|
-
### 핵심 수정사항
|
|
299
|
-
1. `systemMessage`를 최상위 필드로 이동 (NOT in hookSpecificOutput)
|
|
300
|
-
2. UserPromptSubmit 특수 스키마 분리
|
|
301
|
-
3. 내부 필드 JSON 출력 제외
|
|
302
|
-
4. 모든 Hook 이벤트 스키마 정규화
|
|
303
|
-
|
|
304
|
-
### 다음 단계
|
|
305
|
-
- ✅ Hook 스키마 검증 자동화
|
|
306
|
-
- ✅ 테스트 스크립트 작성
|
|
307
|
-
- ⏭️ 현재 상태 유지 및 모니터링
|
|
308
|
-
|
|
309
|
-
---
|
|
310
|
-
|
|
311
|
-
**검증 완료**: 2025-10-23
|
|
312
|
-
**담당자**: @agent-cc-manager
|
|
313
|
-
**참고**: @CODE:HOOKS-REFACTOR-001
|
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
# Alfred Hooks System
|
|
2
|
-
|
|
3
|
-
**Event-Driven Context Management for MoAI-ADK**
|
|
4
|
-
|
|
5
|
-
Alfred Hooks integrates with Claude Code's event system to automatically manage project context, create checkpoints before risky operations, and provide just-in-time (JIT) document loading.
|
|
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
|
-
├── tool.py # PreToolUse, PostToolUse
|
|
27
|
-
└── notification.py # Notification, Stop, SubagentStop
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Design Principles
|
|
31
|
-
|
|
32
|
-
- **Single Responsibility**: Each module has one clear responsibility
|
|
33
|
-
- **Separation of Concerns**: core (business logic) vs handlers (event processing)
|
|
34
|
-
- **CODE-FIRST**: Scan code directly without intermediate cache (mtime Based invalidation)
|
|
35
|
-
- **Context Engineering**: Minimize initial context burden with JIT Retrieval
|
|
36
|
-
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
## 🎯 Core Modules
|
|
40
|
-
|
|
41
|
-
### `core/project.py` (284 LOC)
|
|
42
|
-
|
|
43
|
-
**Project metadata and language detection**
|
|
44
|
-
|
|
45
|
-
```python
|
|
46
|
-
# Public API
|
|
47
|
-
detect_language(cwd: str) -> str
|
|
48
|
-
get_project_language(cwd: str) -> str
|
|
49
|
-
get_git_info(cwd: str) -> dict[str, Any]
|
|
50
|
-
count_specs(cwd: str) -> dict[str, int]
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
**Features**:
|
|
54
|
-
- Automatic detection of 20 languages (Python, TypeScript, Java, Go, Rust, etc.)
|
|
55
|
-
- `.moai/config.json` First, fallback to auto-detection
|
|
56
|
-
- Check Git information (branch, commit, changes)
|
|
57
|
-
- SPEC progress calculation (total, completed, percentage)
|
|
58
|
-
|
|
59
|
-
### `core/context.py` (110 LOC)
|
|
60
|
-
|
|
61
|
-
**JIT Context Retrieval and Workflow Management**
|
|
62
|
-
|
|
63
|
-
```python
|
|
64
|
-
# Public API
|
|
65
|
-
get_jit_context(prompt: str, cwd: str) -> list[str]
|
|
66
|
-
save_phase_context(phase: str, data: Any, ttl: int = 600)
|
|
67
|
-
load_phase_context(phase: str, ttl: int = 600) -> Any | None
|
|
68
|
-
clear_workflow_context()
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
**Features**:
|
|
72
|
-
- Automatically recommend documents based on prompt analysis
|
|
73
|
-
- `/alfred:1-plan` → `spec-metadata.md`
|
|
74
|
-
- `/alfred:2-run` → `development-guide.md`
|
|
75
|
-
- Context caching for each workflow step (TTL 10 minutes)
|
|
76
|
-
- Compliance with Anthropic Context Engineering principles
|
|
77
|
-
|
|
78
|
-
### `core/checkpoint.py` (244 LOC)
|
|
79
|
-
|
|
80
|
-
**Event-Driven Checkpoint Automation**
|
|
81
|
-
|
|
82
|
-
```python
|
|
83
|
-
# Public API
|
|
84
|
-
detect_risky_operation(tool: str, args: dict, cwd: str) -> tuple[bool, str]
|
|
85
|
-
create_checkpoint(cwd: str, operation: str) -> str
|
|
86
|
-
log_checkpoint(cwd: str, branch: str, description: str)
|
|
87
|
-
list_checkpoints(cwd: str, max_count: int = 10) -> list[dict]
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
**Features**:
|
|
91
|
-
- Automatic detection of dangerous tasks:
|
|
92
|
-
- Bash: `rm -rf`, `git merge`, `git reset --hard`
|
|
93
|
-
- Edit/Write: `CLAUDE.md`, `config.json`
|
|
94
|
-
- MultiEdit: ≥10 files
|
|
95
|
-
- Automatic creation of Git checkpoint: `checkpoint/before-{operation}-{timestamp}`
|
|
96
|
-
- Checkpoint history management and recovery guide
|
|
97
|
-
|
|
98
|
-
### `core/tags.py` (244 LOC)
|
|
99
|
-
|
|
100
|
-
**CODE-FIRST TAG SYSTEM**
|
|
101
|
-
|
|
102
|
-
```python
|
|
103
|
-
# Public API
|
|
104
|
-
search_tags(pattern: str, scope: list[str], cache_ttl: int = 60) -> list[dict]
|
|
105
|
-
verify_tag_chain(tag_id: str) -> dict[str, Any]
|
|
106
|
-
find_all_tags_by_type(tag_type: str) -> dict[str, list[str]]
|
|
107
|
-
suggest_tag_reuse(keyword: str) -> list[str]
|
|
108
|
-
get_library_version(library: str, cache_ttl: int = 86400) -> str | None
|
|
109
|
-
set_library_version(library: str, version: str)
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
**Features**:
|
|
113
|
-
- ripgrep-based TAG search (parsing JSON output)
|
|
114
|
-
- mtime-based cache invalidation (CODE-FIRST guaranteed)
|
|
115
|
-
- TAG chain verification (@SPEC → @TEST → @CODE completeness check)
|
|
116
|
-
- Library version caching (TTL 24 hours)
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
## 🎬 Event Handlers
|
|
121
|
-
|
|
122
|
-
### `handlers/session.py`
|
|
123
|
-
|
|
124
|
-
**SessionStart, SessionEnd handlers**
|
|
125
|
-
|
|
126
|
-
- **SessionStart**: Display project information
|
|
127
|
-
- Language, Git status, SPEC progress, recent checkpoint
|
|
128
|
-
- Display directly to user with `systemMessage` field
|
|
129
|
-
- **SessionEnd**: Cleanup task (stub)
|
|
130
|
-
|
|
131
|
-
### `handlers/user.py`
|
|
132
|
-
|
|
133
|
-
**UserPromptSubmit Handler**
|
|
134
|
-
|
|
135
|
-
- Return list of JIT Context recommended documents
|
|
136
|
-
- Analyze user prompt patterns and load related documents
|
|
137
|
-
|
|
138
|
-
### `handlers/tool.py`
|
|
139
|
-
|
|
140
|
-
**PreToolUse, PostToolUse handlers**
|
|
141
|
-
|
|
142
|
-
- **PreToolUse**: Automatic checkpoint creation when dangerous operation is detected
|
|
143
|
-
- **PostToolUse**: Post-processing operation (stub)
|
|
144
|
-
|
|
145
|
-
### `handlers/notification.py`
|
|
146
|
-
|
|
147
|
-
**Notification, Stop, SubagentStop handlers**
|
|
148
|
-
|
|
149
|
-
- Basic implementation (stub, can be expanded in the future)
|
|
150
|
-
|
|
151
|
-
---
|
|
152
|
-
|
|
153
|
-
## 🧪 Testing
|
|
154
|
-
|
|
155
|
-
### Test Suite
|
|
156
|
-
|
|
157
|
-
```bash
|
|
158
|
-
# Run all tests
|
|
159
|
-
uv run pytest tests/unit/test_alfred_hooks_*.py -v --no-cov
|
|
160
|
-
|
|
161
|
-
# Run specific module tests
|
|
162
|
-
uv run pytest tests/unit/test_alfred_hooks_core_tags.py -v
|
|
163
|
-
uv run pytest tests/unit/test_alfred_hooks_core_context.py -v
|
|
164
|
-
uv run pytest tests/unit/test_alfred_hooks_core_project.py -v
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
### Test Coverage (18 tests)
|
|
168
|
-
|
|
169
|
-
- ✅ **tags.py**: 7 tests (cache, TAG verification, version management)
|
|
170
|
-
- ✅ **context.py**: 5 tests (JIT, workflow context)
|
|
171
|
-
- ✅ **project.py**: 6 tests (language detection, Git, SPEC count)
|
|
172
|
-
|
|
173
|
-
### Test Structure
|
|
174
|
-
|
|
175
|
-
```python
|
|
176
|
-
# Dynamic module loading for isolated testing
|
|
177
|
-
def _load_{module}_module(module_name: str):
|
|
178
|
-
repo_root = Path(__file__).resolve().parents[2]
|
|
179
|
-
hooks_dir = repo_root / ".claude" / "hooks" / "alfred"
|
|
180
|
-
sys.path.insert(0, str(hooks_dir))
|
|
181
|
-
|
|
182
|
-
module_path = hooks_dir / "core" / "{module}.py"
|
|
183
|
-
spec = importlib.util.spec_from_file_location(module_name, module_path)
|
|
184
|
-
# ...
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
## 🔄 Migration from moai_hooks.py
|
|
190
|
-
|
|
191
|
-
### Before (Monolithic)
|
|
192
|
-
|
|
193
|
-
- **1 file**: 1233 LOC
|
|
194
|
-
- **Issues**:
|
|
195
|
-
- All functions concentrated in one file
|
|
196
|
-
- Difficult to test, complex to maintain
|
|
197
|
-
- Unclear separation of responsibilities
|
|
198
|
-
|
|
199
|
-
### After (Modular)
|
|
200
|
-
|
|
201
|
-
- **9 files**: ≤284 LOC each
|
|
202
|
-
- **Benefits**:
|
|
203
|
-
- Clear separation of responsibilities (SRP)
|
|
204
|
-
- Independent module testing possible
|
|
205
|
-
- Easy to expand, easy to maintain
|
|
206
|
-
- Compliance with Context Engineering principles
|
|
207
|
-
|
|
208
|
-
### Breaking Changes
|
|
209
|
-
|
|
210
|
-
**None** - External APIs remain the same.
|
|
211
|
-
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
## 📚 References
|
|
215
|
-
|
|
216
|
-
### Internal Documents
|
|
217
|
-
|
|
218
|
-
- **CLAUDE.md**: MoAI-ADK User Guide
|
|
219
|
-
- **.moai/memory/development-guide.md**: SPEC-First TDD Workflow
|
|
220
|
-
- **.moai/memory/spec-metadata.md**: SPEC metadata standard
|
|
221
|
-
|
|
222
|
-
### External Resources
|
|
223
|
-
|
|
224
|
-
- [Claude Code Hooks Documentation](https://docs.claude.com/en/docs/claude-code)
|
|
225
|
-
- [Anthropic Context Engineering](https://docs.anthropic.com/claude/docs/context-engineering)
|
|
226
|
-
|
|
227
|
-
---
|
|
228
|
-
|
|
229
|
-
**Last Updated**: 2025-10-16
|
|
230
|
-
**Author**: @Alfred (MoAI-ADK SuperAgent)
|