moai-adk 0.4.1__py3-none-any.whl → 0.4.4__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 CHANGED
@@ -4,5 +4,11 @@
4
4
  SPEC-First TDD Framework with Alfred SuperAgent
5
5
  """
6
6
 
7
- __version__ = "0.4.0"
7
+ from importlib.metadata import PackageNotFoundError, version
8
+
9
+ try:
10
+ __version__ = version("moai-adk")
11
+ except PackageNotFoundError:
12
+ __version__ = "0.4.1-dev"
13
+
8
14
  __all__ = ["__version__"]
@@ -315,7 +315,7 @@ def update(path: str, force: bool, check: bool) -> None:
315
315
  console.print("\n[cyan]💾 Creating backup...[/cyan]")
316
316
  processor = TemplateProcessor(project_path)
317
317
  backup_path = processor.create_backup()
318
- console.print(f"[green]✓ Backup completed: {backup_path.relative_to(project_path)}[/green]")
318
+ console.print(f"[green]✓ Backup completed: {backup_path.relative_to(project_path)}/[/green]")
319
319
  else:
320
320
  console.print("\n[yellow]⚠ Skipping backup (--force)[/yellow]")
321
321
 
@@ -93,11 +93,11 @@ def prompt_project_setup(
93
93
  answers["locale"] = initial_locale or "en"
94
94
  if initial_locale:
95
95
  console.print(
96
- f"[cyan]🌐 Preferred Language:[/cyan] {answers['locale']} (CLI 옵션으로 지정됨)"
96
+ f"[cyan]🌐 Preferred Language:[/cyan] {answers['locale']} (specified via CLI option)"
97
97
  )
98
98
  else:
99
99
  console.print(
100
- "[cyan]🌐 Preferred Language:[/cyan] en (기본값, /alfred:0-project에서 변경 가능)"
100
+ "[cyan]🌐 Preferred Language:[/cyan] en (default, changeable in /alfred:0-project)"
101
101
  )
102
102
 
103
103
  # 3. Programming language (auto-detect or manual)
@@ -3,10 +3,9 @@
3
3
 
4
4
  Selective backup strategy:
5
5
  - Back up only the required files (OR condition)
6
- - Backup path: .moai-backups/{timestamp}/ (v0.3.0)
6
+ - Backup path: .moai-backups/backup/ (v0.4.2)
7
7
  """
8
8
 
9
- from datetime import datetime
10
9
  from pathlib import Path
11
10
 
12
11
  # Backup targets (OR condition - back up when any exist)
@@ -59,15 +58,6 @@ def get_backup_targets(project_path: Path) -> list[str]:
59
58
  return targets
60
59
 
61
60
 
62
- def generate_backup_dir_name() -> str:
63
- """Generate a timestamp-based backup directory name (v0.3.0).
64
-
65
- Returns:
66
- Timestamp formatted as YYYYMMDD-HHMMSS.
67
- Note: callers use .moai-backups/{timestamp}/ format.
68
- """
69
- timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
70
- return timestamp
71
61
 
72
62
 
73
63
  def is_protected_path(rel_path: Path) -> bool:
@@ -298,5 +298,5 @@ def get_permission_fix_message(path: str) -> str:
298
298
  Platform-specific fix instructions.
