@team-semicolon/semo-cli 3.7.1 → 3.7.3

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.
Files changed (2) hide show
  1. package/dist/index.js +159 -15
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -995,17 +995,17 @@ program
995
995
  spinner.fail("Git 레포지토리가 아닙니다. 'git init'을 먼저 실행하세요.");
996
996
  process.exit(1);
997
997
  }
998
- // 2. Extension 패키지 처리 (--with 옵션으로만 지정 가능)
999
- let extensionsToInstall = [];
998
+ // 2. Extension 패키지 처리
999
+ // semo-hooks는 기본 포함 (Claude Code Hooks 로깅 시스템)
1000
+ let extensionsToInstall = ["semo-hooks"];
1000
1001
  if (options.with) {
1001
- extensionsToInstall = options.with.split(",").map((p) => p.trim()).filter((p) => p in EXTENSION_PACKAGES);
1002
- if (extensionsToInstall.length > 0) {
1003
- console.log(chalk_1.default.cyan("\n📦 추가 Extension 설치:"));
1004
- extensionsToInstall.forEach(pkg => {
1005
- console.log(chalk_1.default.gray(` - ${EXTENSION_PACKAGES[pkg].name}: ${EXTENSION_PACKAGES[pkg].desc}`));
1006
- });
1007
- }
1002
+ const additionalPkgs = options.with.split(",").map((p) => p.trim()).filter((p) => p in EXTENSION_PACKAGES);
1003
+ extensionsToInstall = [...new Set([...extensionsToInstall, ...additionalPkgs])];
1008
1004
  }
1005
+ console.log(chalk_1.default.cyan("\n📦 Extension 설치:"));
1006
+ extensionsToInstall.forEach(pkg => {
1007
+ console.log(chalk_1.default.gray(` - ${EXTENSION_PACKAGES[pkg].name}: ${EXTENSION_PACKAGES[pkg].desc}`));
1008
+ });
1009
1009
  // 3. .claude 디렉토리 생성
1010
1010
  const claudeDir = path.join(cwd, ".claude");
