moai-adk 0.10.1__py3-none-any.whl → 0.11.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/core/issue_creator.py +2 -2
- moai_adk/core/project/detector.py +285 -12
- moai_adk/core/project/phase_executor.py +4 -0
- moai_adk/core/tags/ci_validator.py +33 -3
- moai_adk/core/template_engine.py +6 -2
- moai_adk/templates/.claude/commands/alfred/0-project.md +60 -62
- moai_adk/templates/.claude/commands/alfred/1-plan.md +6 -0
- moai_adk/templates/.claude/commands/alfred/2-run.md +6 -0
- moai_adk/templates/.claude/commands/alfred/3-sync.md +6 -0
- moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +8 -9
- moai_adk/templates/.claude/hooks/alfred/core/project.py +22 -28
- moai_adk/templates/.claude/hooks/alfred/core/timeout.py +136 -0
- moai_adk/templates/.claude/hooks/alfred/core/ttl_cache.py +109 -0
- moai_adk/templates/.claude/hooks/alfred/core/version_cache.py +4 -4
- moai_adk/templates/.claude/hooks/alfred/notification__handle_events.py +10 -15
- moai_adk/templates/.claude/hooks/alfred/post_tool__log_changes.py +10 -15
- moai_adk/templates/.claude/hooks/alfred/pre_tool__auto_checkpoint.py +10 -15
- moai_adk/templates/.claude/hooks/alfred/session_end__cleanup.py +10 -15
- moai_adk/templates/.claude/hooks/alfred/session_start__show_project_info.py +10 -15
- moai_adk/templates/.claude/hooks/alfred/shared/core/__init__.py +2 -2
- moai_adk/templates/.claude/hooks/alfred/shared/core/project.py +19 -26
- moai_adk/templates/.claude/hooks/alfred/shared/core/tags.py +55 -23
- moai_adk/templates/.claude/hooks/alfred/shared/core/version_cache.py +4 -4
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/notification.py +134 -3
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/session.py +9 -10
- moai_adk/templates/.claude/hooks/alfred/shared/handlers/tool.py +3 -6
- moai_adk/templates/.claude/hooks/alfred/stop__handle_interrupt.py +10 -15
- moai_adk/templates/.claude/hooks/alfred/subagent_stop__handle_subagent_end.py +10 -15
- moai_adk/templates/.claude/hooks/alfred/user_prompt__jit_load_docs.py +11 -20
- moai_adk/templates/.claude/hooks/alfred/utils/__init__.py +1 -0
- moai_adk/templates/.claude/hooks/alfred/utils/timeout.py +136 -0
- moai_adk/templates/.github/workflows/c-tag-validation.yml +83 -0
- moai_adk/templates/.github/workflows/cpp-tag-validation.yml +79 -0
- moai_adk/templates/.github/workflows/csharp-tag-validation.yml +65 -0
- moai_adk/templates/.github/workflows/dart-tag-validation.yml +82 -0
- moai_adk/templates/.github/workflows/java-tag-validation.yml +75 -0
- moai_adk/templates/.github/workflows/kotlin-tag-validation.yml +67 -0
- moai_adk/templates/.github/workflows/{release.yml → moai-adk-release.yml} +6 -2
- moai_adk/templates/.github/workflows/{tag-validation.yml → moai-adk-tag-validation.yml} +53 -8
- moai_adk/templates/.github/workflows/moai-gitflow.yml +6 -1
- moai_adk/templates/.github/workflows/php-tag-validation.yml +56 -0
- moai_adk/templates/.github/workflows/ruby-tag-validation.yml +68 -0
- moai_adk/templates/.github/workflows/rust-tag-validation.yml +73 -0
- moai_adk/templates/.github/workflows/shell-tag-validation.yml +65 -0
- moai_adk/templates/.github/workflows/swift-tag-validation.yml +79 -0
- moai_adk/templates/.moai/memory/GITFLOW-PROTECTION-POLICY.md +330 -0
- moai_adk/templates/.moai/memory/SPEC-METADATA.md +356 -0
- moai_adk/templates/CLAUDE.md +536 -65
- moai_adk/templates/workflows/go-tag-validation.yml +130 -0
- moai_adk/templates/workflows/javascript-tag-validation.yml +135 -0
- moai_adk/templates/workflows/python-tag-validation.yml +118 -0
- moai_adk/templates/workflows/typescript-tag-validation.yml +154 -0
- {moai_adk-0.10.1.dist-info → moai_adk-0.11.1.dist-info}/METADATA +70 -13
- {moai_adk-0.10.1.dist-info → moai_adk-0.11.1.dist-info}/RECORD +58 -37
- /moai_adk/templates/.github/workflows/{spec-issue-sync.yml → moai-adk-spec-issue-sync.yml} +0 -0
- {moai_adk-0.10.1.dist-info → moai_adk-0.11.1.dist-info}/WHEEL +0 -0
- {moai_adk-0.10.1.dist-info → moai_adk-0.11.1.dist-info}/entry_points.txt +0 -0
- {moai_adk-0.10.1.dist-info → moai_adk-0.11.1.dist-info}/licenses/LICENSE +0 -0
moai_adk/core/issue_creator.py
CHANGED
|
@@ -59,7 +59,7 @@ class GitHubIssueCreator:
|
|
|
59
59
|
IssueType.BUG: ["bug", "reported"],
|
|
60
60
|
IssueType.FEATURE: ["feature-request", "enhancement"],
|
|
61
61
|
IssueType.IMPROVEMENT: ["improvement", "enhancement"],
|
|
62
|
-
IssueType.QUESTION: ["question", "help
|
|
62
|
+
IssueType.QUESTION: ["question", "help wanted"], # Fixed: "help-wanted" → "help wanted" (GitHub standard)
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
# Priority emoji
|
|
@@ -145,7 +145,7 @@ class GitHubIssueCreator:
|
|
|
145
145
|
# Collect labels
|
|
146
146
|
labels = self.LABEL_MAP.get(config.issue_type, []).copy()
|
|
147
147
|
if config.priority:
|
|
148
|
-
labels.append(
|
|
148
|
+
labels.append(config.priority.value) # Fixed: removed "priority-" prefix (use direct label names)
|
|
149
149
|
if config.category:
|
|
150
150
|
labels.append(f"category-{config.category.lower().replace(' ', '-')}")
|
|
151
151
|
if config.custom_labels:
|
|
@@ -16,7 +16,18 @@ class LanguageDetector:
|
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
LANGUAGE_PATTERNS = {
|
|
19
|
-
#
|
|
19
|
+
# @CODE:LDE-PRIORITY-001 | SPEC: SPEC-LANGUAGE-DETECTION-EXTENDED-001/spec.md
|
|
20
|
+
# Priority order (highest to lowest):
|
|
21
|
+
# 1. Rust, 2. Dart, 3. Swift, 4. Kotlin, 5. C#, 6. Java, 7. Ruby, 8. PHP
|
|
22
|
+
# 9. Go, 10. Python, 11. TypeScript, 12. JavaScript, 13. C++, 14. C, 15. Shell
|
|
23
|
+
|
|
24
|
+
"rust": ["*.rs", "Cargo.toml"],
|
|
25
|
+
"dart": ["*.dart", "pubspec.yaml"],
|
|
26
|
+
"swift": ["*.swift", "Package.swift"],
|
|
27
|
+
"kotlin": ["*.kt", "build.gradle.kts"],
|
|
28
|
+
"csharp": ["*.cs", "*.csproj"],
|
|
29
|
+
"java": ["*.java", "pom.xml", "build.gradle"],
|
|
30
|
+
# Ruby moved for priority (Rails detection)
|
|
20
31
|
# @CODE:LANG-DETECT-RUBY-001 | SPEC: Issue #51 Language Detection Fix
|
|
21
32
|
"ruby": [
|
|
22
33
|
"*.rb",
|
|
@@ -26,7 +37,7 @@ class LanguageDetector:
|
|
|
26
37
|
"app/controllers/", # Rails: controller directory
|
|
27
38
|
"Rakefile" # Rails/Ruby: task file
|
|
28
39
|
],
|
|
29
|
-
# PHP
|
|
40
|
+
# PHP after Ruby (Laravel detection)
|
|
30
41
|
"php": [
|
|
31
42
|
"*.php",
|
|
32
43
|
"composer.json",
|
|
@@ -34,23 +45,18 @@ class LanguageDetector:
|
|
|
34
45
|
"app/", # Laravel: application directory
|
|
35
46
|
"bootstrap/laravel.php" # Laravel: bootstrap file
|
|
36
47
|
],
|
|
48
|
+
"go": ["*.go", "go.mod"],
|
|
37
49
|
"python": ["*.py", "pyproject.toml", "requirements.txt", "setup.py"],
|
|
38
50
|
"typescript": ["*.ts", "tsconfig.json"],
|
|
39
51
|
"javascript": ["*.js", "package.json"],
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
"swift": ["*.swift", "Package.swift"],
|
|
45
|
-
"kotlin": ["*.kt", "build.gradle.kts"],
|
|
46
|
-
"csharp": ["*.cs", "*.csproj"],
|
|
52
|
+
"cpp": ["*.cpp", "CMakeLists.txt"],
|
|
53
|
+
"c": ["*.c", "Makefile"],
|
|
54
|
+
"shell": ["*.sh", "*.bash"],
|
|
55
|
+
# Additional languages (lower priority)
|
|
47
56
|
"elixir": ["*.ex", "mix.exs"],
|
|
48
57
|
"scala": ["*.scala", "build.sbt"],
|
|
49
58
|
"clojure": ["*.clj", "project.clj"],
|
|
50
59
|
"haskell": ["*.hs", "*.cabal"],
|
|
51
|
-
"c": ["*.c", "Makefile"],
|
|
52
|
-
"cpp": ["*.cpp", "CMakeLists.txt"],
|
|
53
|
-
"shell": ["*.sh", "*.bash"],
|
|
54
60
|
"lua": ["*.lua"],
|
|
55
61
|
}
|
|
56
62
|
|
|
@@ -112,6 +118,273 @@ class LanguageDetector:
|
|
|
112
118
|
|
|
113
119
|
return False
|
|
114
120
|
|
|
121
|
+
# @CODE:LANG-002 | SPEC: SPEC-LANGUAGE-DETECTION-001.md | TEST: tests/unit/test_detector.py
|
|
122
|
+
def detect_package_manager(self, path: str | Path = ".") -> str:
|
|
123
|
+
"""Detect JavaScript/TypeScript package manager.
|
|
124
|
+
|
|
125
|
+
Checks for lock files in priority order (highest to lowest):
|
|
126
|
+
1. bun.lockb (Bun) - fastest runtime
|
|
127
|
+
2. pnpm-lock.yaml (pnpm) - efficient disk usage
|
|
128
|
+
3. yarn.lock (Yarn) - Facebook's package manager
|
|
129
|
+
4. package-lock.json (npm) - default Node.js package manager
|
|
130
|
+
|
|
131
|
+
Priority order reflects modern best practices and performance characteristics.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
path: Project root directory to inspect. Defaults to current directory.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
Package manager name: 'bun' | 'pnpm' | 'yarn' | 'npm'
|
|
138
|
+
|
|
139
|
+
Example:
|
|
140
|
+
>>> detector = LanguageDetector()
|
|
141
|
+
>>> detector.detect_package_manager("/path/to/project")
|
|
142
|
+
'pnpm'
|
|
143
|
+
"""
|
|
144
|
+
path = Path(path)
|
|
145
|
+
|
|
146
|
+
# Check in priority order (Bun → pnpm → Yarn → npm)
|
|
147
|
+
if (path / "bun.lockb").exists():
|
|
148
|
+
return "bun"
|
|
149
|
+
elif (path / "pnpm-lock.yaml").exists():
|
|
150
|
+
return "pnpm"
|
|
151
|
+
elif (path / "yarn.lock").exists():
|
|
152
|
+
return "yarn"
|
|
153
|
+
else:
|
|
154
|
+
# Default to npm (most common, works everywhere)
|
|
155
|
+
return "npm"
|
|
156
|
+
|
|
157
|
+
# @CODE:LANG-002 | SPEC: SPEC-LANGUAGE-DETECTION-001.md | TEST: tests/unit/test_detector.py
|
|
158
|
+
def get_workflow_template_path(self, language: str) -> str:
|
|
159
|
+
"""Get workflow template path for detected language.
|
|
160
|
+
|
|
161
|
+
Returns the relative path to the language-specific GitHub Actions workflow template.
|
|
162
|
+
These templates are pre-configured with language-specific testing tools, linting,
|
|
163
|
+
and coverage reporting.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
language: Detected language name (lowercase).
|
|
167
|
+
Supported: 'python', 'javascript', 'typescript', 'go'
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
Relative path to workflow template (e.g., 'workflows/python-tag-validation.yml')
|
|
171
|
+
|
|
172
|
+
Raises:
|
|
173
|
+
ValueError: If language doesn't have a dedicated workflow template
|
|
174
|
+
|
|
175
|
+
Example:
|
|
176
|
+
>>> detector = LanguageDetector()
|
|
177
|
+
>>> detector.get_workflow_template_path("python")
|
|
178
|
+
'workflows/python-tag-validation.yml'
|
|
179
|
+
"""
|
|
180
|
+
# Language-to-template mapping (add new languages here)
|
|
181
|
+
template_mapping = {
|
|
182
|
+
"python": "python-tag-validation.yml",
|
|
183
|
+
"javascript": "javascript-tag-validation.yml",
|
|
184
|
+
"typescript": "typescript-tag-validation.yml",
|
|
185
|
+
"go": "go-tag-validation.yml",
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if language not in template_mapping:
|
|
189
|
+
supported = ", ".join(sorted(template_mapping.keys()))
|
|
190
|
+
raise ValueError(
|
|
191
|
+
f"Language '{language}' does not have a dedicated workflow template. "
|
|
192
|
+
f"Supported languages: {supported}"
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
template_filename = template_mapping[language]
|
|
196
|
+
# Return path relative to templates directory
|
|
197
|
+
return f"workflows/{template_filename}"
|
|
198
|
+
|
|
199
|
+
# @CODE:LANG-002 | SPEC: SPEC-LANGUAGE-DETECTION-001.md | TEST: tests/unit/test_detector.py
|
|
200
|
+
def get_supported_languages_for_workflows(self) -> list[str]:
|
|
201
|
+
"""Get list of languages with dedicated workflow templates.
|
|
202
|
+
|
|
203
|
+
Returns languages that have pre-built GitHub Actions workflow templates
|
|
204
|
+
with language-specific testing, linting, and coverage configuration.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
List of supported language names (lowercase)
|
|
208
|
+
|
|
209
|
+
Example:
|
|
210
|
+
>>> detector = LanguageDetector()
|
|
211
|
+
>>> detector.get_supported_languages_for_workflows()
|
|
212
|
+
['python', 'javascript', 'typescript', 'go']
|
|
213
|
+
|
|
214
|
+
Note:
|
|
215
|
+
While LanguageDetector can detect 20+ languages, only these 4
|
|
216
|
+
have dedicated CI/CD workflow templates. Other languages fall back
|
|
217
|
+
to generic workflows.
|
|
218
|
+
"""
|
|
219
|
+
return ["python", "javascript", "typescript", "go"]
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def get_workflow_template_path(self, language: str) -> str:
|
|
223
|
+
"""Get the GitHub Actions workflow template path for a language.
|
|
224
|
+
|
|
225
|
+
@CODE:LDE-WORKFLOW-PATH-001 | SPEC: SPEC-LANGUAGE-DETECTION-EXTENDED-001/spec.md
|
|
226
|
+
|
|
227
|
+
Args:
|
|
228
|
+
language: Programming language name (lowercase).
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
Workflow template file path relative to templates directory.
|
|
232
|
+
|
|
233
|
+
Raises:
|
|
234
|
+
ValueError: If language is not supported for workflows.
|
|
235
|
+
"""
|
|
236
|
+
workflow_mapping = {
|
|
237
|
+
"python": ".github/workflows/python-tag-validation.yml",
|
|
238
|
+
"javascript": ".github/workflows/javascript-tag-validation.yml",
|
|
239
|
+
"typescript": ".github/workflows/typescript-tag-validation.yml",
|
|
240
|
+
"go": ".github/workflows/go-tag-validation.yml",
|
|
241
|
+
"ruby": ".github/workflows/ruby-tag-validation.yml",
|
|
242
|
+
"php": ".github/workflows/php-tag-validation.yml",
|
|
243
|
+
"java": ".github/workflows/java-tag-validation.yml",
|
|
244
|
+
"rust": ".github/workflows/rust-tag-validation.yml",
|
|
245
|
+
"dart": ".github/workflows/dart-tag-validation.yml",
|
|
246
|
+
"swift": ".github/workflows/swift-tag-validation.yml",
|
|
247
|
+
"kotlin": ".github/workflows/kotlin-tag-validation.yml",
|
|
248
|
+
"csharp": ".github/workflows/csharp-tag-validation.yml",
|
|
249
|
+
"c": ".github/workflows/c-tag-validation.yml",
|
|
250
|
+
"cpp": ".github/workflows/cpp-tag-validation.yml",
|
|
251
|
+
"shell": ".github/workflows/shell-tag-validation.yml",
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if language.lower() not in workflow_mapping:
|
|
255
|
+
raise ValueError(
|
|
256
|
+
f"No workflow template available for language: {language}. "
|
|
257
|
+
f"Supported languages: {', '.join(workflow_mapping.keys())}"
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
return workflow_mapping[language.lower()]
|
|
261
|
+
|
|
262
|
+
def detect_package_manager(self, path: str | Path = ".") -> str | None:
|
|
263
|
+
"""Detect the package manager for the detected language.
|
|
264
|
+
|
|
265
|
+
@CODE:LDE-PKG-MGR-001 | SPEC: SPEC-LANGUAGE-DETECTION-EXTENDED-001/spec.md
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
path: Directory to inspect.
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
Package manager name or None if not detected.
|
|
272
|
+
"""
|
|
273
|
+
path = Path(path)
|
|
274
|
+
|
|
275
|
+
# Ruby
|
|
276
|
+
if (path / "Gemfile").exists():
|
|
277
|
+
return "bundle"
|
|
278
|
+
|
|
279
|
+
# PHP
|
|
280
|
+
if (path / "composer.json").exists():
|
|
281
|
+
return "composer"
|
|
282
|
+
|
|
283
|
+
# Java/Kotlin
|
|
284
|
+
if (path / "pom.xml").exists():
|
|
285
|
+
return "maven"
|
|
286
|
+
if (path / "build.gradle").exists() or (path / "build.gradle.kts").exists():
|
|
287
|
+
return "gradle"
|
|
288
|
+
|
|
289
|
+
# Rust
|
|
290
|
+
if (path / "Cargo.toml").exists():
|
|
291
|
+
return "cargo"
|
|
292
|
+
|
|
293
|
+
# Dart/Flutter
|
|
294
|
+
if (path / "pubspec.yaml").exists():
|
|
295
|
+
return "dart_pub"
|
|
296
|
+
|
|
297
|
+
# Swift
|
|
298
|
+
if (path / "Package.swift").exists():
|
|
299
|
+
return "spm"
|
|
300
|
+
|
|
301
|
+
# C#
|
|
302
|
+
if list(path.glob("*.csproj")) or list(path.glob("*.sln")):
|
|
303
|
+
return "dotnet"
|
|
304
|
+
|
|
305
|
+
# Python
|
|
306
|
+
if (path / "pyproject.toml").exists():
|
|
307
|
+
return "pip"
|
|
308
|
+
|
|
309
|
+
# JavaScript/TypeScript
|
|
310
|
+
if (path / "package.json").exists():
|
|
311
|
+
return "npm"
|
|
312
|
+
|
|
313
|
+
# Go
|
|
314
|
+
if (path / "go.mod").exists():
|
|
315
|
+
return "go_modules"
|
|
316
|
+
|
|
317
|
+
return None
|
|
318
|
+
|
|
319
|
+
def detect_build_tool(self, path: str | Path = ".", language: str | None = None) -> str | None:
|
|
320
|
+
"""Detect the build tool for the detected language.
|
|
321
|
+
|
|
322
|
+
@CODE:LDE-BUILD-TOOL-001 | SPEC: SPEC-LANGUAGE-DETECTION-EXTENDED-001/spec.md
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
path: Directory to inspect.
|
|
326
|
+
language: Optional language hint for disambiguation.
|
|
327
|
+
|
|
328
|
+
Returns:
|
|
329
|
+
Build tool name or None if not detected.
|
|
330
|
+
"""
|
|
331
|
+
path = Path(path)
|
|
332
|
+
|
|
333
|
+
# C/C++
|
|
334
|
+
if (path / "CMakeLists.txt").exists():
|
|
335
|
+
return "cmake"
|
|
336
|
+
if (path / "Makefile").exists():
|
|
337
|
+
return "make"
|
|
338
|
+
|
|
339
|
+
# Java/Kotlin
|
|
340
|
+
if language in ["java", "kotlin"]:
|
|
341
|
+
if (path / "pom.xml").exists():
|
|
342
|
+
return "maven"
|
|
343
|
+
if (path / "build.gradle").exists() or (path / "build.gradle.kts").exists():
|
|
344
|
+
return "gradle"
|
|
345
|
+
|
|
346
|
+
# Rust
|
|
347
|
+
if (path / "Cargo.toml").exists():
|
|
348
|
+
return "cargo"
|
|
349
|
+
|
|
350
|
+
# Swift
|
|
351
|
+
if (path / "Package.swift").exists():
|
|
352
|
+
return "spm"
|
|
353
|
+
if list(path.glob("*.xcodeproj")) or list(path.glob("*.xcworkspace")):
|
|
354
|
+
return "xcode"
|
|
355
|
+
|
|
356
|
+
# C#
|
|
357
|
+
if list(path.glob("*.csproj")) or list(path.glob("*.sln")):
|
|
358
|
+
return "dotnet"
|
|
359
|
+
|
|
360
|
+
return None
|
|
361
|
+
|
|
362
|
+
def get_supported_languages_for_workflows(self) -> list[str]:
|
|
363
|
+
"""Get the list of languages with dedicated CI/CD workflow support.
|
|
364
|
+
|
|
365
|
+
@CODE:LDE-SUPPORTED-LANGS-001 | SPEC: SPEC-LANGUAGE-DETECTION-EXTENDED-001/spec.md
|
|
366
|
+
|
|
367
|
+
Returns:
|
|
368
|
+
List of supported language names (15 total).
|
|
369
|
+
"""
|
|
370
|
+
return [
|
|
371
|
+
"python",
|
|
372
|
+
"javascript",
|
|
373
|
+
"typescript",
|
|
374
|
+
"go",
|
|
375
|
+
"ruby",
|
|
376
|
+
"php",
|
|
377
|
+
"java",
|
|
378
|
+
"rust",
|
|
379
|
+
"dart",
|
|
380
|
+
"swift",
|
|
381
|
+
"kotlin",
|
|
382
|
+
"csharp",
|
|
383
|
+
"c",
|
|
384
|
+
"cpp",
|
|
385
|
+
"shell",
|
|
386
|
+
]
|
|
387
|
+
|
|
115
388
|
|
|
116
389
|
def detect_project_language(path: str | Path = ".") -> str | None:
|
|
117
390
|
"""Detect the project language (helper).
|
|
@@ -312,8 +312,12 @@ class PhaseExecutor:
|
|
|
312
312
|
cwd=project_path,
|
|
313
313
|
check=True,
|
|
314
314
|
capture_output=True,
|
|
315
|
+
timeout=30, # Default timeout for git operations
|
|
315
316
|
)
|
|
316
317
|
# Intentionally avoid printing to keep progress output clean
|
|
318
|
+
except subprocess.TimeoutExpired:
|
|
319
|
+
# Timeout is non-fatal
|
|
320
|
+
pass
|
|
317
321
|
except subprocess.CalledProcessError:
|
|
318
322
|
# Only log on error; failures are non-fatal
|
|
319
323
|
pass
|
|
@@ -16,6 +16,8 @@ import os
|
|
|
16
16
|
from typing import Any, Dict, List, Optional
|
|
17
17
|
|
|
18
18
|
import requests
|
|
19
|
+
from requests.adapters import HTTPAdapter
|
|
20
|
+
from urllib3.util import Retry
|
|
19
21
|
|
|
20
22
|
from .pre_commit_validator import (
|
|
21
23
|
PreCommitValidator,
|
|
@@ -87,16 +89,44 @@ class CIValidator(PreCommitValidator):
|
|
|
87
89
|
'Accept': 'application/vnd.github.v3+json'
|
|
88
90
|
}
|
|
89
91
|
|
|
92
|
+
# Create session with retry strategy
|
|
93
|
+
session = requests.Session()
|
|
94
|
+
retry = Retry(
|
|
95
|
+
total=3,
|
|
96
|
+
backoff_factor=0.5,
|
|
97
|
+
status_forcelist=[500, 502, 503, 504],
|
|
98
|
+
allowed_methods=["GET"]
|
|
99
|
+
)
|
|
100
|
+
adapter = HTTPAdapter(max_retries=retry)
|
|
101
|
+
session.mount("https://", adapter)
|
|
102
|
+
|
|
90
103
|
try:
|
|
91
|
-
|
|
104
|
+
# Dual timeout: (connect_timeout, read_timeout)
|
|
105
|
+
response = session.get(
|
|
106
|
+
url,
|
|
107
|
+
headers=headers,
|
|
108
|
+
timeout=(5, 10)
|
|
109
|
+
)
|
|
92
110
|
response.raise_for_status()
|
|
93
111
|
|
|
94
112
|
files_data = response.json()
|
|
95
113
|
return [file_info['filename'] for file_info in files_data]
|
|
96
114
|
|
|
97
|
-
except
|
|
98
|
-
#
|
|
115
|
+
except requests.exceptions.Timeout:
|
|
116
|
+
# Network timeout - return empty list gracefully
|
|
117
|
+
return []
|
|
118
|
+
except requests.exceptions.HTTPError as e:
|
|
119
|
+
# HTTP error (4xx, 5xx)
|
|
120
|
+
if e.response.status_code == 404:
|
|
121
|
+
# PR not found
|
|
122
|
+
return []
|
|
123
|
+
# Other HTTP errors: log but continue
|
|
124
|
+
return []
|
|
125
|
+
except requests.exceptions.RequestException:
|
|
126
|
+
# Network/connection errors
|
|
99
127
|
return []
|
|
128
|
+
finally:
|
|
129
|
+
session.close()
|
|
100
130
|
|
|
101
131
|
def validate_pr_changes(
|
|
102
132
|
self,
|
moai_adk/core/template_engine.py
CHANGED
|
@@ -31,13 +31,17 @@ class TemplateEngine:
|
|
|
31
31
|
- File-based and string-based template rendering
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
|
-
def __init__(self, strict_undefined: bool =
|
|
34
|
+
def __init__(self, strict_undefined: bool = True):
|
|
35
35
|
"""
|
|
36
36
|
Initialize the template engine.
|
|
37
37
|
|
|
38
38
|
Args:
|
|
39
|
-
strict_undefined: If True, raise error on undefined variables.
|
|
39
|
+
strict_undefined: If True, raise error on undefined variables (default: True).
|
|
40
40
|
If False, render undefined variables as empty strings.
|
|
41
|
+
|
|
42
|
+
Note:
|
|
43
|
+
Changed to strict_undefined=True (v0.10.2+) for safer template rendering.
|
|
44
|
+
Variables must be explicitly provided to avoid silent template failures.
|
|
41
45
|
"""
|
|
42
46
|
self.strict_undefined = strict_undefined
|
|
43
47
|
self.undefined_behavior = StrictUndefined if strict_undefined else None
|
|
@@ -96,6 +96,8 @@ The user executes the `/alfred:8-project` command to start analyzing the project
|
|
|
96
96
|
|
|
97
97
|
**목적**: 프로젝트 초기화 시작 전에 대화 언어를 설정하고 사용자 닉네임을 등록합니다. 이 설정은 모든 Alfred 프롬프트, 인터뷰 질문 및 생성된 문서에 적용됩니다.
|
|
98
98
|
|
|
99
|
+
**UX 개선**: 2개 질문을 **1회 배치 호출**로 통합 (50% 상호작용 감소: 2 turns → 1 turn)
|
|
100
|
+
|
|
99
101
|
### 0.0 Alfred 자기소개 및 환영 인사
|
|
100
102
|
|
|
101
103
|
Alfred가 첫 상호작용으로 다음과 같이 인사합니다:
|
|
@@ -108,58 +110,61 @@ MoAI-ADK의 SuperAgent로서 당신의 프로젝트를 함께 만들어갈 준
|
|
|
108
110
|
먼저 기본 설정을 진행하겠습니다.
|
|
109
111
|
```
|
|
110
112
|
|
|
111
|
-
### 0.1 언어 선택
|
|
112
|
-
|
|
113
|
-
Alfred가 `AskUserQuestion tool (documented in moai-alfred-interactive-questions skill)` 를 사용하여
|
|
114
|
-
|
|
115
|
-
**
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
{
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
113
|
+
### 0.1 배치 설계: 언어 선택 + 사용자 닉네임 수집 (1회 호출)
|
|
114
|
+
|
|
115
|
+
Alfred가 `AskUserQuestion tool (documented in moai-alfred-interactive-questions skill)` 를 사용하여 **단일 배치 호출**로 언어와 닉네임을 동시에 수집합니다:
|
|
116
|
+
|
|
117
|
+
**Example AskUserQuestion Call**:
|
|
118
|
+
```python
|
|
119
|
+
AskUserQuestion(
|
|
120
|
+
questions=[
|
|
121
|
+
{
|
|
122
|
+
"question": "Which language would you like to use for the project initialization and documentation?",
|
|
123
|
+
"header": "Language",
|
|
124
|
+
"multiSelect": false,
|
|
125
|
+
"options": [
|
|
126
|
+
{
|
|
127
|
+
"label": "🌍 English",
|
|
128
|
+
"description": "All dialogs and documentation in English"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"label": "🇰🇷 한국어",
|
|
132
|
+
"description": "All dialogs and documentation in Korean"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"label": "🇯🇵 日本語",
|
|
136
|
+
"description": "All dialogs and documentation in Japanese"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"label": "🇨🇳 中文",
|
|
140
|
+
"description": "All dialogs and documentation in Chinese"
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"question": "How would you like to be called in our conversations? (e.g., GOOS, Team Lead, Developer, or custom name - max 20 chars)",
|
|
146
|
+
"header": "Nickname",
|
|
147
|
+
"multiSelect": false,
|
|
148
|
+
"options": [
|
|
149
|
+
{
|
|
150
|
+
"label": "Enter custom nickname",
|
|
151
|
+
"description": "Type your preferred name using the 'Other' option below"
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
]
|
|
156
|
+
)
|
|
137
157
|
```
|
|
138
158
|
|
|
139
|
-
|
|
140
|
-
- Passed to all sub-agents as a context parameter
|
|
141
|
-
- Stored in `.moai/config.json` under `language` field
|
|
142
|
-
- Used to generate all documentation in the selected language
|
|
143
|
-
- Displayed in CLAUDE.md under "## Project Information"
|
|
144
|
-
|
|
145
|
-
### 0.2.5 사용자 닉네임 선택
|
|
146
|
-
|
|
147
|
-
언어 선택 완료 후, Alfred가 `AskUserQuestion tool (documented in moai-alfred-interactive-questions skill)` 를 사용하여 사용자 닉네임을 요청합니다:
|
|
148
|
-
|
|
149
|
-
**질문**:
|
|
159
|
+
**User Response Example**:
|
|
150
160
|
```
|
|
151
|
-
|
|
152
|
-
|
|
161
|
+
Selected Language: 🇰🇷 한국어
|
|
162
|
+
Selected Nickname: GOOS (typed via "Other" option)
|
|
153
163
|
```
|
|
154
164
|
|
|
155
|
-
|
|
156
|
-
- 텍스트 직접 입력 가능 (자유 형식)
|
|
157
|
-
- 예시: "GOOS", "팀장", "개발자" 등
|
|
158
|
-
- 최대 20자 한도
|
|
159
|
-
|
|
160
|
-
### 0.2.6 사용자 정보 저장
|
|
165
|
+
### 0.2 사용자 정보 저장
|
|
161
166
|
|
|
162
|
-
Alfred가 선택된 닉네임을 다음과 같이 저장합니다:
|
|
167
|
+
Alfred가 선택된 언어와 닉네임을 다음과 같이 저장합니다:
|
|
163
168
|
|
|
164
169
|
```json
|
|
165
170
|
{
|
|
@@ -172,15 +177,18 @@ Alfred가 선택된 닉네임을 다음과 같이 저장합니다:
|
|
|
172
177
|
|
|
173
178
|
이 정보는:
|
|
174
179
|
- 모든 sub-agents 에게 컨텍스트 파라미터로 전달됨
|
|
175
|
-
- `.moai/config.json` 의 `user` 필드에 저장됨
|
|
176
|
-
- CLAUDE.md의 `{{USER_NICKNAME}}` 변수로 치환됨
|
|
180
|
+
- `.moai/config.json` 의 `language` 및 `user` 필드에 저장됨
|
|
181
|
+
- CLAUDE.md의 `{{CONVERSATION_LANGUAGE}}` 및 `{{USER_NICKNAME}}` 변수로 치환됨
|
|
177
182
|
- 모든 Alfred 대화에서 사용됨
|
|
178
183
|
|
|
179
|
-
|
|
180
|
-
```
|
|
181
|
-
|
|
184
|
+
**설정 완료 출력 예시**:
|
|
185
|
+
```markdown
|
|
186
|
+
✅ 초기 설정 완료!
|
|
182
187
|
|
|
183
|
-
|
|
188
|
+
언어: 한국어 (ko)
|
|
189
|
+
닉네임: GOOS
|
|
190
|
+
|
|
191
|
+
이제 GOOS님의 프로젝트 환경 분석으로 진행하겠습니다...
|
|
184
192
|
```
|
|
185
193
|
|
|
186
194
|
### 0.3 STEP 1로 전환
|
|
@@ -192,16 +200,6 @@ Alfred가 선택된 닉네임을 다음과 같이 저장합니다:
|
|
|
192
200
|
- 생성된 문서 (product.md, structure.md, tech.md)가 선택된 언어로 작성됨
|
|
193
201
|
- CLAUDE.md가 선택된 언어와 사용자 닉네임을 표시함
|
|
194
202
|
|
|
195
|
-
**한국어 선택 시 출력 예시**:
|
|
196
|
-
```markdown
|
|
197
|
-
✅ 설정 완료!
|
|
198
|
-
|
|
199
|
-
언어: 한국어 (ko)
|
|
200
|
-
닉네임: GOOS
|
|
201
|
-
|
|
202
|
-
이제 GOOS님의 프로젝트 환경 분석으로 진행하겠습니다...
|
|
203
|
-
```
|
|
204
|
-
|
|
205
203
|
---
|
|
206
204
|
|
|
207
205
|
## 🚀 STEP 1: Environmental analysis and interview plan development
|
|
@@ -22,6 +22,12 @@ allowed-tools:
|
|
|
22
22
|
|
|
23
23
|
# 🏗️ MoAI-ADK Step 1: Establish a plan (Plan) - Always make a plan first and then proceed.
|
|
24
24
|
> **Note**: Interactive prompts use `AskUserQuestion tool (documented in moai-alfred-interactive-questions skill)` for TUI selection menus. The skill is loaded on-demand when user interaction is required.
|
|
25
|
+
>
|
|
26
|
+
> **Batched Design**: All AskUserQuestion calls follow batched design principles (1-4 questions per call) to minimize user interaction turns. See CLAUDE.md section "Alfred Command Completion Pattern" for details.
|
|
27
|
+
|
|
28
|
+
<!-- @CODE:ALF-WORKFLOW-001:CMD-PLAN -->
|
|
29
|
+
|
|
30
|
+
**4-Step Workflow Integration**: This command implements Steps 1-2 of Alfred's workflow (Intent Understanding → Plan Creation). See CLAUDE.md for full workflow details.
|
|
25
31
|
|
|
26
32
|
## 🎯 Command Purpose
|
|
27
33
|
|
|
@@ -25,6 +25,12 @@ allowed-tools:
|
|
|
25
25
|
|
|
26
26
|
# ⚒️ MoAI-ADK Phase 2: Run the plan - Flexible implementation strategy
|
|
27
27
|
> **Note**: Interactive prompts use `AskUserQuestion tool (documented in moai-alfred-interactive-questions skill)` for TUI selection menus. The skill is loaded on-demand when user interaction is required.
|
|
28
|
+
>
|
|
29
|
+
> **Batched Design**: All AskUserQuestion calls follow batched design principles (1-4 questions per call) to minimize user interaction turns. See CLAUDE.md section "Alfred Command Completion Pattern" for details.
|
|
30
|
+
|
|
31
|
+
<!-- @CODE:ALF-WORKFLOW-001:CMD-RUN -->
|
|
32
|
+
|
|
33
|
+
**4-Step Workflow Integration**: This command implements Step 3 of Alfred's workflow (Task Execution with TodoWrite tracking). See CLAUDE.md for full workflow details.
|
|
28
34
|
|
|
29
35
|
## 🎯 Command Purpose
|
|
30
36
|
|
|
@@ -23,6 +23,12 @@ allowed-tools:
|
|
|
23
23
|
|
|
24
24
|
# 📚 MoAI-ADK Step 3: Document Synchronization (+Optional PR Ready)
|
|
25
25
|
> **Note**: Interactive prompts use `AskUserQuestion tool (documented in moai-alfred-interactive-questions skill)` for TUI selection menus. The skill is loaded on-demand when user interaction is required.
|
|
26
|
+
>
|
|
27
|
+
> **Batched Design**: All AskUserQuestion calls follow batched design principles (1-4 questions per call) to minimize user interaction turns. See CLAUDE.md section "Alfred Command Completion Pattern" for details.
|
|
28
|
+
|
|
29
|
+
<!-- @CODE:ALF-WORKFLOW-001:CMD-SYNC -->
|
|
30
|
+
|
|
31
|
+
**4-Step Workflow Integration**: This command implements Step 4 of Alfred's workflow (Report & Commit with conditional report generation). See CLAUDE.md for full workflow details.
|
|
26
32
|
|
|
27
33
|
## 🚀 START HERE
|
|
28
34
|
|