299
299
  """
300
300
  if platform.system() == "Windows":
301
- return f"관리자 권한으로 실행하거나 '{path}' 디렉토리 속성에서 권한을 확인하세요"
302
- return f"chmod 755 {path} 실행 재시도하세요"
301
+ return f"Run with administrator privileges or verify permissions in the properties of the '{path}' directory"
302
+ return f"Run 'chmod 755 {path}' and try again"
@@ -1,8 +1,8 @@
1
1
  # @CODE:INIT-003:PHASE | SPEC: .moai/specs/SPEC-INIT-003/spec.md | TEST: tests/unit/test_init_reinit.py
2
- """Phase-based installation executor (SPEC-INIT-003 v0.3.0)
2
+ """Phase-based installation executor (SPEC-INIT-003 v0.4.2)
3
3
 
4
4
  Runs the project initialization across five phases:
5
- - Phase 1: Preparation (create backup at .moai-backups/{timestamp}/, keep only latest)
5
+ - Phase 1: Preparation (create single backup at .moai-backups/backup/)
6
6
  - Phase 2: Directory (build directory structure)
7
7
  - Phase 3: Resource (copy templates while preserving user content)
8
8
  - Phase 4: Configuration (generate configuration files)
@@ -20,7 +20,6 @@ from rich.console import Console
20
20
 
21
21
  from moai_adk import __version__
22
22
  from moai_adk.core.project.backup_utils import (
23
- generate_backup_dir_name,
24
23
  get_backup_targets,
25
24
  has_any_moai_files,
26
25
  is_protected_path,
@@ -229,25 +228,21 @@ class PhaseExecutor:
229
228
  self._initialize_git(project_path)
230
229
 
231
230
  def _create_backup(self, project_path: Path) -> None:
232
- """Create a selective backup (v0.3.0).
231
+ """Create a single backup (v0.4.2).
233
232
 
234
- Keep only the latest backup in .moai-backups/{timestamp}/.
233
+ Maintains only one backup at .moai-backups/backup/.
235
234
 
236
235
  Args:
237
236
  project_path: Project path.
238
237
  """
239
238
  # Define backup directory
240
239
  backups_dir = project_path / ".moai-backups"
240
+ backup_path = backups_dir / "backup"
241
241
 
242
- # Remove all existing backups (keep only latest)
243
- if backups_dir.exists():
244
- for item in backups_dir.iterdir():
245
- if item.is_dir():
246
- shutil.rmtree(item)
242
+ # Remove existing backup if present
243
+ if backup_path.exists():
244
+ shutil.rmtree(backup_path)
247
245
 
248
- # Create new backup directory (.moai-backups/{timestamp}/)
249
- timestamp = generate_backup_dir_name()
250
- backup_path = backups_dir / timestamp
251
246
  backup_path.mkdir(parents=True, exist_ok=True)
252
247
 
253
248
  # Collect backup targets
@@ -1,5 +1,5 @@
1
1
  # @CODE:TRUST-001 | SPEC: SPEC-TRUST-001/spec.md | TEST: tests/unit/core/quality/
2
- """TRUST 원칙 자동 검증 시스템"""
2
+ """TRUST principle automated validation system"""
3
3
 
4
4
  from moai_adk.core.quality.trust_checker import TrustChecker
5
5
 
@@ -1,13 +1,13 @@
1
1
  # @CODE:TRUST-001 | SPEC: SPEC-TRUST-001/spec.md | TEST: tests/unit/core/quality/test_trust_checker.py
2
2
  """
3
- TRUST 원칙 통합 검증 시스템
4
-
5
- TRUST 5원칙:
6
- - T: Test First (테스트 커버리지 ≥85%)
7
- - R: Readable (파일 ≤300 LOC, 함수 ≤50 LOC, 매개변수 ≤5)
8
- - U: Unified (타입 안전성)
9
- - S: Secured (보안 취약점 스캔)
10
- - T: Trackable (TAG 체인 무결성)
3
+ Integrated TRUST principle validation system
4
+
5
+ TRUST 5 principles:
6
+ - T: Test First (test coverage ≥85%)
7
+ - R: Readable (file ≤300 LOC, function ≤50 LOC, parameters ≤5)
8
+ - U: Unified (type safety)
9
+ - S: Secured (vulnerability scanning)
10
+ - T: Trackable (TAG chain integrity)
11
11
  """
12
12
 
13
13
  import ast
@@ -18,7 +18,7 @@ from typing import Any
18
18
  from moai_adk.core.quality.validators.base_validator import ValidationResult
19
19
 
20
20
  # ========================================