1011
1011
  if (!fs.existsSync(claudeDir)) {
@@ -1072,7 +1072,8 @@ program
1072
1072
  console.log(chalk_1.default.gray(" 1. Claude Code에서 프로젝트 열기"));
1073
1073
  console.log(chalk_1.default.gray(" 2. 자연어로 요청하기 (예: \"댓글 기능 구현해줘\")"));
1074
1074
  console.log(chalk_1.default.gray(" 3. /SEMO:help로 도움말 확인"));
1075
- if (extensionsToInstall.length === 0) {
1075
+ // semo-hooks만 설치된 경우 추가 패키지 안내
1076
+ if (extensionsToInstall.length === 1 && extensionsToInstall[0] === "semo-hooks") {
1076
1077
  console.log(chalk_1.default.gray("\n💡 추가 패키지: semo add <package> (예: semo add meta)"));
1077
1078
  }
1078
1079
  console.log();
@@ -1421,7 +1422,8 @@ async function downloadExtensions(cwd, packages, force) {
1421
1422
  }
1422
1423
  // 개별 패키지 복사
1423
1424
  for (const pkg of packages) {
1424
- const srcPath = path.join(tempDir, "packages", pkg);
1425
+ // Extension 패키지는 semo-system/ 폴더에 있음
1426
+ const srcPath = path.join(tempDir, "semo-system", pkg);
1425
1427
  const destPath = path.join(semoSystemDir, pkg);
1426
1428
  if (fs.existsSync(srcPath)) {
1427
1429
  if (fs.existsSync(destPath) && !force) {
@@ -1497,6 +1499,26 @@ function createMergedOrchestrator(claudeAgentsDir, orchestratorSources) {
1497
1499
  }
1498
1500
  }
1499
1501
  }
1502
+ // meta 패키지 포함 여부 확인
1503
+ const hasMetaInSources = orchestratorSources.some(s => s.pkg === "meta");
1504
+ // Meta 자동 체이닝 섹션
1505
+ const metaAutoChainSection = hasMetaInSources ? `
1506
+ ## 🔴 Meta 환경 자동 체이닝 (NON-NEGOTIABLE)
1507
+
1508
+ > **조건**: semo-system/ 내 파일 수정이 감지되면
1509
+ > **동작**: 작업 종료 전 자동으로 \`skill:meta-workflow\` 호출
1510
+
1511
+ \`\`\`text
1512
+ semo-system/ 파일 수정 감지
1513
+
1514
+ [자동] skill:meta-workflow 호출
1515
+
1516
+ 버저닝 → 배포 → 로컬 동기화
1517
+ \`\`\`
1518
+
1519
+ **이 규칙은 우회할 수 없습니다.**
1520
+
1521
+ ` : "";
1500
1522
  // 병합된 orchestrator.md 생성
1501
1523
  const mergedContent = `---
1502
1524
  name: orchestrator
@@ -1565,7 +1587,7 @@ ${routingTables.join("\n\n---\n\n")}
1565
1587
  3. **Package Priority**: 라우팅 충돌 시 설치 순서대로 우선순위 적용
1566
1588
  4. **Cross-Package**: 다른 패키지 전문 영역 요청 시 인계 권유
1567
1589
 
1568
- ${crossPackageRouting.length > 0 ? `## 🔄 Cross-Package Routing
1590
+ ${metaAutoChainSection}${crossPackageRouting.length > 0 ? `## 🔄 Cross-Package Routing
1569
1591
 
1570
1592
  ${crossPackageRouting[0]}` : ""}
1571
1593
 
@@ -2346,6 +2368,8 @@ async function setupClaudeMd(cwd, extensions, force) {
2346
2368
  : "";
2347
2369
  // 패키지별 CLAUDE.md 병합 섹션 생성
2348
2370
  let packageClaudeMdSections = "";
2371
+ // meta 패키지 설치 여부 확인
2372
+ const hasMetaPackage = extensions.includes("meta");
2349
2373
  // 개별 패키지 CLAUDE.md 병합 - 중복 제거 적용
2350
2374
  for (const pkg of extensions) {
2351
2375
  const pkgClaudeMdPath = path.join(semoSystemDir, pkg, "CLAUDE.md");
@@ -2391,6 +2415,47 @@ ${orchestratorPaths.map(p => `- \`${p}\``).join("\n")}
2391
2415
  : `**반드시 읽어야 할 파일**: \`semo-system/semo-core/agents/orchestrator/orchestrator.md\`
2392
2416
 
2393
2417
  이 파일에서 라우팅 테이블, 의도 분류, 메시지 포맷을 확인하세요.`;
2418
+ // Meta 패키지 설치 시 자동 워크플로우 강제 규칙
2419
+ const metaWorkflowSection = hasMetaPackage ? `
2420
+ ### 3. Meta 환경 자동 워크플로우 (NON-NEGOTIABLE)
2421
+
2422
+ > **⚠️ Meta 패키지가 설치된 환경에서는 반드시 아래 규칙이 적용됩니다.**
2423
+ > **이 규칙을 우회하거나 무시하는 것은 금지됩니다.**
2424
+
2425
+ #### 자동 트리거 조건
2426
+
2427
+ \`semo-system/\` 디렉토리 내 파일이 수정되면:
2428
+ 1. 작업 종료 전 반드시 \`skill:meta-workflow\` 호출
2429
+ 2. 버저닝 → 배포 → 로컬 동기화 체인 자동 실행
2430
+
2431
+ #### 감지 패턴
2432
+
2433
+ 다음 경로의 파일 수정 시 자동 트리거:
2434
+ - \`semo-system/semo-core/**\`
2435
+ - \`semo-system/semo-skills/**\`
2436
+ - \`semo-system/meta/**\`
2437
+ - \`semo-system/semo-remote/**\`
2438
+ - \`semo-system/semo-hooks/**\`
2439
+ - \`packages/cli/**\` (CLI 수정 시)
2440
+
2441
+ #### 강제 동작 흐름
2442
+
2443
+ \`\`\`text
2444
+ [작업 완료 감지]
2445
+
2446
+ semo-system/ 또는 packages/ 파일 수정 여부 확인
2447
+
2448
+ 수정됨? → [SEMO] Skill 호출: meta-workflow
2449
+ 버저닝 → 배포 → 동기화 자동 실행
2450
+
2451
+ 수정 안됨? → 정상 종료
2452
+ \`\`\`
2453
+
2454
+ **금지 사항**:
2455
+ - semo-system/ 수정 후 버저닝 없이 종료
2456
+ - "버저닝 나중에 해줘" 요청 수락
2457
+ - meta-workflow 스킬 호출 건너뛰기
2458
+ ` : "";
2394
2459
  const claudeMdContent = `# SEMO Project Configuration
2395
2460
 
2396
2461
  > SEMO (Semicolon Orchestrate) - AI Agent Orchestration Framework v${VERSION}
@@ -2444,7 +2509,7 @@ npm run build # 3. 빌드 검증 (Next.js/TypeScript 프로젝트)
2444
2509
  - \`--no-verify\` 플래그 사용 금지
2445
2510
  - Quality Gate 우회 시도 거부
2446
2511
  - "그냥 커밋해줘", "빌드 생략해줘" 등 거부
2447
-
2512
+ ${metaWorkflowSection}
2448
2513
  ---
2449
2514
 
2450
2515
  ## 설치된 구성
@@ -3035,8 +3100,87 @@ program
3035
3100
  else {
3036
3101
  console.log(chalk_1.default.red(" ❌ .claude/ 디렉토리 없음"));
3037
3102
  }
3038
- // 4. 설치 검증
3039
- console.log(chalk_1.default.cyan("\n4. 전체 설치 검증"));
3103
+ // 4. semo-hooks 상태 확인
3104
+ console.log(chalk_1.default.cyan("\n4. semo-hooks (Claude Code Hooks)"));
3105
+ const hooksDir = path.join(semoSystemDir, "semo-hooks");
3106
+ const hooksDistDir = path.join(hooksDir, "dist");
3107
+ const hooksIndexJs = path.join(hooksDistDir, "index.js");
3108
+ if (!fs.existsSync(hooksDir)) {
3109
+ console.log(chalk_1.default.gray(" ⏭️ semo-hooks 미설치 (선택 패키지)"));
3110
+ console.log(chalk_1.default.gray(" 💡 설치: semo add hooks"));
3111
+ }
3112
+ else {
3113
+ // hooks 버전 확인
3114
+ const hooksVersionPath = path.join(hooksDir, "VERSION");
3115
+ const hooksVersion = fs.existsSync(hooksVersionPath)
3116
+ ? fs.readFileSync(hooksVersionPath, "utf-8").trim()
3117
+ : "?";
3118
+ console.log(chalk_1.default.green(` ✅ semo-hooks v${hooksVersion} 설치됨`));
3119
+ // 빌드 상태 확인
3120
+ if (!fs.existsSync(hooksDistDir) || !fs.existsSync(hooksIndexJs)) {
3121
+ console.log(chalk_1.default.red(" ❌ 빌드되지 않음 (dist/index.js 없음)"));
3122
+ console.log(chalk_1.default.gray(" 💡 해결: semo hooks enable"));
3123
+ }
3124
+ else {
3125
+ console.log(chalk_1.default.green(" ✅ 빌드 완료 (dist/index.js 존재)"));
3126
+ }
3127
+ // settings.local.json hooks 설정 확인
3128
+ const homeDir = process.env.HOME || process.env.USERPROFILE || "";
3129
+ const settingsPath = path.join(homeDir, ".claude", "settings.local.json");
3130
+ if (!fs.existsSync(settingsPath)) {
3131
+ console.log(chalk_1.default.yellow(" ⚠️ settings.local.json 없음"));
3132
+ console.log(chalk_1.default.gray(" 💡 해결: semo hooks enable"));
3133
+ }
3134
+ else {
3135
+ try {
3136
+ const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
3137
+ const hooksConfig = settings.hooks;
3138
+ if (!hooksConfig) {
3139
+ console.log(chalk_1.default.yellow(" ⚠️ hooks 설정 없음"));
3140
+ console.log(chalk_1.default.gray(" 💡 해결: semo hooks enable"));
3141
+ }
3142
+ else {
3143
+ const requiredHooks = ["SessionStart", "UserPromptSubmit", "Stop", "SessionEnd"];
3144
+ const missingHooks = [];
3145
+ const invalidPathHooks = [];
3146
+ for (const hookName of requiredHooks) {
3147
+ const hookArray = hooksConfig[hookName];
3148
+ if (!hookArray || !Array.isArray(hookArray) || hookArray.length === 0) {
3149
+ missingHooks.push(hookName);
3150
+ }
3151
+ else {
3152
+ // 경로 검증
3153
+ const hookEntry = hookArray[0];
3154
+ const innerHooks = hookEntry?.hooks;
3155
+ if (innerHooks && Array.isArray(innerHooks) && innerHooks.length > 0) {
3156
+ const command = innerHooks[0]?.command || "";
3157
+ // 현재 프로젝트의 semo-hooks 경로와 비교
3158
+ if (!command.includes(hooksDir) && !command.includes("semo-hooks")) {
3159
+ invalidPathHooks.push(hookName);
3160
+ }
3161
+ }
3162
+ }
3163
+ }
3164
+ if (missingHooks.length > 0) {
3165
+ console.log(chalk_1.default.yellow(` ⚠️ 누락된 hooks: ${missingHooks.join(", ")}`));
3166
+ console.log(chalk_1.default.gray(" 💡 해결: semo hooks enable"));
3167
+ }
3168
+ else if (invalidPathHooks.length > 0) {
3169
+ console.log(chalk_1.default.yellow(` ⚠️ 경로 불일치: ${invalidPathHooks.join(", ")}`));
3170
+ console.log(chalk_1.default.gray(" 💡 해결: semo hooks enable (다른 프로젝트 설정 감지)"));
3171
+ }
3172
+ else {
3173
+ console.log(chalk_1.default.green(" ✅ hooks 설정 완료 (4개 hook 등록됨)"));
3174
+ }
3175
+ }
3176
+ }
3177
+ catch {
3178
+ console.log(chalk_1.default.red(" ❌ settings.local.json 파싱 오류"));
3179
+ }
3180
+ }
3181
+ }
3182
+ // 5. 전체 설치 검증
3183
+ console.log(chalk_1.default.cyan("\n5. 전체 설치 검증"));
3040
3184
  const verificationResult = verifyInstallation(cwd, []);
3041
3185
  if (verificationResult.success) {
3042
3186
  console.log(chalk_1.default.green(" ✅ 설치 상태 정상"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-semicolon/semo-cli",
3
- "version": "3.7.1",
3
+ "version": "3.7.3",
4
4
  "description": "SEMO CLI - AI Agent Orchestration Framework Installer",
5
5
  "main": "dist/index.js",
6
6
  "bin": {