moai-adk 0.3.13__py3-none-any.whl → 0.4.1__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/__init__.py +1 -1
- moai_adk/__main__.py +1 -1
- moai_adk/cli/commands/__init__.py +1 -1
- moai_adk/cli/commands/doctor.py +2 -2
- moai_adk/cli/commands/init.py +10 -5
- moai_adk/cli/commands/status.py +1 -1
- moai_adk/cli/commands/update.py +210 -8
- moai_adk/cli/prompts/init_prompts.py +15 -19
- moai_adk/core/__init__.py +1 -1
- moai_adk/core/diagnostics/slash_commands.py +1 -1
- moai_adk/core/git/branch.py +1 -1
- moai_adk/core/git/manager.py +1 -1
- moai_adk/core/project/backup_utils.py +1 -0
- moai_adk/core/project/phase_executor.py +3 -1
- moai_adk/core/project/validator.py +3 -2
- moai_adk/core/quality/__init__.py +1 -1
- moai_adk/core/quality/trust_checker.py +1 -1
- moai_adk/core/quality/validators/__init__.py +1 -1
- moai_adk/core/quality/validators/base_validator.py +1 -1
- moai_adk/core/template/__init__.py +1 -1
- moai_adk/core/template/backup.py +12 -3
- moai_adk/core/template/config.py +24 -0
- moai_adk/core/template/languages.py +1 -1
- moai_adk/core/template/merger.py +74 -4
- moai_adk/core/template/processor.py +62 -14
- moai_adk/templates/.claude/agents/alfred/cc-manager.md +765 -191
- moai_adk/templates/.claude/agents/alfred/debug-helper.md +116 -103
- moai_adk/templates/.claude/agents/alfred/doc-syncer.md +130 -116
- moai_adk/templates/.claude/agents/alfred/git-manager.md +186 -174
- moai_adk/templates/.claude/agents/alfred/implementation-planner.md +227 -213
- moai_adk/templates/.claude/agents/alfred/project-manager.md +205 -125
- moai_adk/templates/.claude/agents/alfred/quality-gate.md +224 -209
- moai_adk/templates/.claude/agents/alfred/spec-builder.md +174 -160
- moai_adk/templates/.claude/agents/alfred/tag-agent.md +151 -139
- moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +209 -196
- moai_adk/templates/.claude/agents/alfred/trust-checker.md +247 -233
- moai_adk/templates/.claude/commands/alfred/0-project.md +856 -355
- moai_adk/templates/.claude/commands/alfred/1-plan.md +572 -0
- moai_adk/templates/.claude/commands/alfred/2-run.md +470 -0
- moai_adk/templates/.claude/commands/alfred/3-sync.md +366 -356
- moai_adk/templates/.claude/hooks/alfred/README.md +52 -52
- moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +44 -48
- moai_adk/templates/.claude/hooks/alfred/core/__init__.py +17 -17
- moai_adk/templates/.claude/hooks/alfred/core/checkpoint.py +59 -59
- moai_adk/templates/.claude/hooks/alfred/core/context.py +19 -19
- moai_adk/templates/.claude/hooks/alfred/core/project.py +52 -52
- moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +1 -1
- moai_adk/templates/.claude/hooks/alfred/handlers/notification.py +4 -4
- moai_adk/templates/.claude/hooks/alfred/handlers/session.py +30 -51
- moai_adk/templates/.claude/hooks/alfred/handlers/tool.py +16 -17
- moai_adk/templates/.claude/hooks/alfred/handlers/user.py +11 -11
- moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +308 -307
- moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +297 -296
- moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +191 -190
- moai_adk/templates/.claude/skills/moai-alfred-code-reviewer/SKILL.md +112 -0
- moai_adk/templates/.claude/skills/moai-alfred-debugger-pro/SKILL.md +103 -0
- moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/SKILL.md +103 -0
- moai_adk/templates/.claude/skills/moai-alfred-git-workflow/SKILL.md +95 -0
- moai_adk/templates/.claude/skills/moai-alfred-language-detection/SKILL.md +99 -0
- moai_adk/templates/.claude/skills/moai-alfred-performance-optimizer/SKILL.md +105 -0
- moai_adk/templates/.claude/skills/moai-alfred-refactoring-coach/SKILL.md +97 -0
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/SKILL.md +97 -0
- moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/SKILL.md +90 -0
- moai_adk/templates/.claude/skills/moai-alfred-trust-validation/SKILL.md +99 -0
- moai_adk/templates/.claude/skills/moai-alfred-tui-survey/SKILL.md +87 -0
- moai_adk/templates/.claude/skills/moai-alfred-tui-survey/examples.md +62 -0
- moai_adk/templates/.claude/skills/moai-claude-code/SKILL.md +94 -0
- moai_adk/templates/.claude/skills/moai-claude-code/examples.md +513 -0
- moai_adk/templates/.claude/skills/moai-claude-code/reference.md +433 -0
- moai_adk/templates/.claude/skills/moai-claude-code/templates/agent-full.md +332 -0
- moai_adk/templates/.claude/skills/moai-claude-code/templates/command-full.md +384 -0
- moai_adk/templates/.claude/skills/moai-claude-code/templates/plugin-full.json +363 -0
- moai_adk/templates/.claude/skills/moai-claude-code/templates/settings-full.json +595 -0
- moai_adk/templates/.claude/skills/moai-claude-code/templates/skill-full.md +496 -0
- moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +99 -0
- moai_adk/templates/.claude/skills/moai-domain-cli-tool/SKILL.md +95 -0
- moai_adk/templates/.claude/skills/moai-domain-data-science/SKILL.md +98 -0
- moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +100 -0
- moai_adk/templates/.claude/skills/moai-domain-devops/SKILL.md +100 -0
- moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +99 -0
- moai_adk/templates/.claude/skills/moai-domain-ml/SKILL.md +99 -0
- moai_adk/templates/.claude/skills/moai-domain-mobile-app/SKILL.md +93 -0
- moai_adk/templates/.claude/skills/moai-domain-security/SKILL.md +105 -0
- moai_adk/templates/.claude/skills/moai-domain-web-api/SKILL.md +97 -0
- moai_adk/templates/.claude/skills/moai-essentials-debug/SKILL.md +102 -0
- moai_adk/templates/.claude/skills/moai-essentials-perf/SKILL.md +104 -0
- moai_adk/templates/.claude/skills/moai-essentials-refactor/SKILL.md +96 -0
- moai_adk/templates/.claude/skills/moai-essentials-review/SKILL.md +112 -0
- moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +98 -0
- moai_adk/templates/.claude/skills/moai-foundation-git/SKILL.md +90 -0
- moai_adk/templates/.claude/skills/moai-foundation-langs/SKILL.md +94 -0
- moai_adk/templates/.claude/skills/moai-foundation-specs/SKILL.md +93 -0
- moai_adk/templates/.claude/skills/moai-foundation-tags/SKILL.md +86 -0
- moai_adk/templates/.claude/skills/moai-foundation-trust/SKILL.md +86 -0
- moai_adk/templates/.claude/skills/moai-lang-c/SKILL.md +100 -0
- moai_adk/templates/.claude/skills/moai-lang-clojure/SKILL.md +100 -0
- moai_adk/templates/.claude/skills/moai-lang-cpp/SKILL.md +102 -0
- moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +100 -0
- moai_adk/templates/.claude/skills/moai-lang-dart/SKILL.md +98 -0
- moai_adk/templates/.claude/skills/moai-lang-elixir/SKILL.md +99 -0
- moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +100 -0
- moai_adk/templates/.claude/skills/moai-lang-haskell/SKILL.md +100 -0
- moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +98 -0
- moai_adk/templates/.claude/skills/moai-lang-javascript/SKILL.md +96 -0
- moai_adk/templates/.claude/skills/moai-lang-julia/SKILL.md +98 -0
- moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +99 -0
- moai_adk/templates/.claude/skills/moai-lang-lua/SKILL.md +98 -0
- moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +98 -0
- moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +96 -0
- moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +99 -0
- moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +99 -0
- moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +100 -0
- moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +100 -0
- moai_adk/templates/.claude/skills/moai-lang-shell/SKILL.md +100 -0
- moai_adk/templates/.claude/skills/moai-lang-sql/SKILL.md +100 -0
- moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +99 -0
- moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +96 -0
- moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +44 -43
- moai_adk/templates/.github/workflows/moai-gitflow.yml +36 -35
- moai_adk/templates/.moai/config.json +9 -6
- moai_adk/templates/.moai/memory/development-guide.md +220 -221
- moai_adk/templates/.moai/memory/gitflow-protection-policy.md +85 -85
- moai_adk/templates/.moai/memory/spec-metadata.md +149 -150
- moai_adk/templates/.moai/project/product.md +90 -90
- moai_adk/templates/.moai/project/structure.md +85 -85
- moai_adk/templates/.moai/project/tech.md +117 -117
- moai_adk/templates/CLAUDE.md +354 -573
- moai_adk/templates/__init__.py +1 -1
- moai_adk/utils/__init__.py +1 -1
- moai_adk/utils/banner.py +7 -7
- moai_adk/utils/logger.py +1 -1
- moai_adk-0.4.1.dist-info/METADATA +303 -0
- moai_adk-0.4.1.dist-info/RECORD +152 -0
- moai_adk/templates/.claude/commands/alfred/1-spec.md +0 -532
- moai_adk/templates/.claude/commands/alfred/2-build.md +0 -432
- moai_adk/templates/.moai/hooks/pre-push.sample +0 -88
- moai_adk-0.3.13.dist-info/METADATA +0 -1586
- moai_adk-0.3.13.dist-info/RECORD +0 -90
- {moai_adk-0.3.13.dist-info → moai_adk-0.4.1.dist-info}/WHEEL +0 -0
- {moai_adk-0.3.13.dist-info → moai_adk-0.4.1.dist-info}/entry_points.txt +0 -0
- {moai_adk-0.3.13.dist-info → moai_adk-0.4.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""Event-Driven Checkpoint system
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
Detect risky tasks and create automatic checkpoints
|
|
5
5
|
@TAG:CHECKPOINT-EVENT-001
|
|
6
6
|
"""
|
|
7
7
|
|
|
@@ -12,7 +12,7 @@ from datetime import datetime
|
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from typing import Any
|
|
14
14
|
|
|
15
|
-
#
|
|
15
|
+
# Script execution pattern for each language supported by MoAI-ADK
|
|
16
16
|
# Python, TypeScript, Java, Go, Rust, Dart, Swift, Kotlin + Shell
|
|
17
17
|
SCRIPT_EXECUTION_PATTERN = re.compile(
|
|
18
18
|
r"\b("
|
|
@@ -39,25 +39,25 @@ SCRIPT_EXECUTION_PATTERN = re.compile(
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
def detect_risky_operation(tool_name: str, tool_args: dict[str, Any], cwd: str) -> tuple[bool, str]:
|
|
42
|
-
"""
|
|
42
|
+
"""Risk task detection (for Event-Driven Checkpoint)
|
|
43
43
|
|
|
44
|
-
Claude Code tool
|
|
45
|
-
|
|
44
|
+
Claude Code tool automatically detects dangerous tasks before use.
|
|
45
|
+
When a risk is detected, a checkpoint is automatically created to enable rollback.
|
|
46
46
|
|
|
47
47
|
Args:
|
|
48
|
-
tool_name: Claude Code tool
|
|
49
|
-
tool_args: Tool
|
|
50
|
-
cwd:
|
|
48
|
+
tool_name: Name of the Claude Code tool (Bash, Edit, Write, MultiEdit)
|
|
49
|
+
tool_args: Tool argument dictionary
|
|
50
|
+
cwd: Project root directory path
|
|
51
51
|
|
|
52
52
|
Returns:
|
|
53
|
-
(is_risky, operation_type)
|
|
54
|
-
- is_risky:
|
|
55
|
-
- operation_type:
|
|
53
|
+
(is_risky, operation_type) tuple
|
|
54
|
+
- is_risky: Whether the operation is dangerous (bool)
|
|
55
|
+
- operation_type: operation type (str: delete, merge, script, critical-file, refactor)
|
|
56
56
|
|
|
57
57
|
Risky Operations:
|
|
58
58
|
- Bash tool: rm -rf, git merge, git reset --hard, git rebase, script execution
|
|
59
59
|
- Edit/Write tool: CLAUDE.md, config.json, .moai/memory/*.md
|
|
60
|
-
- MultiEdit tool: ≥10
|
|
60
|
+
- MultiEdit tool: Edit ≥10 items File simultaneously
|
|
61
61
|
- Script execution: Python, Node, Java, Go, Rust, Dart, Swift, Kotlin, Shell scripts
|
|
62
62
|
|
|
63
63
|
Examples:
|
|
@@ -69,29 +69,29 @@ def detect_risky_operation(tool_name: str, tool_args: dict[str, Any], cwd: str)
|
|
|
69
69
|
(False, '')
|
|
70
70
|
|
|
71
71
|
Notes:
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
72
|
+
- Minimize false positives: ignore safe operations
|
|
73
|
+
- Performance: lightweight string matching (< 1ms)
|
|
74
|
+
- Extensibility: Easily added to the patterns dictionary
|
|
75
75
|
|
|
76
76
|
@TAG:CHECKPOINT-EVENT-001
|
|
77
77
|
"""
|
|
78
|
-
# Bash tool:
|
|
78
|
+
# Bash tool: Detect dangerous commands
|
|
79
79
|
if tool_name == "Bash":
|
|
80
80
|
command = tool_args.get("command", "")
|
|
81
81
|
|
|
82
|
-
#
|
|
82
|
+
# Mass Delete
|
|
83
83
|
if any(pattern in command for pattern in ["rm -rf", "git rm"]):
|
|
84
84
|
return (True, "delete")
|
|
85
85
|
|
|
86
|
-
# Git
|
|
86
|
+
# Git merge/reset/rebase
|
|
87
87
|
if any(pattern in command for pattern in ["git merge", "git reset --hard", "git rebase"]):
|
|
88
88
|
return (True, "merge")
|
|
89
89
|
|
|
90
|
-
#
|
|
90
|
+
# Execute external script (potentially destructive)
|
|
91
91
|
if any(command.startswith(prefix) for prefix in ["python ", "node ", "bash ", "sh "]):
|
|
92
92
|
return (True, "script")
|
|
93
93
|
|
|
94
|
-
# Edit/Write tool:
|
|
94
|
+
# Edit/Write tool: Detect important files
|
|
95
95
|
if tool_name in ("Edit", "Write"):
|
|
96
96
|
file_path = tool_args.get("file_path", "")
|
|
97
97
|
|
|
@@ -106,7 +106,7 @@ def detect_risky_operation(tool_name: str, tool_args: dict[str, Any], cwd: str)
|
|
|
106
106
|
if any(cf in file_path for cf in critical_files):
|
|
107
107
|
return (True, "critical-file")
|
|
108
108
|
|
|
109
|
-
# MultiEdit tool:
|
|
109
|
+
# MultiEdit tool: Detect large edits
|
|
110
110
|
if tool_name == "MultiEdit":
|
|
111
111
|
edits = tool_args.get("edits", [])
|
|
112
112
|
if len(edits) >= 10:
|
|
@@ -116,32 +116,32 @@ def detect_risky_operation(tool_name: str, tool_args: dict[str, Any], cwd: str)
|
|
|
116
116
|
|
|
117
117
|
|
|
118
118
|
def create_checkpoint(cwd: str, operation_type: str) -> str:
|
|
119
|
-
"""
|
|
119
|
+
"""Create checkpoint (Git local branch)
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
Automatically creates checkpoints before dangerous operations.
|
|
122
|
+
Prevent remote repository contamination by creating a Git local branch.
|
|
123
123
|
|
|
124
124
|
Args:
|
|
125
|
-
cwd:
|
|
126
|
-
operation_type:
|
|
125
|
+
cwd: Project root directory path
|
|
126
|
+
operation_type: operation type (delete, merge, script, etc.)
|
|
127
127
|
|
|
128
128
|
Returns:
|
|
129
|
-
checkpoint_branch:
|
|
130
|
-
|
|
129
|
+
checkpoint_branch: Created branch name
|
|
130
|
+
Returns "checkpoint-failed" on failure
|
|
131
131
|
|
|
132
132
|
Branch Naming:
|
|
133
133
|
before-{operation}-{YYYYMMDD-HHMMSS}
|
|
134
|
-
|
|
134
|
+
Example: before-delete-20251015-143000
|
|
135
135
|
|
|
136
136
|
Examples:
|
|
137
137
|
>>> create_checkpoint(".", "delete")
|
|
138
138
|
'before-delete-20251015-143000'
|
|
139
139
|
|
|
140
140
|
Notes:
|
|
141
|
-
-
|
|
142
|
-
-
|
|
143
|
-
-
|
|
144
|
-
-
|
|
141
|
+
- Create only local branch (no remote push)
|
|
142
|
+
- Fallback in case of Git error (ignore and continue)
|
|
143
|
+
- Do not check dirty working directory (allow uncommitted changes)
|
|
144
|
+
- Automatically record checkpoint logs (.moai/checkpoints.log)
|
|
145
145
|
|
|
146
146
|
@TAG:CHECKPOINT-EVENT-001
|
|
147
147
|
"""
|
|
@@ -149,8 +149,8 @@ def create_checkpoint(cwd: str, operation_type: str) -> str:
|
|
|
149
149
|
branch_name = f"before-{operation_type}-{timestamp}"
|
|
150
150
|
|
|
151
151
|
try:
|
|
152
|
-
#
|
|
153
|
-
|
|
152
|
+
# Create a new local branch from the current branch (without checking out)
|
|
153
|
+
subprocess.run(
|
|
154
154
|
["git", "branch", branch_name],
|
|
155
155
|
cwd=cwd,
|
|
156
156
|
check=True,
|
|
@@ -159,38 +159,38 @@ def create_checkpoint(cwd: str, operation_type: str) -> str:
|
|
|
159
159
|
timeout=2,
|
|
160
160
|
)
|
|
161
161
|
|
|
162
|
-
# Checkpoint
|
|
162
|
+
# Checkpoint log records
|
|
163
163
|
log_checkpoint(cwd, branch_name, operation_type)
|
|
164
164
|
|
|
165
165
|
return branch_name
|
|
166
166
|
|
|
167
167
|
except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError):
|
|
168
|
-
#
|
|
168
|
+
# Fallback (ignore) in case of Git error
|
|
169
169
|
return "checkpoint-failed"
|
|
170
170
|
|
|
171
171
|
|
|
172
172
|
def log_checkpoint(cwd: str, branch_name: str, operation_type: str) -> None:
|
|
173
|
-
"""Checkpoint
|
|
173
|
+
"""Checkpoint log records (.moai/checkpoints.log)
|
|
174
174
|
|
|
175
|
-
Checkpoint
|
|
176
|
-
SessionStart
|
|
175
|
+
Checkpoint creation history is recorded in JSON Lines format.
|
|
176
|
+
SessionStart reads this log to display a list of checkpoints.
|
|
177
177
|
|
|
178
178
|
Args:
|
|
179
|
-
cwd:
|
|
180
|
-
branch_name:
|
|
181
|
-
operation_type:
|
|
179
|
+
cwd: Project root directory path
|
|
180
|
+
branch_name: Created checkpoint branch name
|
|
181
|
+
operation_type: operation type
|
|
182
182
|
|
|
183
183
|
Log Format (JSON Lines):
|
|
184
184
|
{"timestamp": "2025-10-15T14:30:00", "branch": "before-delete-...", "operation": "delete"}
|
|
185
185
|
|
|
186
186
|
Examples:
|
|
187
187
|
>>> log_checkpoint(".", "before-delete-20251015-143000", "delete")
|
|
188
|
-
# .moai/checkpoints.log
|
|
188
|
+
# Add 1 line to .moai/checkpoints.log
|
|
189
189
|
|
|
190
190
|
Notes:
|
|
191
|
-
-
|
|
192
|
-
- append
|
|
193
|
-
-
|
|
191
|
+
- If the file does not exist, it is automatically created.
|
|
192
|
+
- Record in append mode (preserve existing logs)
|
|
193
|
+
- Ignored in case of failure (not critical)
|
|
194
194
|
|
|
195
195
|
@TAG:CHECKPOINT-EVENT-001
|
|
196
196
|
"""
|
|
@@ -209,22 +209,22 @@ def log_checkpoint(cwd: str, branch_name: str, operation_type: str) -> None:
|
|
|
209
209
|
f.write(json.dumps(log_entry) + "\n")
|
|
210
210
|
|
|
211
211
|
except (OSError, PermissionError):
|
|
212
|
-
#
|
|
212
|
+
# Ignore log failures (not critical)
|
|
213
213
|
pass
|
|
214
214
|
|
|
215
215
|
|
|
216
216
|
def list_checkpoints(cwd: str, max_count: int = 10) -> list[dict[str, str]]:
|
|
217
|
-
"""Checkpoint
|
|
217
|
+
"""Checkpoint list (parsing .moai/checkpoints.log)
|
|
218
218
|
|
|
219
|
-
|
|
220
|
-
SessionStart, /alfred:0-project restore
|
|
219
|
+
Returns a list of recently created checkpoints.
|
|
220
|
+
Used in the SessionStart, /alfred:0-project restore command.
|
|
221
221
|
|
|
222
222
|
Args:
|
|
223
|
-
cwd:
|
|
224
|
-
max_count:
|
|
223
|
+
cwd: Project root directory path
|
|
224
|
+
max_count: Maximum number to return (default 10 items)
|
|
225
225
|
|
|
226
226
|
Returns:
|
|
227
|
-
Checkpoint
|
|
227
|
+
Checkpoint list (most recent)
|
|
228
228
|
[{"timestamp": "...", "branch": "...", "operation": "..."}, ...]
|
|
229
229
|
|
|
230
230
|
Examples:
|
|
@@ -235,9 +235,9 @@ def list_checkpoints(cwd: str, max_count: int = 10) -> list[dict[str, str]]:
|
|
|
235
235
|
]
|
|
236
236
|
|
|
237
237
|
Notes:
|
|
238
|
-
-
|
|
239
|
-
-
|
|
240
|
-
-
|
|
238
|
+
- If there is no log file, an empty list is returned.
|
|
239
|
+
- Ignore lines where JSON parsing fails
|
|
240
|
+
- Return only the latest max_count
|
|
241
241
|
|
|
242
242
|
@TAG:CHECKPOINT-EVENT-001
|
|
243
243
|
"""
|
|
@@ -254,12 +254,12 @@ def list_checkpoints(cwd: str, max_count: int = 10) -> list[dict[str, str]]:
|
|
|
254
254
|
try:
|
|
255
255
|
checkpoints.append(json.loads(line.strip()))
|
|
256
256
|
except json.JSONDecodeError:
|
|
257
|
-
#
|
|
257
|
+
# Ignore lines where parsing failed
|
|
258
258
|
pass
|
|
259
259
|
except (OSError, PermissionError):
|
|
260
260
|
return []
|
|
261
261
|
|
|
262
|
-
#
|
|
262
|
+
# Return only the most recent max_count items (in order of latest)
|
|
263
263
|
return checkpoints[-max_count:]
|
|
264
264
|
|
|
265
265
|
|
|
@@ -8,26 +8,26 @@ from pathlib import Path
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def get_jit_context(prompt: str, cwd: str) -> list[str]:
|
|
11
|
-
"""
|
|
11
|
+
"""JIT Context Retrieval based on prompt.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
Alfred
|
|
13
|
+
Analyze user prompts and automatically recommend relevant documents.
|
|
14
|
+
Alfred commands and keyword-based pattern matching load only the documents you need.
|
|
15
15
|
|
|
16
16
|
Args:
|
|
17
|
-
prompt:
|
|
18
|
-
cwd:
|
|
17
|
+
prompt: Prompt for user input (case is irrelevant)
|
|
18
|
+
cwd: Project root directory path
|
|
19
19
|
|
|
20
20
|
Returns:
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
List of recommended document paths (relative paths).
|
|
22
|
+
If there is no matching pattern or file, an empty list []
|
|
23
23
|
|
|
24
24
|
Patterns:
|
|
25
|
-
- "/alfred:1-
|
|
26
|
-
- "/alfred:2-
|
|
27
|
-
- "test" → tests/ (
|
|
25
|
+
- "/alfred:1-plan" → .moai/memory/spec-metadata.md
|
|
26
|
+
- "/alfred:2-run" → .moai/memory/development-guide.md
|
|
27
|
+
- "test" → tests/ (if directory exists)
|
|
28
28
|
|
|
29
29
|
Examples:
|
|
30
|
-
>>> get_jit_context("/alfred:1-
|
|
30
|
+
>>> get_jit_context("/alfred:1-plan", "/project")
|
|
31
31
|
['.moai/memory/spec-metadata.md']
|
|
32
32
|
>>> get_jit_context("implement test", "/project")
|
|
33
33
|
['tests/']
|
|
@@ -35,22 +35,22 @@ def get_jit_context(prompt: str, cwd: str) -> list[str]:
|
|
|
35
35
|
[]
|
|
36
36
|
|
|
37
37
|
Notes:
|
|
38
|
-
- Context Engineering: JIT Retrieval
|
|
39
|
-
-
|
|
40
|
-
-
|
|
38
|
+
- Context Engineering: Compliance with JIT Retrieval principles
|
|
39
|
+
- Minimize initial context burden by loading only necessary documents
|
|
40
|
+
- Return after checking whether file exists
|
|
41
41
|
|
|
42
42
|
TDD History:
|
|
43
|
-
- RED: 18
|
|
44
|
-
- GREEN:
|
|
45
|
-
- REFACTOR:
|
|
43
|
+
- RED: 18 items scenario testing (command matching, keywords, empty results)
|
|
44
|
+
- GREEN: Pattern matching dictionary-based implementation
|
|
45
|
+
- REFACTOR: Expandable pattern structure, file existence validation added
|
|
46
46
|
"""
|
|
47
47
|
context_files = []
|
|
48
48
|
cwd_path = Path(cwd)
|
|
49
49
|
|
|
50
50
|
# Pattern matching
|
|
51
51
|
patterns = {
|
|
52
|
-
"/alfred:1-
|
|
53
|
-
"/alfred:2-
|
|
52
|
+
"/alfred:1-plan": [".moai/memory/spec-metadata.md"],
|
|
53
|
+
"/alfred:2-run": [".moai/memory/development-guide.md"],
|
|
54
54
|
"test": ["tests/"],
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""Project metadata utilities
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
Project information inquiry (language, Git, SPEC progress, etc.)
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import json
|
|
@@ -11,18 +11,18 @@ from typing import Any
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def detect_language(cwd: str) -> str:
|
|
14
|
-
"""
|
|
14
|
+
"""Detect project language (supports 20 items languages)
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
pyproject.toml
|
|
18
|
-
TypeScript
|
|
16
|
+
Browse the File system to detect your project's main development language.
|
|
17
|
+
First, check configuration files such as pyproject.toml and tsconfig.json.
|
|
18
|
+
Apply TypeScript first principles (if tsconfig.json exists).
|
|
19
19
|
|
|
20
20
|
Args:
|
|
21
|
-
cwd:
|
|
21
|
+
cwd: Project root directory path (both absolute and relative paths are possible)
|
|
22
22
|
|
|
23
23
|
Returns:
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
Detected language name (lowercase). If detection fails, "Unknown Language" is returned.
|
|
25
|
+
Supported languages: python, typescript, javascript, java, go, rust,
|
|
26
26
|
dart, swift, kotlin, php, ruby, elixir, scala,
|
|
27
27
|
clojure, cpp, c, csharp, haskell, shell, lua
|
|
28
28
|
|
|
@@ -35,9 +35,9 @@ def detect_language(cwd: str) -> str:
|
|
|
35
35
|
'Unknown Language'
|
|
36
36
|
|
|
37
37
|
TDD History:
|
|
38
|
-
- RED: 21
|
|
39
|
-
- GREEN: 20
|
|
40
|
-
- REFACTOR:
|
|
38
|
+
- RED: Write a 21 items language detection test (20 items language + 1 items unknown)
|
|
39
|
+
- GREEN: 20 items language + unknown implementation, all tests passed
|
|
40
|
+
- REFACTOR: Optimize file inspection order, apply TypeScript priority principle
|
|
41
41
|
"""
|
|
42
42
|
cwd_path = Path(cwd)
|
|
43
43
|
|
|
@@ -89,22 +89,22 @@ def detect_language(cwd: str) -> str:
|
|
|
89
89
|
|
|
90
90
|
|
|
91
91
|
def _run_git_command(args: list[str], cwd: str, timeout: int = 2) -> str:
|
|
92
|
-
"""Git
|
|
92
|
+
"""Git command execution helper function
|
|
93
93
|
|
|
94
|
-
Git
|
|
95
|
-
|
|
94
|
+
Safely execute Git commands and return output.
|
|
95
|
+
Eliminates code duplication and provides consistent error handling.
|
|
96
96
|
|
|
97
97
|
Args:
|
|
98
|
-
args: Git
|
|
99
|
-
cwd:
|
|
100
|
-
timeout:
|
|
98
|
+
args: Git command argument list (git adds automatically)
|
|
99
|
+
cwd: Execution directory path
|
|
100
|
+
timeout: Timeout (seconds, default 2 seconds)
|
|
101
101
|
|
|
102
102
|
Returns:
|
|
103
|
-
Git
|
|
103
|
+
Git command output (stdout, removing leading and trailing spaces)
|
|
104
104
|
|
|
105
105
|
Raises:
|
|
106
|
-
subprocess.TimeoutExpired:
|
|
107
|
-
subprocess.CalledProcessError: Git
|
|
106
|
+
subprocess.TimeoutExpired: Timeout exceeded
|
|
107
|
+
subprocess.CalledProcessError: Git command failed
|
|
108
108
|
|
|
109
109
|
Examples:
|
|
110
110
|
>>> _run_git_command(["branch", "--show-current"], ".")
|
|
@@ -122,22 +122,22 @@ def _run_git_command(args: list[str], cwd: str, timeout: int = 2) -> str:
|
|
|
122
122
|
|
|
123
123
|
|
|
124
124
|
def get_git_info(cwd: str) -> dict[str, Any]:
|
|
125
|
-
"""Git
|
|
125
|
+
"""Gather Git repository information
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
Git
|
|
127
|
+
View the current status of a Git repository.
|
|
128
|
+
Returns the branch name, commit hash, and number of changes.
|
|
129
|
+
If it is not a Git repository, it returns an empty dictionary.
|
|
130
130
|
|
|
131
131
|
Args:
|
|
132
|
-
cwd:
|
|
132
|
+
cwd: Project root directory path
|
|
133
133
|
|
|
134
134
|
Returns:
|
|
135
|
-
Git
|
|
136
|
-
- branch:
|
|
137
|
-
- commit:
|
|
138
|
-
- changes:
|
|
135
|
+
Git information dictionary. Includes the following keys:
|
|
136
|
+
- branch: Current branch name (str)
|
|
137
|
+
- commit: Current commit hash (str, full hash)
|
|
138
|
+
- changes: Number of changed files (int, staged + unstaged)
|
|
139
139
|
|
|
140
|
-
|
|
140
|
+
Empty dictionary {} if it is not a Git repository or the query fails.
|
|
141
141
|
|
|
142
142
|
Examples:
|
|
143
143
|
>>> get_git_info("/path/to/git/repo")
|
|
@@ -146,14 +146,14 @@ def get_git_info(cwd: str) -> dict[str, Any]:
|
|
|
146
146
|
{}
|
|
147
147
|
|
|
148
148
|
Notes:
|
|
149
|
-
-
|
|
150
|
-
-
|
|
151
|
-
-
|
|
149
|
+
- Timeout: 2 seconds for each Git command
|
|
150
|
+
- Security: Safe execution with subprocess.run(shell=False)
|
|
151
|
+
- Error handling: Returns an empty dictionary in case of all exceptions
|
|
152
152
|
|
|
153
153
|
TDD History:
|
|
154
|
-
- RED: 3
|
|
155
|
-
- GREEN: subprocess
|
|
156
|
-
- REFACTOR:
|
|
154
|
+
- RED: 3 items scenario test (Git repo, non-Git, error)
|
|
155
|
+
- GREEN: Implementation of subprocess-based Git command execution
|
|
156
|
+
- REFACTOR: Add timeout (2 seconds), strengthen exception handling, remove duplicates with helper function
|
|
157
157
|
"""
|
|
158
158
|
try:
|
|
159
159
|
# Check if it's a git repository
|
|
@@ -176,21 +176,21 @@ def get_git_info(cwd: str) -> dict[str, Any]:
|
|
|
176
176
|
|
|
177
177
|
|
|
178
178
|
def count_specs(cwd: str) -> dict[str, int]:
|
|
179
|
-
"""SPEC
|
|
179
|
+
"""SPEC File count and progress calculation
|
|
180
180
|
|
|
181
|
-
.moai/specs/
|
|
182
|
-
|
|
181
|
+
Browse the .moai/specs/ directory to find the number of SPEC Files and
|
|
182
|
+
Counts the number of SPECs with status: completed.
|
|
183
183
|
|
|
184
184
|
Args:
|
|
185
|
-
cwd:
|
|
185
|
+
cwd: Project root directory path
|
|
186
186
|
|
|
187
187
|
Returns:
|
|
188
|
-
SPEC
|
|
189
|
-
- completed:
|
|
190
|
-
- total:
|
|
191
|
-
- percentage:
|
|
188
|
+
SPEC progress dictionary. Includes the following keys:
|
|
189
|
+
- completed: Number of completed SPECs (int)
|
|
190
|
+
- total: total number of SPECs (int)
|
|
191
|
+
- percentage: completion percentage (int, 0~100)
|
|
192
192
|
|
|
193
|
-
.moai/specs/
|
|
193
|
+
All 0 if .moai/specs/ directory does not exist
|
|
194
194
|
|
|
195
195
|
Examples:
|
|
196
196
|
>>> count_specs("/path/to/project")
|
|
@@ -199,14 +199,14 @@ def count_specs(cwd: str) -> dict[str, int]:
|
|
|
199
199
|
{'completed': 0, 'total': 0, 'percentage': 0}
|
|
200
200
|
|
|
201
201
|
Notes:
|
|
202
|
-
- SPEC
|
|
203
|
-
-
|
|
204
|
-
-
|
|
202
|
+
- SPEC File Location: .moai/specs/SPEC-{ID}/spec.md
|
|
203
|
+
- Completion condition: Include “status: completed” in YAML front matter
|
|
204
|
+
- If parsing fails, the SPEC is considered incomplete.
|
|
205
205
|
|
|
206
206
|
TDD History:
|
|
207
|
-
- RED: 5
|
|
208
|
-
- GREEN: Path.iterdir()
|
|
209
|
-
- REFACTOR:
|
|
207
|
+
- RED: 5 items scenario test (0/0, 2/5, 5/5, no directory, parsing error)
|
|
208
|
+
- GREEN: SPEC search with Path.iterdir(), YAML parsing implementation
|
|
209
|
+
- REFACTOR: Strengthened exception handling, improved percentage calculation safety
|
|
210
210
|
"""
|
|
211
211
|
specs_dir = Path(cwd) / ".moai" / "specs"
|
|
212
212
|
|
|
@@ -236,7 +236,7 @@ def count_specs(cwd: str) -> dict[str, int]:
|
|
|
236
236
|
if "status: completed" in yaml_content:
|
|
237
237
|
completed += 1
|
|
238
238
|
except (OSError, UnicodeDecodeError):
|
|
239
|
-
#
|
|
239
|
+
# File read failure or encoding error - considered incomplete
|
|
240
240
|
pass
|
|
241
241
|
|
|
242
242
|
percentage = int(completed / total * 100) if total > 0 else 0
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""Notification and control handlers
|
|
3
3
|
|
|
4
|
-
Notification, Stop, SubagentStop
|
|
4
|
+
Notification, Stop, SubagentStop event handling
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from core import HookPayload, HookResult
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def handle_notification(payload: HookPayload) -> HookResult:
|
|
11
|
-
"""Notification
|
|
11
|
+
"""Notification event handler (default implementation)"""
|
|
12
12
|
return HookResult()
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def handle_stop(payload: HookPayload) -> HookResult:
|
|
16
|
-
"""Stop
|
|
16
|
+
"""Stop event handler (default implementation)"""
|
|
17
17
|
return HookResult()
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def handle_subagent_stop(payload: HookPayload) -> HookResult:
|
|
21
|
-
"""SubagentStop
|
|
21
|
+
"""SubagentStop event handler (default implementation)"""
|
|
22
22
|
return HookResult()
|
|
23
23
|
|
|
24
24
|
|