21
- # 상수 정의 (의도를 드러내는 이름)
21
+ # Constants (descriptive names)
22
22
  # ========================================
23
23
  MIN_TEST_COVERAGE_PERCENT = 85
24
24
  MAX_FILE_LINES_OF_CODE = 300
@@ -26,20 +26,20 @@ MAX_FUNCTION_LINES_OF_CODE = 50
26
26
  MAX_FUNCTION_PARAMETERS = 5
27
27
  MAX_CYCLOMATIC_COMPLEXITY = 10
28
28
 
29
- # 파일 인코딩
29
+ # File encoding
30
30
  DEFAULT_FILE_ENCODING = "utf-8"
31
31
 
32
- # TAG 접두사
32
+ # TAG prefixes
33
33
  TAG_PREFIX_SPEC = "@SPEC:"
34
34
  TAG_PREFIX_CODE = "@CODE:"
35
35
  TAG_PREFIX_TEST = "@TEST:"
36
36
 
37
37
 
38
38
  class TrustChecker:
39
- """TRUST 원칙 통합 검증기"""
39
+ """Integrated TRUST principle validator"""
40
40
 
41
41
  def __init__(self):
42
- """TrustChecker 초기화"""
42
+ """Initialize TrustChecker"""
43
43
  self.results: dict[str, ValidationResult] = {}
44
44
 
45
45
  # ========================================
@@ -48,14 +48,14 @@ class TrustChecker:
48
48
 
49
49
  def validate_coverage(self, project_path: Path, coverage_data: dict[str, Any]) -> ValidationResult:
50
50
  """
51
- 테스트 커버리지 검증 (≥85%)
51
+ Validate test coverage (≥85%)
52
52
 
53
53
  Args:
54
- project_path: 프로젝트 경로
55
- coverage_data: 커버리지 데이터 (total_coverage, low_coverage_files)
54
+ project_path: Project path
55
+ coverage_data: Coverage data (total_coverage, low_coverage_files)
56
56
 
57
57
  Returns:
58
- ValidationResult: 검증 결과
58
+ ValidationResult: Validation result
59
59
  """
60
60
  total_coverage = coverage_data.get("total_coverage", 0)
61
61
 
@@ -64,7 +64,7 @@ class TrustChecker:
64
64
  passed=True, message=f"Test coverage: {total_coverage}% (Target: {MIN_TEST_COVERAGE_PERCENT}%)"
65
65
  )
66
66
 
67
- # 실패 상세 정보 생성
67
+ # Generate detailed information on failure
68
68
  low_files = coverage_data.get("low_coverage_files", [])
69
69
  details = f"Current coverage: {total_coverage}% (Target: {MIN_TEST_COVERAGE_PERCENT}%)\n"
70
70
  details += "Low coverage files:\n"
@@ -84,15 +84,15 @@ class TrustChecker:
84
84
 
85
85
  def validate_file_size(self, src_path: Path) -> ValidationResult:
86
86
  """
87
- 파일 크기 검증 (≤300 LOC)
87
+ Validate file size (≤300 LOC)
88
88
 
89
89
  Args:
90
- src_path: 소스 코드 디렉토리 경로
90
+ src_path: Source code directory path
91
91
 
92
92
  Returns:
93
- ValidationResult: 검증 결과
93
+ ValidationResult: Validation result
94
94
  """
95
- # 입력 검증 (보안 강화)
95
+ # Input validation (security)
96
96
  if not src_path.exists():
97
97
  return ValidationResult(passed=False, message=f"Source path does not exist: {src_path}", details="")
98
98
 
@@ -102,7 +102,7 @@ class TrustChecker:
102
102
  violations = []
103
103
 
104
104
  for py_file in src_path.rglob("*.py"):
105
- # 가드절 적용 (가독성 향상)
105
+ # Apply guard clause (improves readability)
106
106
  if py_file.name.startswith("test_"):
107
107
  continue
108
108
 
