moai-adk 0.3.9__tar.gz → 0.3.10__tar.gz
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-0.3.9 → moai_adk-0.3.10}/PKG-INFO +1 -1
- {moai_adk-0.3.9 → moai_adk-0.3.10}/pyproject.toml +1 -1
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/cli/commands/init.py +27 -34
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/template/processor.py +14 -25
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/core/__init__.py +6 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/core/context.py +2 -45
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/settings.json +10 -3
- moai_adk-0.3.9/src/moai_adk/templates/.claude/hooks/alfred/core/tags.py +0 -244
- {moai_adk-0.3.9 → moai_adk-0.3.10}/.gitignore +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/LICENSE +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/README.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/__init__.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/__main__.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/cli/__init__.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/cli/commands/__init__.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/cli/commands/backup.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/cli/commands/doctor.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/cli/commands/restore.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/cli/commands/status.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/cli/commands/update.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/cli/main.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/cli/prompts/__init__.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/cli/prompts/init_prompts.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/__init__.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/git/__init__.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/git/branch.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/git/branch_manager.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/git/checkpoint.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/git/commit.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/git/event_detector.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/git/manager.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/project/__init__.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/project/backup_utils.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/project/checker.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/project/detector.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/project/initializer.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/project/phase_executor.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/project/validator.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/quality/__init__.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/quality/trust_checker.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/quality/validators/__init__.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/quality/validators/base_validator.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/template/__init__.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/template/backup.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/template/config.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/template/languages.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/core/template/merger.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/cc-manager.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/debug-helper.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/doc-syncer.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/git-manager.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/implementation-planner.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/project-manager.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/quality-gate.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/spec-builder.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/tag-agent.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/trust-checker.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/commands/alfred/0-project.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/commands/alfred/1-spec.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/commands/alfred/2-build.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/commands/alfred/3-sync.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/README.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/core/checkpoint.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/core/project.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/handlers/notification.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/handlers/session.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/handlers/tool.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/handlers/user.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.github/workflows/moai-gitflow.yml +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.gitignore +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.moai/config.json +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.moai/hooks/pre-push.sample +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.moai/memory/development-guide.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.moai/memory/gitflow-protection-policy.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.moai/memory/spec-metadata.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.moai/project/product.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.moai/project/structure.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.moai/project/tech.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/CLAUDE.md +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/__init__.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/utils/__init__.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/utils/banner.py +0 -0
- {moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/utils/logger.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: moai-adk
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.10
|
|
4
4
|
Summary: MoAI Agentic Development Kit - SPEC-First TDD with Alfred SuperAgent
|
|
5
5
|
Project-URL: Homepage, https://github.com/modu-ai/moai-adk
|
|
6
6
|
Project-URL: Repository, https://github.com/modu-ai/moai-adk
|
|
@@ -134,45 +134,20 @@ def init(
|
|
|
134
134
|
|
|
135
135
|
console.print("\n[cyan]🚀 Starting installation...[/cyan]\n")
|
|
136
136
|
|
|
137
|
-
# 4. Check for reinitialization (SPEC-INIT-003 v0.3.0)
|
|
137
|
+
# 4. Check for reinitialization (SPEC-INIT-003 v0.3.0) - DEFAULT TO FORCE MODE
|
|
138
138
|
initializer = ProjectInitializer(project_path)
|
|
139
139
|
|
|
140
140
|
if initializer.is_initialized():
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
console.print("\n[
|
|
144
|
-
console.print(f"[dim] Location: {project_path}/.moai/[/dim]")
|
|
145
|
-
console.print("[dim] Use --force to reinitialize or interactive mode[/dim]\n")
|
|
146
|
-
raise click.Abort()
|
|
147
|
-
|
|
148
|
-
if force:
|
|
149
|
-
# Force mode: Reinitialize without confirmation
|
|
150
|
-
console.print("\n[green]🔄 Force reinitializing project...[/green]\n")
|
|
141
|
+
# Always reinitialize without confirmation (force mode by default)
|
|
142
|
+
if non_interactive:
|
|
143
|
+
console.print("\n[green]🔄 Reinitializing project (force mode)...[/green]\n")
|
|
151
144
|
else:
|
|
152
|
-
# Interactive mode:
|
|
153
|
-
console.print("\n
|
|
154
|
-
console.print(
|
|
155
|
-
|
|
156
|
-
console.print("[cyan]This will:[/cyan]")
|
|
157
|
-
console.print(" ✓ Backup existing files to .moai-backups/{timestamp}/")
|
|
158
|
-
console.print(" • CLAUDE.md")
|
|
159
|
-
console.print(" • .claude/ (settings, commands, hooks)")
|
|
160
|
-
console.print(" • .moai/ (all configurations and specs)")
|
|
161
|
-
console.print(" ✓ Update template files from moai-adk v0.3.0")
|
|
162
|
-
console.print(" • .claude/ → Latest Alfred commands")
|
|
163
|
-
console.print(" • .moai/memory/ → Latest development guides")
|
|
164
|
-
console.print(" • CLAUDE.md → Latest project documentation")
|
|
165
|
-
console.print(" ✓ Preserve your content")
|
|
166
|
-
console.print(" • .moai/project/ (product/structure/tech.md)")
|
|
167
|
-
console.print(" • .moai/specs/ (all SPEC documents)\n")
|
|
168
|
-
|
|
169
|
-
if not Confirm.ask("Would you like to update the project templates?", default=True):
|
|
170
|
-
console.print("\n[yellow]Reinit cancelled.[/yellow]\n")
|
|
171
|
-
raise click.Abort()
|
|
172
|
-
|
|
173
|
-
console.print("\n[green]🔄 Starting reinit process...[/green]\n")
|
|
145
|
+
# Interactive mode: Simple notification
|
|
146
|
+
console.print("\n[cyan]🔄 Reinitializing project...[/cyan]")
|
|
147
|
+
console.print(" Backup will be created at .moai-backups/{timestamp}/\n")
|
|
174
148
|
|
|
175
149
|
# 5. Initialize project (Progress Bar with 5 phases)
|
|
150
|
+
# Always allow reinit (force mode by default)
|
|
176
151
|
is_reinit = initializer.is_initialized()
|
|
177
152
|
|
|
178
153
|
# Reinit mode: set config.json optimized to false (v0.3.1+)
|
|
@@ -220,7 +195,7 @@ def init(
|
|
|
220
195
|
language=language,
|
|
221
196
|
backup_enabled=True,
|
|
222
197
|
progress_callback=callback,
|
|
223
|
-
reinit=
|
|
198
|
+
reinit=True, # Always allow reinit (force mode by default)
|
|
224
199
|
)
|
|
225
200
|
|
|
226
201
|
# 6. Output results
|
|
@@ -241,7 +216,25 @@ def init(
|
|
|
241
216
|
f" [dim]📄 Files:[/dim] {len(result.created_files)} created"
|
|
242
217
|
)
|
|
243
218
|
console.print(f" [dim]⏱️ Duration:[/dim] {result.duration}ms")
|
|
219
|
+
|
|
220
|
+
# Show backup info if reinitialized
|
|
221
|
+
if is_reinit:
|
|
222
|
+
backup_dir = project_path / ".moai-backups"
|
|
223
|
+
if backup_dir.exists():
|
|
224
|
+
latest_backup = max(backup_dir.iterdir(), key=lambda p: p.stat().st_mtime)
|
|
225
|
+
console.print(f" [dim]💾 Backup:[/dim] {latest_backup.name}/")
|
|
226
|
+
|
|
244
227
|
console.print(f"\n{separator}")
|
|
228
|
+
|
|
229
|
+
# Show config merge notice if reinitialized
|
|
230
|
+
if is_reinit:
|
|
231
|
+
console.print("\n[yellow]⚠️ Configuration Notice:[/yellow]")
|
|
232
|
+
console.print(" All template files have been [bold]force overwritten[/bold]")
|
|
233
|
+
console.print(" Previous files are backed up in [cyan].moai-backups/{timestamp}/[/cyan]")
|
|
234
|
+
console.print("\n [cyan]To merge your previous config:[/cyan]")
|
|
235
|
+
console.print(" Run [bold]/alfred:0-project[/bold] command in Claude Code")
|
|
236
|
+
console.print(" It will merge backup config when [dim]optimized=false[/dim]\n")
|
|
237
|
+
|
|
245
238
|
console.print("\n[cyan]🚀 Next Steps:[/cyan]")
|
|
246
239
|
if not is_current_dir:
|
|
247
240
|
console.print(
|
|
@@ -23,7 +23,8 @@ class TemplateProcessor:
|
|
|
23
23
|
".moai/specs/", # User SPEC documents
|
|
24
24
|
".moai/reports/", # User reports
|
|
25
25
|
".moai/project/", # User project documents (product/structure/tech.md)
|
|
26
|
-
|
|
26
|
+
# config.json is now FORCE OVERWRITTEN (backup in .moai-backups/)
|
|
27
|
+
# Merge via /alfred:0-project when optimized=false
|
|
27
28
|
]
|
|
28
29
|
|
|
29
30
|
# Paths excluded from backups
|
|
@@ -277,7 +278,7 @@ class TemplateProcessor:
|
|
|
277
278
|
if not silent:
|
|
278
279
|
console.print(f" ✅ .claude/{folder}/ overwritten")
|
|
279
280
|
|
|
280
|
-
# 2. Copy other files/folders individually (
|
|
281
|
+
# 2. Copy other files/folders individually (FORCE OVERWRITE all files)
|
|
281
282
|
all_warnings = []
|
|
282
283
|
for item in src.iterdir():
|
|
283
284
|
rel_path = item.relative_to(src)
|
|
@@ -288,16 +289,12 @@ class TemplateProcessor:
|
|
|
288
289
|
continue
|
|
289
290
|
|
|
290
291
|
if item.is_file():
|
|
291
|
-
#
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
warnings = self._copy_file_with_substitution(item, dst_item)
|
|
295
|
-
all_warnings.extend(warnings)
|
|
292
|
+
# FORCE OVERWRITE: Always copy files (no skip)
|
|
293
|
+
warnings = self._copy_file_with_substitution(item, dst_item)
|
|
294
|
+
all_warnings.extend(warnings)
|
|
296
295
|
elif item.is_dir():
|
|
297
|
-
#
|
|
298
|
-
|
|
299
|
-
# Recursively copy directory with substitution
|
|
300
|
-
self._copy_dir_with_substitution(item, dst_item)
|
|
296
|
+
# FORCE OVERWRITE: Always copy directories (no skip)
|
|
297
|
+
self._copy_dir_with_substitution(item, dst_item)
|
|
301
298
|
|
|
302
299
|
# Print warnings if any
|
|
303
300
|
if all_warnings and not silent:
|
|
@@ -362,9 +359,7 @@ class TemplateProcessor:
|
|
|
362
359
|
|
|
363
360
|
dst_item = dst / rel_path
|
|
364
361
|
if item.is_file():
|
|
365
|
-
#
|
|
366
|
-
if dst_item.exists():
|
|
367
|
-
continue
|
|
362
|
+
# FORCE OVERWRITE: Always copy files (no skip)
|
|
368
363
|
dst_item.parent.mkdir(parents=True, exist_ok=True)
|
|
369
364
|
# Copy with variable substitution
|
|
370
365
|
warnings = self._copy_file_with_substitution(item, dst_item)
|
|
@@ -382,7 +377,7 @@ class TemplateProcessor:
|
|
|
382
377
|
console.print(" ✅ .moai/ copy complete (variables substituted)")
|
|
383
378
|
|
|
384
379
|
def _copy_claude_md(self, silent: bool = False) -> None:
|
|
385
|
-
"""Copy CLAUDE.md with
|
|
380
|
+
"""Copy CLAUDE.md with FORCE OVERWRITE."""
|
|
386
381
|
src = self.template_root / "CLAUDE.md"
|
|
387
382
|
dst = self.target_path / "CLAUDE.md"
|
|
388
383
|
|
|
@@ -391,16 +386,10 @@ class TemplateProcessor:
|
|
|
391
386
|
console.print("⚠️ CLAUDE.md template not found")
|
|
392
387
|
return
|
|
393
388
|
|
|
394
|
-
#
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
console.print(" 🔄 CLAUDE.md merged (project information preserved)")
|
|
399
|
-
else:
|
|
400
|
-
# Copy with variable substitution
|
|
401
|
-
self._copy_file_with_substitution(src, dst)
|
|
402
|
-
if not silent:
|
|
403
|
-
console.print(" ✅ CLAUDE.md copy complete")
|
|
389
|
+
# FORCE OVERWRITE: Always copy template (backup already created in Phase 1)
|
|
390
|
+
self._copy_file_with_substitution(src, dst)
|
|
391
|
+
if not silent:
|
|
392
|
+
console.print(" ✅ CLAUDE.md overwritten (backup available in .moai-backups/)")
|
|
404
393
|
|
|
405
394
|
def _merge_claude_md(self, src: Path, dst: Path) -> None:
|
|
406
395
|
"""Delegate the smart merge for CLAUDE.md.
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/core/__init__.py
RENAMED
|
@@ -77,3 +77,9 @@ class HookResult:
|
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
__all__ = ["HookPayload", "HookResult"]
|
|
80
|
+
|
|
81
|
+
# Note: core module exports:
|
|
82
|
+
# - HookPayload, HookResult (type definitions)
|
|
83
|
+
# - project.py: detect_language, get_git_info, count_specs, get_project_language
|
|
84
|
+
# - context.py: get_jit_context
|
|
85
|
+
# - checkpoint.py: detect_risky_operation, create_checkpoint, log_checkpoint, list_checkpoints
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/core/context.py
RENAMED
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""Context Engineering utilities
|
|
3
3
|
|
|
4
|
-
JIT (Just-in-Time) Retrieval
|
|
4
|
+
JIT (Just-in-Time) Retrieval
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
import time
|
|
8
7
|
from pathlib import Path
|
|
9
|
-
from typing import Any
|
|
10
|
-
|
|
11
|
-
# Workflow context shared across phases
|
|
12
|
-
_workflow_context: dict[str, Any] = {}
|
|
13
8
|
|
|
14
9
|
|
|
15
10
|
def get_jit_context(prompt: str, cwd: str) -> list[str]:
|
|
@@ -69,42 +64,4 @@ def get_jit_context(prompt: str, cwd: str) -> list[str]:
|
|
|
69
64
|
return context_files
|
|
70
65
|
|
|
71
66
|
|
|
72
|
-
|
|
73
|
-
"""Store per-phase workflow context data.
|
|
74
|
-
|
|
75
|
-
Args:
|
|
76
|
-
phase: ``"analysis"``, ``"implementation"`` or ``"verification"``.
|
|
77
|
-
data: Payload to share with later phases.
|
|
78
|
-
|
|
79
|
-
Notes:
|
|
80
|
-
- Enables reuse of expensive analysis across phases.
|
|
81
|
-
- Entries expire after 10 minutes to avoid stale data.
|
|
82
|
-
"""
|
|
83
|
-
_workflow_context[phase] = {"data": data, "timestamp": time.time()}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
def load_phase_context(phase: str) -> dict | None:
|
|
87
|
-
"""Load previously stored workflow context for a phase.
|
|
88
|
-
|
|
89
|
-
Returns:
|
|
90
|
-
Stored context data or ``None`` when expired or missing.
|
|
91
|
-
"""
|
|
92
|
-
if phase in _workflow_context:
|
|
93
|
-
ctx = _workflow_context[phase]
|
|
94
|
-
# Only accept entries that are younger than 10 minutes
|
|
95
|
-
if time.time() - ctx["timestamp"] < 600:
|
|
96
|
-
return ctx["data"]
|
|
97
|
-
return None
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def clear_workflow_context():
|
|
101
|
-
"""Clear all cached workflow context (call at workflow end)."""
|
|
102
|
-
_workflow_context.clear()
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
__all__ = [
|
|
106
|
-
"get_jit_context",
|
|
107
|
-
"save_phase_context",
|
|
108
|
-
"load_phase_context",
|
|
109
|
-
"clear_workflow_context",
|
|
110
|
-
]
|
|
67
|
+
__all__ = ["get_jit_context"]
|
|
@@ -86,7 +86,9 @@
|
|
|
86
86
|
"Bash(uv remove:*)",
|
|
87
87
|
"Bash(pip install:*)",
|
|
88
88
|
"Bash(pip3 install:*)",
|
|
89
|
-
"Bash(rm:*)"
|
|
89
|
+
"Bash(rm:*)",
|
|
90
|
+
"Bash(sudo:*)",
|
|
91
|
+
"Bash(rm -rf:*)"
|
|
90
92
|
],
|
|
91
93
|
"deny": [
|
|
92
94
|
"Read(./.env)",
|
|
@@ -95,8 +97,13 @@
|
|
|
95
97
|
"Read(~/.ssh/**)",
|
|
96
98
|
"Read(~/.aws/**)",
|
|
97
99
|
"Read(~/.config/gcloud/**)",
|
|
98
|
-
"Bash(
|
|
99
|
-
"Bash(rm -rf
|
|
100
|
+
"Bash(rm -rf /:*)",
|
|
101
|
+
"Bash(rm -rf /*:*)",
|
|
102
|
+
"Bash(rm -rf C\\:/:*)",
|
|
103
|
+
"Bash(rm -rf C\\:/*:*)",
|
|
104
|
+
"Bash(del /S /Q C\\:/:*)",
|
|
105
|
+
"Bash(rmdir /S /Q C\\:/:*)",
|
|
106
|
+
"Bash(format:*)",
|
|
100
107
|
"Bash(chmod -R 777:*)",
|
|
101
108
|
"Bash(dd:*)",
|
|
102
109
|
"Bash(mkfs:*)",
|
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""TAG search and verification system
|
|
3
|
-
|
|
4
|
-
TAG 검색, 체인 검증, 라이브러리 버전 캐싱
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import json
|
|
8
|
-
import subprocess
|
|
9
|
-
import time
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
|
|
12
|
-
# TAG search cache: {pattern: (results, mtime_hash, cached_at)}
|
|
13
|
-
_tag_cache: dict[str, tuple[list[dict], float, float]] = {}
|
|
14
|
-
|
|
15
|
-
# Library version cache: {lib_name: (version, timestamp)}
|
|
16
|
-
_lib_version_cache: dict[str, tuple[str, float]] = {}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def _get_dir_mtime_hash(paths: list[str]) -> float:
|
|
20
|
-
"""Calculate a directory-wide mtime hash used for cache invalidation.
|
|
21
|
-
|
|
22
|
-
Args:
|
|
23
|
-
paths: List of directory paths to inspect.
|
|
24
|
-
|
|
25
|
-
Returns:
|
|
26
|
-
Highest modification timestamp (float) across all files.
|
|
27
|
-
|
|
28
|
-
Notes:
|
|
29
|
-
- Any file change bumps the hash and invalidates the cache.
|
|
30
|
-
- Missing or inaccessible directories are ignored.
|
|
31
|
-
"""
|
|
32
|
-
max_mtime = 0.0
|
|
33
|
-
for path in paths:
|
|
34
|
-
path_obj = Path(path)
|
|
35
|
-
if not path_obj.exists():
|
|
36
|
-
continue
|
|
37
|
-
|
|
38
|
-
try:
|
|
39
|
-
for file_path in path_obj.rglob("*"):
|
|
40
|
-
if file_path.is_file():
|
|
41
|
-
max_mtime = max(max_mtime, file_path.stat().st_mtime)
|
|
42
|
-
except (OSError, PermissionError):
|
|
43
|
-
# Skip directories we cannot read
|
|
44
|
-
continue
|
|
45
|
-
|
|
46
|
-
return max_mtime
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def search_tags(pattern: str, scope: list[str] | None = None, cache_ttl: int = 60) -> list[dict]:
|
|
50
|
-
"""Search TAG markers using an in-memory cache.
|
|
51
|
-
|
|
52
|
-
Args:
|
|
53
|
-
pattern: Regex pattern (for example ``'@SPEC:AUTH-.*'``).
|
|
54
|
-
scope: List of directories to scan. Defaults to specs/src/tests.
|
|
55
|
-
cache_ttl: Cache time-to-live in seconds (default 60).
|
|
56
|
-
|
|
57
|
-
Returns:
|
|
58
|
-
List of matches such as ``{"file": "path", "line": 10, "tag": "...", "content": "..."}``.
|
|
59
|
-
|
|
60
|
-
Notes:
|
|
61
|
-
- Cache integrity relies on directory mtimes plus TTL.
|
|
62
|
-
- Cache hits avoid spawning ``rg`` while misses shell out (≈13ms).
|
|
63
|
-
- Uses ``rg --json`` output for structured parsing.
|
|
64
|
-
"""
|
|
65
|
-
if scope is None:
|
|
66
|
-
scope = [".moai/specs/", "src/", "tests/"]
|
|
67
|
-
|
|
68
|
-
cache_key = f"{pattern}:{':'.join(scope)}"
|
|
69
|
-
|
|
70
|
-
current_mtime = _get_dir_mtime_hash(scope)
|
|
71
|
-
cache_entry = _tag_cache.get(cache_key)
|
|
72
|
-
|
|
73
|
-
# Serve cached results when still valid
|
|
74
|
-
if cache_entry:
|
|
75
|
-
cached_results, cached_mtime, cached_at = cache_entry
|
|
76
|
-
ttl_valid = time.time() - cached_at < cache_ttl
|
|
77
|
-
|
|
78
|
-
# Matching mtime and a fresh TTL means we can reuse the cache
|
|
79
|
-
if current_mtime == cached_mtime and ttl_valid:
|
|
80
|
-
return cached_results
|
|
81
|
-
|
|
82
|
-
# Cache miss → invoke ripgrep
|
|
83
|
-
cmd = ["rg", pattern, "--json"] + scope
|
|
84
|
-
|
|
85
|
-
try:
|
|
86
|
-
result = subprocess.run(cmd, capture_output=True, text=True, timeout=5, check=False)
|
|
87
|
-
except (subprocess.TimeoutExpired, FileNotFoundError):
|
|
88
|
-
# Missing rg or a timeout returns an empty list
|
|
89
|
-
return []
|
|
90
|
-
|
|
91
|
-
matches = []
|
|
92
|
-
for line in result.stdout.strip().split("\n"):
|
|
93
|
-
if not line:
|
|
94
|
-
continue
|
|
95
|
-
try:
|
|
96
|
-
data = json.loads(line)
|
|
97
|
-
if data.get("type") == "match":
|
|
98
|
-
matches.append(
|
|
99
|
-
{
|
|
100
|
-
"file": data["data"]["path"]["text"],
|
|
101
|
-
"line": data["data"]["line_number"],
|
|
102
|
-
"tag": data["data"]["lines"]["text"].strip(),
|
|
103
|
-
"content": data["data"]["lines"]["text"],
|
|
104
|
-
}
|
|
105
|
-
)
|
|
106
|
-
except (json.JSONDecodeError, KeyError):
|
|
107
|
-
# Ignore malformed JSON lines
|
|
108
|
-
continue
|
|
109
|
-
|
|
110
|
-
# Persist results with the current mtime snapshot
|
|
111
|
-
_tag_cache[cache_key] = (matches, _get_dir_mtime_hash(scope), time.time())
|
|
112
|
-
|
|
113
|
-
return matches
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
def verify_tag_chain(spec_id: str) -> dict:
|
|
117
|
-
"""Verify a TAG chain across ``@SPEC`` → ``@TEST`` → ``@CODE``.
|
|
118
|
-
|
|
119
|
-
Args:
|
|
120
|
-
spec_id: SPEC identifier (for example ``"AUTH-001"``).
|
|
121
|
-
|
|
122
|
-
Returns:
|
|
123
|
-
Dictionary with keys ``complete``, ``spec``, ``test``, ``code`` and ``orphans``.
|
|
124
|
-
|
|
125
|
-
Notes:
|
|
126
|
-
- Orphans capture TAGs found in code/tests without a SPEC.
|
|
127
|
-
- A chain is complete only when all three categories contain matches.
|
|
128
|
-
- Relies on ``search_tags`` so cached scans remain inexpensive.
|
|
129
|
-
"""
|
|
130
|
-
chain = {
|
|
131
|
-
"spec": search_tags(f"@SPEC:{spec_id}", [".moai/specs/"]),
|
|
132
|
-
"test": search_tags(f"@TEST:{spec_id}", ["tests/"]),
|
|
133
|
-
"code": search_tags(f"@CODE:{spec_id}", ["src/"]),
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
orphans = []
|
|
137
|
-
if chain["code"] and not chain["spec"]:
|
|
138
|
-
orphans.extend(chain["code"])
|
|
139
|
-
if chain["test"] and not chain["spec"]:
|
|
140
|
-
orphans.extend(chain["test"])
|
|
141
|
-
|
|
142
|
-
return {
|
|
143
|
-
"complete": bool(chain["spec"] and chain["test"] and chain["code"]),
|
|
144
|
-
**chain,
|
|
145
|
-
"orphans": orphans,
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
def find_all_tags_by_type(tag_type: str = "SPEC") -> dict:
|
|
150
|
-
"""Return TAG IDs grouped by domain for the requested type.
|
|
151
|
-
|
|
152
|
-
Args:
|
|
153
|
-
tag_type: TAG category (``SPEC``, ``TEST``, ``CODE`` or ``DOC``).
|
|
154
|
-
|
|
155
|
-
Returns:
|
|
156
|
-
Dictionary like ``{"AUTH": ["AUTH-001", "AUTH-002"], ...}``.
|
|
157
|
-
|
|
158
|
-
Notes:
|
|
159
|
-
- Domain is derived from the ``FOO-123`` prefix.
|
|
160
|
-
- Deduplicates repeated matches within the same domain.
|
|
161
|
-
- Fetches data via ``search_tags`` so caching still applies.
|
|
162
|
-
"""
|
|
163
|
-
tags = search_tags(f"@{tag_type}:([A-Z]+-[0-9]{{3}})")
|
|
164
|
-
|
|
165
|
-
by_domain = {}
|
|
166
|
-
for tag in tags:
|
|
167
|
-
# @SPEC:AUTH-001 → AUTH
|
|
168
|
-
try:
|
|
169
|
-
tag_id = tag["tag"].split(":")[1]
|
|
170
|
-
domain = "-".join(tag_id.split("-")[:-1])
|
|
171
|
-
|
|
172
|
-
if domain not in by_domain:
|
|
173
|
-
by_domain[domain] = []
|
|
174
|
-
if tag_id not in by_domain[domain]:
|
|
175
|
-
by_domain[domain].append(tag_id)
|
|
176
|
-
except IndexError:
|
|
177
|
-
# 파싱 실패 무시
|
|
178
|
-
continue
|
|
179
|
-
|
|
180
|
-
return by_domain
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
def suggest_tag_reuse(keyword: str, tag_type: str = "SPEC") -> list[str]:
|
|
184
|
-
"""Suggest existing TAG IDs that match the supplied keyword.
|
|
185
|
-
|
|
186
|
-
Args:
|
|
187
|
-
keyword: Keyword used to match domain names (case-insensitive).
|
|
188
|
-
tag_type: TAG category (defaults to ``SPEC``).
|
|
189
|
-
|
|
190
|
-
Returns:
|
|
191
|
-
A list of up to five suggested TAG IDs.
|
|
192
|
-
|
|
193
|
-
Notes:
|
|
194
|
-
- Encourages reuse to avoid creating duplicate TAGs.
|
|
195
|
-
- Performs a simple substring match against domain names.
|
|
196
|
-
"""
|
|
197
|
-
all_tags = find_all_tags_by_type(tag_type)
|
|
198
|
-
suggestions = []
|
|
199
|
-
|
|
200
|
-
keyword_lower = keyword.lower()
|
|
201
|
-
for domain, tag_ids in all_tags.items():
|
|
202
|
-
if keyword_lower in domain.lower():
|
|
203
|
-
suggestions.extend(tag_ids)
|
|
204
|
-
|
|
205
|
-
return suggestions[:5] # Cap results at five
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
def get_library_version(lib_name: str, cache_ttl: int = 86400) -> str | None:
|
|
209
|
-
"""Get the cached latest stable version for a library.
|
|
210
|
-
|
|
211
|
-
Args:
|
|
212
|
-
lib_name: Package name (for example ``"fastapi"``).
|
|
213
|
-
cache_ttl: Cache TTL in seconds (defaults to 24 hours).
|
|
214
|
-
|
|
215
|
-
Returns:
|
|
216
|
-
Cached version string or ``None`` when the cache is cold.
|
|
217
|
-
|
|
218
|
-
Notes:
|
|
219
|
-
- Cache hits skip costly web searches (saves 3–5 seconds).
|
|
220
|
-
- Agents should call ``set_library_version`` after fetching live data.
|
|
221
|
-
"""
|
|
222
|
-
# Serve cached value when still within TTL
|
|
223
|
-
if lib_name in _lib_version_cache:
|
|
224
|
-
cached_version, cached_time = _lib_version_cache[lib_name]
|
|
225
|
-
if time.time() - cached_time < cache_ttl:
|
|
226
|
-
return cached_version
|
|
227
|
-
|
|
228
|
-
# Cache miss → agent needs to perform the web search
|
|
229
|
-
return None
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
def set_library_version(lib_name: str, version: str):
|
|
233
|
-
"""Persist a library version in the cache."""
|
|
234
|
-
_lib_version_cache[lib_name] = (version, time.time())
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
__all__ = [
|
|
238
|
-
"search_tags",
|
|
239
|
-
"verify_tag_chain",
|
|
240
|
-
"find_all_tags_by_type",
|
|
241
|
-
"suggest_tag_reuse",
|
|
242
|
-
"get_library_version",
|
|
243
|
-
"set_library_version",
|
|
244
|
-
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/cc-manager.md
RENAMED
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/debug-helper.md
RENAMED
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/doc-syncer.md
RENAMED
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/git-manager.md
RENAMED
|
File without changes
|
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/project-manager.md
RENAMED
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/quality-gate.md
RENAMED
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/spec-builder.md
RENAMED
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/tag-agent.md
RENAMED
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/tdd-implementer.md
RENAMED
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/agents/alfred/trust-checker.md
RENAMED
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/commands/alfred/0-project.md
RENAMED
|
File without changes
|
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/commands/alfred/2-build.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py
RENAMED
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/core/checkpoint.py
RENAMED
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/core/project.py
RENAMED
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/handlers/session.py
RENAMED
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/handlers/tool.py
RENAMED
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.claude/hooks/alfred/handlers/user.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.github/workflows/moai-gitflow.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moai_adk-0.3.9 → moai_adk-0.3.10}/src/moai_adk/templates/.moai/memory/gitflow-protection-policy.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|