@team-semicolon/semo-cli 3.7.2 → 3.7.4

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 +224 -4
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1499,6 +1499,26 @@ function createMergedOrchestrator(claudeAgentsDir, orchestratorSources) {
1499
1499
  }
1500
1500
  }
1501
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
+ ` : "";
1502
1522
  // 병합된 orchestrator.md 생성
1503
1523
  const mergedContent = `---
1504
1524
  name: orchestrator
@@ -1567,7 +1587,7 @@ ${routingTables.join("\n\n---\n\n")}
1567
1587
  3. **Package Priority**: 라우팅 충돌 시 설치 순서대로 우선순위 적용
1568
1588
  4. **Cross-Package**: 다른 패키지 전문 영역 요청 시 인계 권유
1569
1589
 
1570
- ${crossPackageRouting.length > 0 ? `## 🔄 Cross-Package Routing
1590
+ ${metaAutoChainSection}${crossPackageRouting.length > 0 ? `## 🔄 Cross-Package Routing
1571
1591
 
1572
1592
  ${crossPackageRouting[0]}` : ""}
1573
1593
 
@@ -2348,6 +2368,8 @@ async function setupClaudeMd(cwd, extensions, force) {
2348
2368
  : "";
2349
2369
  // 패키지별 CLAUDE.md 병합 섹션 생성
2350
2370
  let packageClaudeMdSections = "";
2371
+ // meta 패키지 설치 여부 확인
2372
+ const hasMetaPackage = extensions.includes("meta");
2351
2373
  // 개별 패키지 CLAUDE.md 병합 - 중복 제거 적용
2352
2374
  for (const pkg of extensions) {
2353
2375
  const pkgClaudeMdPath = path.join(semoSystemDir, pkg, "CLAUDE.md");
@@ -2393,6 +2415,47 @@ ${orchestratorPaths.map(p => `- \`${p}\``).join("\n")}
2393
2415
  : `**반드시 읽어야 할 파일**: \`semo-system/semo-core/agents/orchestrator/orchestrator.md\`
2394
2416
 
2395
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
+ ` : "";
2396
2459
  const claudeMdContent = `# SEMO Project Configuration
2397
2460
 
2398
2461
  > SEMO (Semicolon Orchestrate) - AI Agent Orchestration Framework v${VERSION}
@@ -2446,7 +2509,7 @@ npm run build # 3. 빌드 검증 (Next.js/TypeScript 프로젝트)
2446
2509
  - \`--no-verify\` 플래그 사용 금지
2447
2510
  - Quality Gate 우회 시도 거부
2448
2511
  - "그냥 커밋해줘", "빌드 생략해줘" 등 거부
2449
-
2512
+ ${metaWorkflowSection}
2450
2513
  ---
2451
2514
 
2452
2515
  ## 설치된 구성
@@ -3037,8 +3100,165 @@ program
3037
3100
  else {
3038
3101
  console.log(chalk_1.default.red(" ❌ .claude/ 디렉토리 없음"));
3039
3102
  }
3040
- // 4. 설치 검증
3041
- 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. semo-mcp (MCP 서버) 상태 확인
3183
+ console.log(chalk_1.default.cyan("\n5. semo-mcp (MCP 서버)"));
3184
+ const userHomeDir = process.env.HOME || process.env.USERPROFILE || "";
3185
+ const claudeSettingsPath = path.join(userHomeDir, ".claude", "settings.local.json");
3186
+ // MCP 서버 설정 확인
3187
+ if (!fs.existsSync(claudeSettingsPath)) {
3188
+ console.log(chalk_1.default.yellow(" ⚠️ settings.local.json 없음"));
3189
+ console.log(chalk_1.default.gray(" 💡 MCP 서버 설정이 필요합니다"));
3190
+ }
3191
+ else {
3192
+ try {
3193
+ const settings = JSON.parse(fs.readFileSync(claudeSettingsPath, "utf-8"));
3194
+ const mcpServers = settings.mcpServers || {};
3195
+ // semo-integrations MCP 서버 확인
3196
+ const semoMcp = mcpServers["semo-integrations"];
3197
+ if (!semoMcp) {
3198
+ console.log(chalk_1.default.yellow(" ⚠️ semo-integrations MCP 서버 미등록"));
3199
+ console.log(chalk_1.default.gray(" 💡 .claude/settings.json에 MCP 서버 추가 필요"));
3200
+ }
3201
+ else {
3202
+ console.log(chalk_1.default.green(" ✅ semo-integrations MCP 서버 등록됨"));
3203
+ // 명령어 경로 확인
3204
+ const mcpCommand = semoMcp.command || "";
3205
+ const mcpArgs = semoMcp.args || [];
3206
+ if (mcpCommand === "npx") {
3207
+ console.log(chalk_1.default.green(" ✅ npx 방식 실행 (자동 업데이트)"));
3208
+ }
3209
+ else if (mcpCommand === "node") {
3210
+ const scriptPath = mcpArgs[0] || "";
3211
+ if (scriptPath && fs.existsSync(scriptPath)) {
3212
+ console.log(chalk_1.default.green(` ✅ 로컬 스크립트: ${scriptPath}`));
3213
+ }
3214
+ else if (scriptPath) {
3215
+ console.log(chalk_1.default.red(` ❌ 스크립트 경로 없음: ${scriptPath}`));
3216
+ }
3217
+ }
3218
+ // 환경변수 확인
3219
+ const env = semoMcp.env || {};
3220
+ const requiredEnvVars = ["SLACK_BOT_TOKEN", "GITHUB_TOKEN"];
3221
+ const missingEnvVars = [];
3222
+ const configuredEnvVars = [];
3223
+ for (const envVar of requiredEnvVars) {
3224
+ if (env[envVar]) {
3225
+ configuredEnvVars.push(envVar);
3226
+ }
3227
+ else {
3228
+ missingEnvVars.push(envVar);
3229
+ }
3230
+ }
3231
+ if (configuredEnvVars.length > 0) {
3232
+ console.log(chalk_1.default.green(` ✅ 환경변수: ${configuredEnvVars.join(", ")}`));
3233
+ }
3234
+ if (missingEnvVars.length > 0) {
3235
+ console.log(chalk_1.default.yellow(` ⚠️ 미설정 환경변수: ${missingEnvVars.join(", ")}`));
3236
+ console.log(chalk_1.default.gray(" 💡 일부 기능이 제한될 수 있습니다"));
3237
+ }
3238
+ // 도구 목록 (알려진 도구)
3239
+ const knownTools = [
3240
+ "slack_send_message",
3241
+ "slack_lookup_user",
3242
+ "slack_list_channels",
3243
+ "slack_find_channel",
3244
+ "github_create_issue",
3245
+ "github_create_pr",
3246
+ "supabase_query",
3247
+ ];
3248
+ console.log(chalk_1.default.gray(` 📦 제공 도구: ${knownTools.length}개`));
3249
+ }
3250
+ // 다른 MCP 서버 확인
3251
+ const otherServers = Object.keys(mcpServers).filter(k => k !== "semo-integrations");
3252
+ if (otherServers.length > 0) {
3253
+ console.log(chalk_1.default.gray(` 📡 기타 MCP 서버: ${otherServers.join(", ")}`));
3254
+ }
3255
+ }
3256
+ catch {
3257
+ console.log(chalk_1.default.red(" ❌ settings.local.json 파싱 오류"));
3258
+ }
3259
+ }
3260
+ // 6. 전체 설치 검증
3261
+ console.log(chalk_1.default.cyan("\n6. 전체 설치 검증"));
3042
3262
  const verificationResult = verifyInstallation(cwd, []);
3043
3263
  if (verificationResult.success) {
3044
3264
  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.2",
3
+ "version": "3.7.4",
4
4
  "description": "SEMO CLI - AI Agent Orchestration Framework Installer",
5
5
  "main": "dist/index.js",
6
6
  "bin": {