@@ -113,7 +113,7 @@ class TrustChecker:
113
113
  if loc > MAX_FILE_LINES_OF_CODE:
114
114
  violations.append(f"{py_file.name}: {loc} LOC (Limit: {MAX_FILE_LINES_OF_CODE})")
115
115
  except (UnicodeDecodeError, PermissionError):
116
- # 보안: 파일 접근 오류 처리
116
+ # Security: handle file access errors
117
117
  continue
118
118
 
119
119
  if not violations:
@@ -126,13 +126,13 @@ class TrustChecker:
126
126
 
127
127
  def validate_function_size(self, src_path: Path) -> ValidationResult:
128
128
  """
129
- 함수 크기 검증 (≤50 LOC)
129
+ Validate function size (≤50 LOC)
130
130
 
131
131
  Args:
132
- src_path: 소스 코드 디렉토리 경로
132
+ src_path: Source code directory path
133
133
 
134
134
  Returns:
135
- ValidationResult: 검증 결과
135
+ ValidationResult: Validation result
136
136
  """
137
137
  violations = []
138
138
 
@@ -147,11 +147,11 @@ class TrustChecker:
147
147
 
148
148
  for node in ast.walk(tree):
149
149
  if isinstance(node, ast.FunctionDef):
150
- # AST 라인 번호는 1-based
150
+ # AST line numbers are 1-based
151
151
  start_line = node.lineno
152
152
  end_line = node.end_lineno if node.end_lineno else start_line # type: ignore
153
153
 
154
- # 실제 함수 라인 계산 (데코레이터 제외)
154
+ # Compute actual function lines of code (decorators excluded)
155
155
  func_lines = lines[start_line - 1:end_line]
156
156
  func_loc = len(func_lines)
157
157
 
@@ -172,13 +172,13 @@ class TrustChecker:
172
172
 
173
173
  def validate_param_count(self, src_path: Path) -> ValidationResult:
174
174
  """
175
- 매개변수 개수 검증 (≤5)
175
+ Validate parameter count (≤5)
176
176
 
177
177
  Args:
178
- src_path: 소스 코드 디렉토리 경로
178
+ src_path: Source code directory path
179
179
 
180
180
  Returns:
181
- ValidationResult: 검증 결과
181
+ ValidationResult: Validation result
182
182
  """
183
183
  violations = []
184
184
 
@@ -211,13 +211,13 @@ class TrustChecker:
211
211
 
212
212
  def validate_complexity(self, src_path: Path) -> ValidationResult:
213
213
  """
214
- 순환 복잡도 검증 (≤10)
214
+ Validate cyclomatic complexity (≤10)
215
215
 
216
216
  Args:
217
- src_path: 소스 코드 디렉토리 경로
217
+ src_path: Source code directory path
218
218
 
219
219
  Returns:
220
- ValidationResult: 검증 결과
220
+ ValidationResult: Validation result
221
221
  """
222
222
  violations = []
223
223
 
@@ -250,23 +250,23 @@ class TrustChecker:
250
250
 
251
251
  def _calculate_complexity(self, node: ast.FunctionDef) -> int:
252
252
  """
253
- 순환 복잡도 계산 (McCabe complexity)
253
+ Calculate cyclomatic complexity (McCabe complexity)
254
254
 
255
255
  Args:
256
- node: 함수 AST 노드
256
+ node: Function AST node
257
257
 
258
258
  Returns:
259
- int: 순환 복잡도
259
+ int: Cyclomatic complexity
260
260
  """
261
261
  complexity = 1
262
262
  for child in ast.walk(node):
263
- # 분기문마다 +1
263
+ # Add 1 for each branching statement
264
264
  if isinstance(child, (ast.If, ast.While, ast.For, ast.ExceptHandler, ast.With)):
265
265
  complexity += 1
266
- # and/or 연산자마다 +1
266
+ # Add 1 for each and/or operator
267
267
  elif isinstance(child, ast.BoolOp):
