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.

Files changed (141) hide show
  1. moai_adk/__init__.py +1 -1
  2. moai_adk/__main__.py +1 -1
  3. moai_adk/cli/commands/__init__.py +1 -1
  4. moai_adk/cli/commands/doctor.py +2 -2
  5. moai_adk/cli/commands/init.py +10 -5
  6. moai_adk/cli/commands/status.py +1 -1
  7. moai_adk/cli/commands/update.py +210 -8
  8. moai_adk/cli/prompts/init_prompts.py +15 -19
  9. moai_adk/core/__init__.py +1 -1
  10. moai_adk/core/diagnostics/slash_commands.py +1 -1
  11. moai_adk/core/git/branch.py +1 -1
  12. moai_adk/core/git/manager.py +1 -1
  13. moai_adk/core/project/backup_utils.py +1 -0
  14. moai_adk/core/project/phase_executor.py +3 -1
  15. moai_adk/core/project/validator.py +3 -2
  16. moai_adk/core/quality/__init__.py +1 -1
  17. moai_adk/core/quality/trust_checker.py +1 -1
  18. moai_adk/core/quality/validators/__init__.py +1 -1
  19. moai_adk/core/quality/validators/base_validator.py +1 -1
  20. moai_adk/core/template/__init__.py +1 -1
  21. moai_adk/core/template/backup.py +12 -3
  22. moai_adk/core/template/config.py +24 -0
  23. moai_adk/core/template/languages.py +1 -1
  24. moai_adk/core/template/merger.py +74 -4
  25. moai_adk/core/template/processor.py +62 -14
  26. moai_adk/templates/.claude/agents/alfred/cc-manager.md +765 -191
  27. moai_adk/templates/.claude/agents/alfred/debug-helper.md +116 -103
  28. moai_adk/templates/.claude/agents/alfred/doc-syncer.md +130 -116
  29. moai_adk/templates/.claude/agents/alfred/git-manager.md +186 -174
  30. moai_adk/templates/.claude/agents/alfred/implementation-planner.md +227 -213
  31. moai_adk/templates/.claude/agents/alfred/project-manager.md +205 -125
  32. moai_adk/templates/.claude/agents/alfred/quality-gate.md +224 -209
  33. moai_adk/templates/.claude/agents/alfred/spec-builder.md +174 -160
  34. moai_adk/templates/.claude/agents/alfred/tag-agent.md +151 -139
  35. moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +209 -196
  36. moai_adk/templates/.claude/agents/alfred/trust-checker.md +247 -233
  37. moai_adk/templates/.claude/commands/alfred/0-project.md +856 -355
  38. moai_adk/templates/.claude/commands/alfred/1-plan.md +572 -0
  39. moai_adk/templates/.claude/commands/alfred/2-run.md +470 -0
  40. moai_adk/templates/.claude/commands/alfred/3-sync.md +366 -356
  41. moai_adk/templates/.claude/hooks/alfred/README.md +52 -52
  42. moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +44 -48
  43. moai_adk/templates/.claude/hooks/alfred/core/__init__.py +17 -17
  44. moai_adk/templates/.claude/hooks/alfred/core/checkpoint.py +59 -59
  45. moai_adk/templates/.claude/hooks/alfred/core/context.py +19 -19
  46. moai_adk/templates/.claude/hooks/alfred/core/project.py +52 -52
  47. moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +1 -1
  48. moai_adk/templates/.claude/hooks/alfred/handlers/notification.py +4 -4
  49. moai_adk/templates/.claude/hooks/alfred/handlers/session.py +30 -51
  50. moai_adk/templates/.claude/hooks/alfred/handlers/tool.py +16 -17
  51. moai_adk/templates/.claude/hooks/alfred/handlers/user.py +11 -11
  52. moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +308 -307
  53. moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +297 -296
  54. moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +191 -190
  55. moai_adk/templates/.claude/skills/moai-alfred-code-reviewer/SKILL.md +112 -0
  56. moai_adk/templates/.claude/skills/moai-alfred-debugger-pro/SKILL.md +103 -0
  57. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/SKILL.md +103 -0
  58. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/SKILL.md +95 -0
  59. moai_adk/templates/.claude/skills/moai-alfred-language-detection/SKILL.md +99 -0
  60. moai_adk/templates/.claude/skills/moai-alfred-performance-optimizer/SKILL.md +105 -0
  61. moai_adk/templates/.claude/skills/moai-alfred-refactoring-coach/SKILL.md +97 -0
  62. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/SKILL.md +97 -0
  63. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/SKILL.md +90 -0
  64. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/SKILL.md +99 -0
  65. moai_adk/templates/.claude/skills/moai-alfred-tui-survey/SKILL.md +87 -0
  66. moai_adk/templates/.claude/skills/moai-alfred-tui-survey/examples.md +62 -0
  67. moai_adk/templates/.claude/skills/moai-claude-code/SKILL.md +94 -0
  68. moai_adk/templates/.claude/skills/moai-claude-code/examples.md +513 -0
  69. moai_adk/templates/.claude/skills/moai-claude-code/reference.md +433 -0
  70. moai_adk/templates/.claude/skills/moai-claude-code/templates/agent-full.md +332 -0
  71. moai_adk/templates/.claude/skills/moai-claude-code/templates/command-full.md +384 -0
  72. moai_adk/templates/.claude/skills/moai-claude-code/templates/plugin-full.json +363 -0
  73. moai_adk/templates/.claude/skills/moai-claude-code/templates/settings-full.json +595 -0
  74. moai_adk/templates/.claude/skills/moai-claude-code/templates/skill-full.md +496 -0
  75. moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +99 -0
  76. moai_adk/templates/.claude/skills/moai-domain-cli-tool/SKILL.md +95 -0
  77. moai_adk/templates/.claude/skills/moai-domain-data-science/SKILL.md +98 -0
  78. moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +100 -0
  79. moai_adk/templates/.claude/skills/moai-domain-devops/SKILL.md +100 -0
  80. moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +99 -0
  81. moai_adk/templates/.claude/skills/moai-domain-ml/SKILL.md +99 -0
  82. moai_adk/templates/.claude/skills/moai-domain-mobile-app/SKILL.md +93 -0
  83. moai_adk/templates/.claude/skills/moai-domain-security/SKILL.md +105 -0
  84. moai_adk/templates/.claude/skills/moai-domain-web-api/SKILL.md +97 -0
  85. moai_adk/templates/.claude/skills/moai-essentials-debug/SKILL.md +102 -0
  86. moai_adk/templates/.claude/skills/moai-essentials-perf/SKILL.md +104 -0
  87. moai_adk/templates/.claude/skills/moai-essentials-refactor/SKILL.md +96 -0
  88. moai_adk/templates/.claude/skills/moai-essentials-review/SKILL.md +112 -0
  89. moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +98 -0
  90. moai_adk/templates/.claude/skills/moai-foundation-git/SKILL.md +90 -0
  91. moai_adk/templates/.claude/skills/moai-foundation-langs/SKILL.md +94 -0
  92. moai_adk/templates/.claude/skills/moai-foundation-specs/SKILL.md +93 -0
  93. moai_adk/templates/.claude/skills/moai-foundation-tags/SKILL.md +86 -0
  94. moai_adk/templates/.claude/skills/moai-foundation-trust/SKILL.md +86 -0
  95. moai_adk/templates/.claude/skills/moai-lang-c/SKILL.md +100 -0
  96. moai_adk/templates/.claude/skills/moai-lang-clojure/SKILL.md +100 -0
  97. moai_adk/templates/.claude/skills/moai-lang-cpp/SKILL.md +102 -0
  98. moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +100 -0
  99. moai_adk/templates/.claude/skills/moai-lang-dart/SKILL.md +98 -0
  100. moai_adk/templates/.claude/skills/moai-lang-elixir/SKILL.md +99 -0
  101. moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +100 -0
  102. moai_adk/templates/.claude/skills/moai-lang-haskell/SKILL.md +100 -0
  103. moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +98 -0
  104. moai_adk/templates/.claude/skills/moai-lang-javascript/SKILL.md +96 -0
  105. moai_adk/templates/.claude/skills/moai-lang-julia/SKILL.md +98 -0
  106. moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +99 -0
  107. moai_adk/templates/.claude/skills/moai-lang-lua/SKILL.md +98 -0
  108. moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +98 -0
  109. moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +96 -0
  110. moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +99 -0
  111. moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +99 -0
  112. moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +100 -0
  113. moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +100 -0
  114. moai_adk/templates/.claude/skills/moai-lang-shell/SKILL.md +100 -0
  115. moai_adk/templates/.claude/skills/moai-lang-sql/SKILL.md +100 -0
  116. moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +99 -0
  117. moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +96 -0
  118. moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +44 -43
  119. moai_adk/templates/.github/workflows/moai-gitflow.yml +36 -35
  120. moai_adk/templates/.moai/config.json +9 -6
  121. moai_adk/templates/.moai/memory/development-guide.md +220 -221
  122. moai_adk/templates/.moai/memory/gitflow-protection-policy.md +85 -85
  123. moai_adk/templates/.moai/memory/spec-metadata.md +149 -150
  124. moai_adk/templates/.moai/project/product.md +90 -90
  125. moai_adk/templates/.moai/project/structure.md +85 -85
  126. moai_adk/templates/.moai/project/tech.md +117 -117
  127. moai_adk/templates/CLAUDE.md +354 -573
  128. moai_adk/templates/__init__.py +1 -1
  129. moai_adk/utils/__init__.py +1 -1
  130. moai_adk/utils/banner.py +7 -7
  131. moai_adk/utils/logger.py +1 -1
  132. moai_adk-0.4.1.dist-info/METADATA +303 -0
  133. moai_adk-0.4.1.dist-info/RECORD +152 -0
  134. moai_adk/templates/.claude/commands/alfred/1-spec.md +0 -532
  135. moai_adk/templates/.claude/commands/alfred/2-build.md +0 -432
  136. moai_adk/templates/.moai/hooks/pre-push.sample +0 -88
  137. moai_adk-0.3.13.dist-info/METADATA +0 -1586
  138. moai_adk-0.3.13.dist-info/RECORD +0 -90
  139. {moai_adk-0.3.13.dist-info → moai_adk-0.4.1.dist-info}/WHEEL +0 -0
  140. {moai_adk-0.3.13.dist-info → moai_adk-0.4.1.dist-info}/entry_points.txt +0 -0
  141. {moai_adk-0.3.13.dist-info → moai_adk-0.4.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,4 @@
1
- # @CODE:TEMPLATE-001 | SPEC: SPEC-INIT-003.md | Chain: TEMPLATE-001
1
+ # @CODE:TEMPLATE-001 | SPEC: SPEC-INIT-003/spec.md | Chain: TEMPLATE-001
2
2
  """Template file merger (SPEC-INIT-003 v0.3.0).
3
3
 
4
4
  Intelligently merges existing user files with new templates.
@@ -15,6 +15,11 @@ from typing import Any
15
15
  class TemplateMerger:
16
16
  """Encapsulate template merging logic."""
17
17
 
18
+ PROJECT_INFO_HEADERS = (
19
+ "## 프로젝트 정보",
20
+ "## Project Information",
21
+ )
22
+
18
23
  def __init__(self, target_path: Path) -> None:
19
24
  """Initialize the merger.
20
25
 
@@ -34,9 +39,9 @@ class TemplateMerger:
34
39
  template_path: Template CLAUDE.md.
35
40
  existing_path: Existing CLAUDE.md.
36
41
  """
37
- # Extract the existing "## 프로젝트 정보" section
42
+ # Extract the existing project information section
38
43
  existing_content = existing_path.read_text(encoding="utf-8")
39
- project_info_start = existing_content.find("## 프로젝트 정보")
44
+ project_info_start, _ = self._find_project_info_section(existing_content)
40
45
  project_info = ""
41
46
  if project_info_start != -1:
42
47
  # Extract until EOF
@@ -48,7 +53,7 @@ class TemplateMerger:
48
53
  # Merge when project info exists
49
54
  if project_info:
50
55
  # Remove the project info section from the template
51
- template_project_start = template_content.find("## 프로젝트 정보")
56
+ template_project_start, _ = self._find_project_info_section(template_content)
52
57
  if template_project_start != -1:
53
58
  template_content = template_content[:template_project_start].rstrip()
54
59
 
@@ -59,6 +64,14 @@ class TemplateMerger:
59
64
  # No project info; copy the template as-is
60
65
  shutil.copy2(template_path, existing_path)
61
66
 
67
+ def _find_project_info_section(self, content: str) -> tuple[int, str | None]:
68
+ """Find the project information header in the given content."""
69
+ for header in self.PROJECT_INFO_HEADERS:
70
+ index = content.find(header)
71
+ if index != -1:
72
+ return index, header
73
+ return -1, None
74
+
62
75
  def merge_gitignore(self, template_path: Path, existing_path: Path) -> None:
63
76
  """.gitignore merge.
64
77
 
@@ -115,3 +128,60 @@ class TemplateMerger:
115
128
  }
