@team-semicolon/semo-cli 3.12.0 → 3.13.0

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.
package/dist/index.js CHANGED
@@ -1354,7 +1354,7 @@ async function createStandardSymlinks(cwd) {
1354
1354
  }
1355
1355
  console.log(chalk_1.default.green(` ✓ .claude/agents/ (${agents.length}개 agent 링크됨)`));
1356
1356
  }
1357
- // skills 디렉토리 생성 및 개별 링크 (Extension 병합 지원)
1357
+ // skills 디렉토리 생성 및 개별 링크 (DB 기반 - 활성 스킬만)
1358
1358
  const claudeSkillsDir = path.join(claudeDir, "skills");
1359
1359
  const coreSkillsDir = path.join(semoSystemDir, "semo-skills");
1360
1360
  if (fs.existsSync(coreSkillsDir)) {
@@ -1363,15 +1363,19 @@ async function createStandardSymlinks(cwd) {
1363
1363
  removeRecursive(claudeSkillsDir);
1364
1364
  }
1365
1365
  fs.mkdirSync(claudeSkillsDir, { recursive: true });
1366
- const skills = fs.readdirSync(coreSkillsDir).filter(f => fs.statSync(path.join(coreSkillsDir, f)).isDirectory());
1367
- for (const skill of skills) {
1368
- const skillLink = path.join(claudeSkillsDir, skill);
1369
- const skillTarget = path.join(coreSkillsDir, skill);
1370
- if (!fs.existsSync(skillLink)) {
1366
+ // DB에서 활성 스킬 목록 조회 (19개 핵심 스킬만)
1367
+ const activeSkillNames = await (0, supabase_1.getActiveSkillNames)();
1368
+ let linkedCount = 0;
1369
+ for (const skillName of activeSkillNames) {
1370
+ const skillLink = path.join(claudeSkillsDir, skillName);
1371
+ const skillTarget = path.join(coreSkillsDir, skillName);
1372
+ // 스킬 폴더가 존재하는 경우에만 링크
1373
+ if (fs.existsSync(skillTarget) && !fs.existsSync(skillLink)) {
1371
1374
  createSymlinkOrJunction(skillTarget, skillLink);
1375
+ linkedCount++;
1372
1376
  }
1373
1377
  }
1374
- console.log(chalk_1.default.green(` ✓ .claude/skills/ (${skills.length}개 skill 링크됨)`));
1378
+ console.log(chalk_1.default.green(` ✓ .claude/skills/ (${linkedCount}개 skill 링크됨 - DB 기반)`));
1375
1379
  }
1376
1380
  // commands 링크
1377
1381
  const commandsDir = path.join(claudeDir, "commands");
@@ -71,3 +71,27 @@ export declare function buildExtensionPackagesFromDb(): Promise<Record<string, {
71
71
  detect: string[];
72
72
  layer: string;
73
73
  }>>;
74
+ export interface SkillDefinition {
75
+ id: string;
76
+ name: string;
77
+ display_name: string;
78
+ description: string | null;
79
+ category: "workflow" | "discovery" | "planning" | "solutioning" | "implementation" | "supporting";
80
+ source_path: string;
81
+ is_active: boolean;
82
+ is_required: boolean;
83
+ install_order: number;
84
+ version: string;
85
+ }
86
+ /**
87
+ * 활성 스킬 목록 조회 (설치할 스킬)
88
+ */
89
+ export declare function getActiveSkills(): Promise<SkillDefinition[]>;
90
+ /**
91
+ * 스킬 이름 목록만 조회
92
+ */
93
+ export declare function getActiveSkillNames(): Promise<string[]>;
94
+ /**
95
+ * 카테고리별 스킬 개수 조회
96
+ */
97
+ export declare function getSkillCountByCategory(): Promise<Record<string, number>>;
package/dist/supabase.js CHANGED
@@ -16,6 +16,9 @@ exports.getDetectablePackages = getDetectablePackages;
16
16
  exports.toExtensionPackageFormat = toExtensionPackageFormat;
17
17
  exports.buildShortnameMappingFromDb = buildShortnameMappingFromDb;
18
18
  exports.buildExtensionPackagesFromDb = buildExtensionPackagesFromDb;
19
+ exports.getActiveSkills = getActiveSkills;
20
+ exports.getActiveSkillNames = getActiveSkillNames;
21
+ exports.getSkillCountByCategory = getSkillCountByCategory;
19
22
  const supabase_js_1 = require("@supabase/supabase-js");
20
23
  // Supabase 연결 정보 (공개 프로젝트용)
21
24
  const SUPABASE_URL = process.env.SEMO_SUPABASE_URL || "https://vdrllieckyeumbhyclkc.supabase.co";
@@ -530,3 +533,70 @@ async function buildExtensionPackagesFromDb() {
530
533
  }
531
534
  return result;
532
535
  }
536
+ // 폴백 스킬 목록 (DB 연결 실패 시 사용)
537
+ const FALLBACK_SKILLS = [
538
+ // Workflow Management (3개)
539
+ { id: "sk-1", name: "workflow-start", display_name: "워크플로우 시작", description: "워크플로우 인스턴스 생성 및 시작", category: "workflow", source_path: "semo-skills/workflow-start", is_active: true, is_required: true, install_order: 1, version: "1.0.0" },
540
+ { id: "sk-2", name: "workflow-progress", display_name: "워크플로우 진행", description: "워크플로우 진행 상황 조회", category: "workflow", source_path: "semo-skills/workflow-progress", is_active: true, is_required: true, install_order: 2, version: "1.0.0" },
541
+ { id: "sk-3", name: "workflow-resume", display_name: "워크플로우 재개", description: "중단된 워크플로우 재개", category: "workflow", source_path: "semo-skills/workflow-resume", is_active: true, is_required: true, install_order: 3, version: "1.0.0" },
542
+ // Discovery (1개)
543
+ { id: "sk-10", name: "ideate", display_name: "아이디에이션", description: "아이디어 발굴 및 분석", category: "discovery", source_path: "semo-skills/ideate", is_active: true, is_required: true, install_order: 10, version: "1.0.0" },
544
+ // Planning (3개)
545
+ { id: "sk-20", name: "create-epic", display_name: "Epic 생성", description: "Epic 이슈 생성", category: "planning", source_path: "semo-skills/create-epic", is_active: true, is_required: true, install_order: 20, version: "1.0.0" },
546
+ { id: "sk-21", name: "design-user-flow", display_name: "사용자 흐름 설계", description: "UX 사용자 흐름 다이어그램 설계", category: "planning", source_path: "semo-skills/design-user-flow", is_active: true, is_required: true, install_order: 21, version: "1.0.0" },
547
+ { id: "sk-22", name: "generate-mockup", display_name: "목업 생성", description: "UI 목업 생성", category: "planning", source_path: "semo-skills/generate-mockup", is_active: true, is_required: true, install_order: 22, version: "1.0.0" },
548
+ // Solutioning (4개)
549
+ { id: "sk-30", name: "scaffold-domain", display_name: "도메인 스캐폴딩", description: "DDD 4-layer 도메인 구조 생성", category: "solutioning", source_path: "semo-skills/scaffold-domain", is_active: true, is_required: true, install_order: 30, version: "1.0.0" },
550
+ { id: "sk-31", name: "validate-architecture", display_name: "아키텍처 검증", description: "DDD 4-layer 아키텍처 준수 검증", category: "solutioning", source_path: "semo-skills/validate-architecture", is_active: true, is_required: true, install_order: 31, version: "1.0.0" },
551
+ { id: "sk-32", name: "generate-spec", display_name: "명세 생성", description: "Speckit 워크플로우 통합 실행", category: "solutioning", source_path: "semo-skills/generate-spec", is_active: true, is_required: true, install_order: 32, version: "1.0.0" },
552
+ { id: "sk-33", name: "design-tests", display_name: "테스트 설계", description: "구현 전 테스트 케이스 설계 (TDD)", category: "solutioning", source_path: "semo-skills/design-tests", is_active: true, is_required: true, install_order: 33, version: "1.0.0" },
553
+ // Implementation (6개)
554
+ { id: "sk-40", name: "create-sprint", display_name: "스프린트 생성", description: "Sprint 목표 설정 및 시작", category: "implementation", source_path: "semo-skills/create-sprint", is_active: true, is_required: true, install_order: 40, version: "1.0.0" },
555
+ { id: "sk-41", name: "start-task", display_name: "태스크 시작", description: "작업 시작 (이슈 상태 변경, 브랜치 생성)", category: "implementation", source_path: "semo-skills/start-task", is_active: true, is_required: true, install_order: 41, version: "1.0.0" },
556
+ { id: "sk-42", name: "review-task", display_name: "태스크 리뷰", description: "태스크 이슈 기반 구현 완료 리뷰", category: "implementation", source_path: "semo-skills/review-task", is_active: true, is_required: true, install_order: 42, version: "1.0.0" },
557
+ { id: "sk-43", name: "write-code", display_name: "코드 작성", description: "코드 작성, 수정, 구현", category: "implementation", source_path: "semo-skills/write-code", is_active: true, is_required: true, install_order: 43, version: "1.0.0" },
558
+ { id: "sk-44", name: "run-code-review", display_name: "코드 리뷰", description: "프로젝트 통합 코드 리뷰", category: "implementation", source_path: "semo-skills/run-code-review", is_active: true, is_required: true, install_order: 44, version: "1.0.0" },
559
+ { id: "sk-45", name: "close-sprint", display_name: "스프린트 종료", description: "Sprint 종료 및 회고 정리", category: "implementation", source_path: "semo-skills/close-sprint", is_active: true, is_required: true, install_order: 45, version: "1.0.0" },
560
+ // Supporting (2개)
561
+ { id: "sk-50", name: "git-workflow", display_name: "Git 워크플로우", description: "Git 커밋/푸시/PR 자동화", category: "supporting", source_path: "semo-skills/git-workflow", is_active: true, is_required: true, install_order: 50, version: "1.0.0" },
562
+ { id: "sk-51", name: "notify-slack", display_name: "Slack 알림", description: "Slack 채널에 메시지 전송", category: "supporting", source_path: "semo-skills/notify-slack", is_active: true, is_required: true, install_order: 51, version: "1.0.0" },
563
+ ];
564
+ /**
565
+ * 활성 스킬 목록 조회 (설치할 스킬)
566
+ */
567
+ async function getActiveSkills() {
568
+ const isConnected = await checkDbConnection();
569
+ if (!isConnected) {
570
+ console.warn("⚠️ DB 연결 실패, 폴백 스킬 목록 사용 (19개)");
571
+ return FALLBACK_SKILLS.filter(s => s.is_active);
572
+ }
573
+ const supabase = getSupabaseClient();
574
+ const { data, error } = await supabase
575
+ .from("skill_definitions")
576
+ .select("*")
577
+ .eq("is_active", true)
578
+ .order("install_order");
579
+ if (error) {
580
+ console.warn("⚠️ 스킬 조회 실패, 폴백 데이터 사용");
581
+ return FALLBACK_SKILLS.filter(s => s.is_active);
582
+ }
583
+ return data || FALLBACK_SKILLS.filter(s => s.is_active);
584
+ }
585
+ /**
586
+ * 스킬 이름 목록만 조회
587
+ */
588
+ async function getActiveSkillNames() {
589
+ const skills = await getActiveSkills();
590
+ return skills.map(s => s.name);
591
+ }
592
+ /**
593
+ * 카테고리별 스킬 개수 조회
594
+ */
595
+ async function getSkillCountByCategory() {
596
+ const skills = await getActiveSkills();
597
+ const counts = {};
598
+ for (const skill of skills) {
599
+ counts[skill.category] = (counts[skill.category] || 0) + 1;
600
+ }
601
+ return counts;
602
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-semicolon/semo-cli",
3
- "version": "3.12.0",
3
+ "version": "3.13.0",
4
4
  "description": "SEMO CLI - AI Agent Orchestration Framework Installer",
5
5
  "main": "dist/index.js",
6
6
  "bin": {