268
268
  complexity += len(child.values) - 1
269
- # elif 이미 ast.If 카운트되므로 별도 처리 불필요
269
+ # elif is already counted as ast.If, no extra handling needed
270
270
  return complexity
271
271
 
272
272
  # ========================================
@@ -275,22 +275,22 @@ class TrustChecker:
275
275
 
276
276
  def validate_tag_chain(self, project_path: Path) -> ValidationResult:
277
277
  """
278
- TAG 체인 완전성 검증
278
+ Validate TAG chain completeness
279
279
 
280
280
  Args:
281
- project_path: 프로젝트 경로
281
+ project_path: Project path
282
282
 
283
283
  Returns:
284
- ValidationResult: 검증 결과
284
+ ValidationResult: Validation result
285
285
  """
286
286
  specs_dir = project_path / ".moai" / "specs"
287
287
  src_dir = project_path / "src"
288
288
 
289
- # TAG 스캔
289
+ # Scan for TAGs
290
290
  spec_tags = self._scan_tags(specs_dir, "@SPEC:")
291
291
  code_tags = self._scan_tags(src_dir, "@CODE:")
292
292
 
293
- # 체인 검증
293
+ # Validate the chain
294
294
  broken_chains = []
295
295
  for code_tag in code_tags:
296
296
  tag_id = code_tag.split(":")[-1]
@@ -307,13 +307,13 @@ class TrustChecker:
307
307
 
308
308
  def detect_orphan_tags(self, project_path: Path) -> list[str]:
309
309
  """
310
- 고아 TAG 탐지
310
+ Detect orphan TAGs
311
311
 
312
312
  Args:
313
- project_path: 프로젝트 경로
313
+ project_path: Project path
314
314
 
315
315
  Returns:
316
- list[str]: 고아 TAG 목록
316
+ list[str]: List of orphan TAGs
317
317
  """
318
318
  specs_dir = project_path / ".moai" / "specs"
319
319
  src_dir = project_path / "src"
@@ -331,14 +331,14 @@ class TrustChecker:
331
331
 
332
332
  def _scan_tags(self, directory: Path, tag_prefix: str) -> list[str]:
333
333
  """
334
- 디렉토리에서 TAG 스캔
334
+ Scan for TAGs in a directory
335
335
 
336
336
  Args:
337
- directory: 스캔할 디렉토리
338
- tag_prefix: TAG 접두사 (예: "@SPEC:", "@CODE:")
337
+ directory: Directory to scan
338
+ tag_prefix: TAG prefix (for example, "@SPEC:", "@CODE:")
339
339
 
340
340
  Returns:
341
- list[str]: 발견된 TAG 목록
341
+ list[str]: List of discovered TAGs
342
342
  """
343
343
  if not directory.exists():
344
344
  return []
@@ -362,25 +362,25 @@ class TrustChecker:
362
362
 
363
363
  def generate_report(self, results: dict[str, Any], format: str = "markdown") -> str:
364
364
  """
365
- 검증 결과 보고서 생성
365
+ Generate validation report
366
366
 
367
367
  Args:
368
- results: 검증 결과 딕셔너리
369
- format: 보고서 형식 ("markdown" 또는 "json")
368
+ results: Validation result dictionary
369
+ format: Report format ("markdown" or "json")
370
370
 
371
371
  Returns:
372
- str: 보고서 문자열
372
+ str: Report string
373
373
  """
374
374
  if format == "json":
375
375
  return json.dumps(results, indent=2)
376
376
 
377
- # Markdown 형식
377
+ # Markdown format
378
378
  report = "# TRUST Validation Report\n\n"
379
379
 
380
380
  for category, result in results.items():
381
381
  status = "✅ PASS" if result.get("passed", False) else "❌ FAIL"
382
382
  value = result.get('value', 'N/A')
383
- # 숫자인 경우 % 기호 추가
383
+ # Add % suffix when the value is numeric
384
384
  if isinstance(value, (int, float)):