116
129
 
117
130
  return new_config
131
+
132
+ def merge_settings_json(self, template_path: Path, existing_path: Path, backup_path: Path | None = None) -> None:
133
+ """Smart merge for .claude/settings.json.
134
+
135
+ Rules:
136
+ - env: shallow merge (user variables preserved)
137
+ - permissions.allow: array merge (deduplicated)
138
+ - permissions.deny: template priority (security)
139
+ - hooks: template priority
140
+
141
+ Args:
142
+ template_path: Template settings.json.
143
+ existing_path: Existing settings.json.
144
+ backup_path: Backup settings.json (optional, for user settings extraction).
145
+ """
146
+ # Load template
147
+ template_data = json.loads(template_path.read_text(encoding="utf-8"))
148
+
149
+ # Load backup or existing for user settings
150
+ user_data: dict[str, Any] = {}
151
+ if backup_path and backup_path.exists():
152
+ user_data = json.loads(backup_path.read_text(encoding="utf-8"))
153
+ elif existing_path.exists():
154
+ user_data = json.loads(existing_path.read_text(encoding="utf-8"))
155
+
156
+ # Merge env (shallow merge, user variables preserved)
157
+ merged_env = {**template_data.get("env", {}), **user_data.get("env", {})}
158
+
159
+ # Merge permissions.allow (deduplicated array merge)
160
+ template_allow = set(template_data.get("permissions", {}).get("allow", []))
161
+ user_allow = set(user_data.get("permissions", {}).get("allow", []))
162
+ merged_allow = sorted(template_allow | user_allow)
163
+
164
+ # permissions.deny: template priority (security)
165
+ merged_deny = template_data.get("permissions", {}).get("deny", [])
166
+
167
+ # permissions.ask: template priority + user additions
168
+ template_ask = set(template_data.get("permissions", {}).get("ask", []))
169
+ user_ask = set(user_data.get("permissions", {}).get("ask", []))
170
+ merged_ask = sorted(template_ask | user_ask)
171
+
172
+ # Build final merged settings
173
+ merged = {
174
+ "env": merged_env,
175
+ "hooks": template_data.get("hooks", {}), # Template priority
176
+ "permissions": {
177
+ "defaultMode": template_data.get("permissions", {}).get("defaultMode", "default"),
178
+ "allow": merged_allow,
179
+ "ask": merged_ask,
180
+ "deny": merged_deny
181
+ }
182
+ }
183
+
184
+ existing_path.write_text(
185
+ json.dumps(merged, indent=2, ensure_ascii=False) + "\n",
186
+ encoding="utf-8"
187
+ )
@@ -1,4 +1,4 @@
1
- # @CODE:TEMPLATE-001 | SPEC: SPEC-INIT-003.md | Chain: TEMPLATE-001
1
+ # @CODE:TEMPLATE-001 | SPEC: SPEC-INIT-003/spec.md | Chain: TEMPLATE-001
2
2
  """Template copy and backup processor (SPEC-INIT-003 v0.3.0: preserve user content)."""
