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
moai_adk/core/template/merger.py
CHANGED
|
@@ -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
|
|
42
|
+
# Extract the existing project information section
|
|
38
43
|
existing_content = existing_path.read_text(encoding="utf-8")
|
|
39
|
-
project_info_start =
|
|
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 =
|
|
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-
|
|
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-
|
|
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
|
-
#
|
|
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 (
|
|
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
|
-
#
|
|
293
|
-
|
|
294
|
-
|
|
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
|
|
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
|
-
#
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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"
|