385
385
  value_str = f"{value}%"
386
386
  else:
@@ -398,13 +398,13 @@ class TrustChecker:
398
398
 
399
399
  def select_tools(self, project_path: Path) -> dict[str, str]:
400
400
  """
401
- 언어별 도구 자동 선택
401
+ Automatically select tools by language
402
402
 
403
403
  Args:
404
- project_path: 프로젝트 경로
404
+ project_path: Project path
405
405
 
406
406
  Returns:
407
- dict[str, str]: 선택된 도구 딕셔너리
407
+ dict[str, str]: Selected tool dictionary
408
408
  """
409
409
  config_path = project_path / ".moai" / "config.json"
410
410
  if not config_path.exists():
@@ -432,7 +432,7 @@ class TrustChecker:
432
432
  "type_checker": "tsc",
433
433
  }
434
434
 
435
- # 기본값 (Python)
435
+ # Default (Python)
436
436
  return {
437
437
  "test_framework": "pytest",
438
438
  "coverage_tool": "coverage.py",
@@ -1,5 +1,5 @@
1
1
  # @CODE:TRUST-001 | SPEC: SPEC-TRUST-001/spec.md
2
- """TRUST 검증기 패키지"""
2
+ """TRUST validator package"""
3
3
 
4
4
  from moai_adk.core.quality.validators.base_validator import ValidationResult
5
5
 
@@ -7,7 +7,7 @@ from typing import Any
7
7
 
8
8
  @dataclass
9
9
  class ValidationResult:
10
- """검증 결과 데이터 클래스"""
10
+ """Validation result data class"""
11
11
 
12
12
  passed: bool
13
13
  message: str
@@ -7,7 +7,6 @@ Creates and manages backups to protect user data during template updates.
7
7
  from __future__ import annotations
8
8
 
9
9
  import shutil
10
- from datetime import datetime
11
10
  from pathlib import Path
12
11
 
13
12
 
@@ -49,13 +48,19 @@ class TemplateBackup:
49
48
  )
50
49
 
51
50
  def create_backup(self) -> Path:
52
- """Create a timestamped backup.
51
+ """Create a single backup (always at .moai-backups/backup/).
52
+
53
+ Existing backups are overwritten to maintain only one backup copy.
53
54
 
54
55
  Returns:
55
- Backup path (for example, .moai-backups/20250110-143025/).
56
+ Backup path (always .moai-backups/backup/).
56
57
  """
57
- timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
58
- backup_path = self.target_path / ".moai-backups" / timestamp
58
+ backup_path = self.target_path / ".moai-backups" / "backup"
59
+
60
+ # Remove existing backup if present
61
+ if backup_path.exists():
62
+ shutil.rmtree(backup_path)
63
+
59
64
  backup_path.mkdir(parents=True, exist_ok=True)
60
65
 
61
66
  # Copy backup targets
@@ -15,10 +15,7 @@ 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
- )
18
+ PROJECT_INFO_HEADERS = ("## Project Information", "## 프로젝트 정보")
22
19
 
23
20
  def __init__(self, target_path: Path) -> None:
24
21
  """Initialize the merger.
@@ -33,7 +30,7 @@ class TemplateMerger:
33
30
 
34
31
  Rules:
35
32
  - Use the latest template structure/content.
36
- - Preserve the existing "## 프로젝트 정보" section.
33
+ - Preserve the existing "## Project Information" section.
37
34
 
38
35
  Args:
39
36
  template_path: Template CLAUDE.md.
@@ -376,7 +376,7 @@ class TemplateProcessor:
376
376
  console.print(" ✅ .github/ copy complete (variables substituted)")
377
377
 
378
378
  def _copy_claude_md(self, silent: bool = False) -> None:
379
- """Copy CLAUDE.md with smart merge (preserves \"## 프로젝트 정보\" section)."""
379
+ """Copy CLAUDE.md with smart merge (preserves \"## Project Information\" section)."""
380
380
  src = self.template_root / "CLAUDE.md"