3
3
 
4
4
  from __future__ import annotations
@@ -178,6 +178,7 @@ class TemplateProcessor:
178
178
 
179
179
  self._copy_claude(silent)
180
180
  self._copy_moai(silent)
181
+ self._copy_github(silent)
181
182
  self._copy_claude_md(silent)
182
183
  self._copy_gitignore(silent)
183
184
 
@@ -237,7 +238,7 @@ class TemplateProcessor:
237
238
  Strategy:
238
239
  - Alfred folders (commands/agents/hooks/output-styles/alfred) → copy wholesale (delete & overwrite)
239
240
  * Creates individual backup before deletion for safety
240
- * Commands: 0-project.md, 1-spec.md, 2-build.md, 3-sync.md
241
+ * Commands: 0-project.md, 1-plan.md, 2-run.md, 3-sync.md
241
242
  - Other files/folders → copy individually (preserve existing)
242
243
  """
243
244
  src = self.template_root / ".claude"
@@ -256,7 +257,7 @@ class TemplateProcessor:
256
257
  # Alfred folders to copy wholesale (overwrite)
257
258
  alfred_folders = [
258
259
  "hooks/alfred",
259
- "commands/alfred", # Contains 0-project.md, 1-spec.md, 2-build.md, 3-sync.md
260
+ "commands/alfred", # Contains 0-project.md, 1-plan.md, 2-run.md, 3-sync.md
260
261
  "output-styles/alfred",
261
262
  "agents/alfred",
262
263
  ]
@@ -267,9 +268,8 @@ class TemplateProcessor:
267
268
  dst_folder = dst / folder
268
269
 
269
270
  if src_folder.exists():
270
- # Backup this folder before deletion (safety measure)
271
+ # Remove existing folder (backup is already handled by create_backup() in update.py)
271
272
  if dst_folder.exists():
272
- self._backup_alfred_folder(dst_folder, folder)
273
273
  shutil.rmtree(dst_folder)
274
274
 
275
275
  # Create parent directory if needed
@@ -278,7 +278,7 @@ class TemplateProcessor:
278
278
  if not silent:
279
279
  console.print(f" ✅ .claude/{folder}/ overwritten")
280
280
 
281
- # 2. Copy other files/folders individually (FORCE OVERWRITE all files)
281
+ # 2. Copy other files/folders individually (smart merge for settings.json)
282
282
  all_warnings = []
283
283
  for item in src.iterdir():
284
284
  rel_path = item.relative_to(src)
@@ -289,9 +289,15 @@ class TemplateProcessor:
289
289
  continue
290
290
 
291
291
  if item.is_file():
292
- # FORCE OVERWRITE: Always copy files (no skip)
293
- warnings = self._copy_file_with_substitution(item, dst_item)
294
- all_warnings.extend(warnings)
292
+ # Smart merge for settings.json
293
+ if item.name == "settings.json":
294
+ self._merge_settings_json(item, dst_item)
295
+ if not silent:
296
+ console.print(" 🔄 settings.json merged (env variables preserved)")
297
+ else:
298
+ # FORCE OVERWRITE: Always copy other files (no skip)
299
+ warnings = self._copy_file_with_substitution(item, dst_item)
300
+ all_warnings.extend(warnings)
295
301
  elif item.is_dir():
296
302
  # FORCE OVERWRITE: Always copy directories (no skip)
297
303
  self._copy_dir_with_substitution(item, dst_item)
@@ -351,8 +357,26 @@ class TemplateProcessor:
351
357
  if not silent:
352
358
  console.print(" ✅ .moai/ copy complete (variables substituted)")
353
359
 
360
+ def _copy_github(self, silent: bool = False) -> None:
361
+ """.github/ directory copy with variable substitution."""
362
+ src = self.template_root / ".github"
363
+ dst = self.target_path / ".github"
364
+
365
+ if not src.exists():
366
+ if not silent:
367
+ console.print("⚠️ .github/ template not found")
368
+ return
369
+
370
+ if dst.exists():
371
+ shutil.rmtree(dst)
372
+
373
+ self._copy_dir_with_substitution(src, dst)
374
+
375
+ if not silent:
376
+ console.print(" ✅ .github/ copy complete (variables substituted)")
377
+
354
378
  def _copy_claude_md(self, silent: bool = False) -> None:
355
- """Copy CLAUDE.md with FORCE OVERWRITE."""
379
+ """Copy CLAUDE.md with smart merge (preserves \"## 프로젝트 정보\" section)."""
356
380
  src = self.template_root / "CLAUDE.md"
357
381
  dst = self.target_path / "CLAUDE.md"
358
382
 
@@ -361,10 +385,16 @@ class TemplateProcessor:
361
385
  console.print("⚠️ CLAUDE.md template not found")
362
386
  return
363
387
 
364
- # FORCE OVERWRITE: Always copy template (backup already created in Phase 1)
365
- self._copy_file_with_substitution(src, dst)
366
- if not silent:
367
- console.print(" ✅ CLAUDE.md overwritten (backup available in .moai-backups/)")
388
+ # Smart merge: preserve existing "## 프로젝트 정보" section
389
+ if dst.exists():
390
+ self._merge_claude_md(src, dst)
391
+ if not silent:
392
+ console.print(" 🔄 CLAUDE.md merged (프로젝트 정보 preserved)")
393
+ else:
394
+ # First time: just copy
395
+ self._copy_file_with_substitution(src, dst)
396
+ if not silent:
397
+ console.print(" ✅ CLAUDE.md created")
368
398
 
369
399
  def _merge_claude_md(self, src: Path, dst: Path) -> None:
370
400
  """Delegate the smart merge for CLAUDE.md.
@@ -375,6 +405,24 @@ class TemplateProcessor:
375
405
  """
376
406
  self.merger.merge_claude_md(src, dst)
377
407
 
408
+ def _merge_settings_json(self, src: Path, dst: Path) -> None:
409
+ """Delegate the smart merge for settings.json.
410
+
411
+ Args:
412
+ src: Template settings.json.
413
+ dst: Project settings.json.
414
+ """
415
+ # Find the latest backup for user settings extraction
416
+ backup_path = None
417
+ if self.backup.backup_dir.exists():
418
+ backups = sorted(self.backup.backup_dir.iterdir(), reverse=True)
419
+ if backups:
420
+ backup_settings = backups[0] / ".claude" / "settings.json"
421
+ if backup_settings.exists():
422
+ backup_path = backup_settings
423
+
424
+ self.merger.merge_settings_json(src, dst, backup_path)
425
+
378
426
  def _copy_gitignore(self, silent: bool = False) -> None:
379
427
  """.gitignore copy (optional)."""
380
428
  src = self.template_root / ".gitignore"