381
381
  dst = self.target_path / "CLAUDE.md"
382
382
 
@@ -385,11 +385,11 @@ class TemplateProcessor:
385
385
  console.print("⚠️ CLAUDE.md template not found")
386
386
  return
387
387
 
388
- # Smart merge: preserve existing "## 프로젝트 정보" section
388
+ # Smart merge: preserve existing "## Project Information" section
389
389
  if dst.exists():
390
390
  self._merge_claude_md(src, dst)
391
391
  if not silent:
392
- console.print(" 🔄 CLAUDE.md merged (프로젝트 정보 preserved)")
392
+ console.print(" 🔄 CLAUDE.md merged (project information preserved)")
393
393
  else:
394
394
  # First time: just copy
395
395
  self._copy_file_with_substitution(src, dst)
@@ -24,7 +24,8 @@ model: sonnet
24
24
  - `Skill("moai-foundation-specs")` – Always checks the command/agent document structure.
25
25
 
26
26
  **Conditional Skill Logic**
27
- - `Skill("moai-alfred-tag-scanning")`: Called when a diff or `agent_skill_plan` contains a TAG influence.If the result is “Rules need to be updated”, we subsequently chain `Skill("moai-foundation-tags")`.
27
+ - `Skill("moai-alfred-language-detection")`: Always called first to detect project language/framework, which gates the activation of language-specific skills.
28
+ - `Skill("moai-alfred-tag-scanning")`: Called when a diff or `agent_skill_plan` contains a TAG influence.If the result is "Rules need to be updated", we subsequently chain `Skill("moai-foundation-tags")`.
28
29
  - `Skill("moai-foundation-tags")`: Executed only when TAG naming reordering or traceability matrix update is confirmed.
29
30
  - `Skill("moai-foundation-trust")`: Rechecks the latest guide when a TRUST policy/version update is detected or requested.
30
31
  - `Skill("moai-alfred-trust-validation")`: Called when it is necessary to actually verify whether there is a standard violation based on the quality gate.
@@ -32,7 +33,9 @@ model: sonnet
32
33
  - `Skill("moai-alfred-spec-metadata-validation")`: Only the relevant file is verified when a new command/agent document is created or the meta field is modified.
33
34
  - Domain skills: When the brief includes CLI/Data Science/Database/DevOps/ML/Mobile/Security needs, add the corresponding item among `Skill("moai-domain-cli-tool")`, `Skill("moai-domain-data-science")`, `Skill("moai-domain-database")`, `Skill("moai-domain-devops")`, `Skill("moai-domain-ml")`, `Skill("moai-domain-mobile-app")`, `Skill("moai-domain-security")`.
34
35
  - `Skill("moai-alfred-refactoring-coach")`: Called when the brief includes refactoring/TODO cleanup and a technical debt remediation plan is needed.
35
- - Language skills: Based on the result of `Skill("moai-alfred-language-detection")`, activate the relevant one(s) among `Skill("moai-lang-python")`, `Skill("moai-lang-typescript")`, `Skill("moai-lang-javascript")`, `Skill("moai-lang-java")`, `Skill("moai-lang-go")`, `Skill("moai-lang-rust")`, `Skill("moai-lang-csharp")`, `Skill("moai-lang-cpp")`, `Skill("moai-lang-c")`, `Skill("moai-lang-clojure")`, `Skill("moai-lang-dart")`, `Skill("moai-lang-elixir")`, `Skill("moai-lang-haskell")`, `Skill("moai-lang-julia")`, `Skill("moai-lang-kotlin")`, `Skill("moai-lang-lua")`, `Skill("moai-lang-php")`, `Skill("moai-lang-r")`, `Skill("moai-lang-ruby")`, `Skill("moai-lang-scala")`, `Skill("moai-lang-shell")`, `Skill("moai-lang-sql")`, `Skill("moai-lang-swift")`.
36
+ - **Language skills** (23 available): Based on the result of `Skill("moai-alfred-language-detection")`, activate the relevant language skill(s) from the Language Tier:
37
+ - Supported: Python, TypeScript, JavaScript, Java, Go, Rust, C#, C++, C, Clojure, Dart, Elixir, Haskell, Julia, Kotlin, Lua, PHP, R, Ruby, Scala, Shell, SQL, Swift
38
+ - Called as: `Skill("moai-lang-{language-name}")` (e.g., `Skill("moai-lang-python")`)
36
39
  - `Skill("moai-claude-code")`: Used to customize the Claude Code output format or reorganize the code example template.
37
40
  - `Skill("moai-alfred-tui-survey")`: Provides an interactive survey when changes to operating policies or introduction of standards need to be confirmed with user approval.
38
41
 
@@ -40,30 +40,38 @@ You are a Senior Project Manager Agent managing successful projects.
40
40
 
41
41
  ## 🎯 Key Role
42
42
 
43
- **✅ project-manager is called from the `/alfred:8-project` command**
43
+ **✅ project-manager is called from the `/alfred:0-project` command**
44
44
 
45
- - When `/alfred:8-project` is executed, it is called as `Task: project-manager` to perform project analysis
45
+ - When `/alfred:0-project` is executed, it is called as `Task: project-manager` to perform project analysis
46
+ - Receives **conversation_language** parameter from Alfred (e.g., "ko", "en", "ja", "zh") as first input
46
47
  - Directly responsible for project type detection (new/legacy) and document creation
47
- - Product/structure/tech documents interactively Writing
48
- - Putting into practice the method and structure of project document creation
48
+ - Product/structure/tech documents written interactively **in the selected language**
49
+ - Putting into practice the method and structure of project document creation with language localization
49
50
 
50
51
  ## 🔄 Workflow
51
52
 
52
53
  **What the project-manager actually does:**
53
54
 
55
+ 0. **Conversation Language Setup** (NEW):
56
+ - Receive `conversation_language` parameter from Alfred (e.g., "ko" for Korean, "en" for English)
57
+ - Confirm and announce the selected language in all subsequent interactions
58
+ - Store language preference in context for all generated documents and responses
59
+ - All prompts, questions, and outputs from this point forward are in the selected language
54
60
  1. **Project status analysis**: `.moai/project/*.md`, README, read source structure
55
61
  2. **Determination of project type**: Decision to introduce new (greenfield) vs. legacy
56
- 3. **User Interview**: Gather information with a question tree tailored to the project type
57
- 4. **Create Document**: Create or update product/structure/tech.md
62
+ 3. **User Interview**: Gather information with a question tree tailored to the project type (questions delivered in selected language)
63
+ 4. **Create Document**: Create or update product/structure/tech.md (all documents generated in the selected language)
58
64
  5. **Prevention of duplication**: Prohibit creation of `.claude/memory/` or `.claude/commands/alfred/*.json` files
59
- 6. **Memory Synchronization**: Leverage CLAUDE.md's existing `@.moai/project/*` import.
65
+ 6. **Memory Synchronization**: Leverage CLAUDE.md's existing `@.moai/project/*` import and add language metadata.
60
66
 
61
67
  ## 📦 Deliverables and Delivery
62
68
 
63
- - Updated `.moai/project/{product,structure,tech}.md`
64
- - Project overview summary (team size, technology stack, constraints)
69
+ - Updated `.moai/project/{product,structure,tech}.md` (in the selected language)
70
+ - Updated `.moai/config.json` with language metadata (conversation_language, language_name)
71
+ - Project overview summary (team size, technology stack, constraints) in selected language
65
72
  - Individual/team mode settings confirmation results
66
73
  - For legacy projects, organized with "Legacy Context" TODO/DEBT items
74
+ - Language preference confirmation in final summary
67
75
 
68
76
  ## ✅ Operational checkpoints
69
77