@team-semicolon/semo-cli 4.1.1 → 4.1.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.
@@ -189,6 +189,13 @@ function registerSessionsCommands(program) {
189
189
  last_activity = NOW(),
190
190
  message_count = COALESCE(EXCLUDED.message_count, semo.bot_sessions.message_count),
191
191
  synced_at = NOW()`, [botId, sessionKey, label, options.kind, messageCount ?? null]);
192
+ // bot_status.session_count 갱신
193
+ await client.query(`UPDATE semo.bot_status
194
+ SET session_count = (
195
+ SELECT COUNT(*) FROM semo.bot_sessions WHERE bot_id = $1
196
+ ),
197
+ synced_at = NOW()
198
+ WHERE bot_id = $1`, [botId]);
192
199
  }
193
200
  client.release();
194
201
  console.log(chalk_1.default.green(`✔ sessions push [${event}] ${botId}/${sessionKey.slice(0, 8)}`));
package/dist/index.js CHANGED
@@ -676,6 +676,11 @@ async function confirmOverwrite(itemName, itemPath) {
676
676
  if (!fs.existsSync(itemPath)) {
677
677
  return true;
678
678
  }
679
+ // 비인터랙티브 환경(CI, 파이프) — 덮어쓰지 않고 기존 파일 유지
680
+ if (!process.stdin.isTTY) {
681
+ console.log(chalk_1.default.gray(` → ${itemName} 이미 존재 (비인터랙티브 모드: 건너뜀)`));
682
+ return false;
683
+ }
679
684
  const { shouldOverwrite } = await inquirer_1.default.prompt([
680
685
  {
681
686
  type: "confirm",
@@ -776,7 +781,6 @@ program
776
781
  .option("--credentials-gist <gistId>", "Private GitHub Gist에서 팀 DB 접속정보 자동 가져오기")
777
782
  .action(async (options) => {
778
783
  console.log(chalk_1.default.cyan.bold("\n🚀 SEMO 설치 시작\n"));
779
- console.log(chalk_1.default.gray("Gemini 하이브리드 전략: White Box + Black Box\n"));
780
784
  const cwd = process.cwd();
781
785
  // 0.1. 버전 비교
782
786
  await showVersionComparison(cwd);
@@ -810,6 +814,8 @@ program
810
814
  fs.mkdirSync(claudeDir, { recursive: true });
811
815
  console.log(chalk_1.default.green("\n✓ .claude/ 디렉토리 생성됨"));
812
816
  }
817
+ // 2.5. ~/.semo.env DB 접속 설정 (자동 감지 → Gist → 프롬프트) — DB 연결 전에 먼저
818
+ await setupSemoEnv(options.credentialsGist);
813
819
  // 3. Standard 설치 (semo-core + semo-skills)
814
820
  await setupStandard(cwd, options.force);
815
821
  // 4. MCP 설정
@@ -822,10 +828,8 @@ program
822
828
  if (options.gitignore !== false) {
823
829
  updateGitignore(cwd);
824
830
  }
825
- // 7. Hooks 설치 (대화 로깅)
831
+ // 7. Hooks 설치
826
832
  await setupHooks(cwd, false);
827
- // 7.5. ~/.semo.env DB 접속 설정 (자동 감지 → Gist → 프롬프트)
828
- await setupSemoEnv(options.credentialsGist);
829
833
  // 8. CLAUDE.md 생성
830
834
  await setupClaudeMd(cwd, [], options.force);
831
835
  // 9. 설치 검증
@@ -845,11 +849,11 @@ program
845
849
  console.log(chalk_1.default.yellow.bold("\n⚠️ SEMO 설치 완료 (일부 문제 발견)\n"));
846
850
  }
847
851
  console.log(chalk_1.default.cyan("설치된 구성:"));
848
- console.log(chalk_1.default.gray(" [Standard]"));
849
- console.log(chalk_1.default.gray(" semo-core (원칙, 오케스트레이터)"));
850
- console.log(chalk_1.default.gray(" semo-skills (13개 통합 스킬)"));
851
- console.log(chalk_1.default.gray(" semo-agents (14개 페르소나 Agent)"));
852
- console.log(chalk_1.default.gray(" semo-scripts (자동화 스크립트)"));
852
+ console.log(chalk_1.default.gray(" ✓ .claude/skills/ (DB 기반 스킬)"));
853
+ console.log(chalk_1.default.gray(" .claude/agents/ (DB 기반 에이전트)"));
854
+ console.log(chalk_1.default.gray(" .claude/commands/ (슬래시 커맨드)"));
855
+ console.log(chalk_1.default.gray(" .claude/memory/ (컨텍스트 동기화)"));
856
+ console.log(chalk_1.default.gray(" ~/.claude/settings.local.json ( 등록)"));
853
857
  console.log(chalk_1.default.cyan("\n다음 단계:"));
854
858
  console.log(chalk_1.default.gray(" 1. Claude Code에서 프로젝트 열기 (SessionStart 훅이 자동 sync)"));
855
859
  console.log(chalk_1.default.gray(" 2. 자연어로 요청하기 (예: \"댓글 기능 구현해줘\")"));
@@ -929,8 +933,6 @@ async function setupStandard(cwd, force) {
929
933
  }
930
934
  console.log(chalk_1.default.green(` ✓ agents 설치 완료 (${agents.length}개)`));
931
935
  spinner.succeed("Standard 설치 완료 (DB 기반)");
932
- // CLAUDE.md 생성
933
- await generateClaudeMd(cwd);
934
936
  }
935
937
  catch (error) {
936
938
  spinner.fail("Standard 설치 실패");
@@ -1629,54 +1631,11 @@ semo-system/
1629
1631
  async function setupHooks(cwd, isUpdate = false) {
1630
1632
  const action = isUpdate ? "업데이트" : "설치";
1631
1633
  console.log(chalk_1.default.cyan(`\n🪝 Claude Code Hooks ${action}`));
1632
- console.log(chalk_1.default.gray(" 전체 대화 로깅 시스템\n"));
1633
- const hooksDir = path.join(cwd, "semo-system", "semo-hooks");
1634
- // semo-hooks 디렉토리 확인
1635
- if (!fs.existsSync(hooksDir)) {
1636
- console.log(chalk_1.default.yellow(" ⚠ semo-hooks 디렉토리 없음 (건너뜀)"));
1637
- return;
1638
- }
1639
- // 1. npm install
1640
- console.log(chalk_1.default.gray(" → 의존성 설치 중..."));
1641
- try {
1642
- (0, child_process_1.execSync)("npm install", {
1643
- cwd: hooksDir,
1644
- stdio: ["pipe", "pipe", "pipe"],
1645
- });
1646
- }
1647
- catch {
1648
- console.log(chalk_1.default.yellow(" ⚠ npm install 실패 (건너뜀)"));
1649
- return;
1650
- }
1651
- // 2. 빌드
1652
- console.log(chalk_1.default.gray(" → 빌드 중..."));
1653
- try {
1654
- (0, child_process_1.execSync)("npm run build", {
1655
- cwd: hooksDir,
1656
- stdio: ["pipe", "pipe", "pipe"],
1657
- });
1658
- }
1659
- catch {
1660
- console.log(chalk_1.default.yellow(" ⚠ 빌드 실패 (건너뜀)"));
1661
- return;
1662
- }
1663
- // 3. settings.local.json 설정
1664
1634
  const homeDir = process.env.HOME || process.env.USERPROFILE || "";
1665
1635
  const settingsPath = path.join(homeDir, ".claude", "settings.local.json");
1666
- const hooksCmd = `node ${path.join(hooksDir, "dist", "index.js")}`;
1667
- // hooks 설정 객체
1636
+ // Core 훅: semo context sync/push — semo-hooks 유무와 무관하게 항상 등록
1668
1637
  const hooksConfig = {
1669
1638
  SessionStart: [
1670
- {
1671
- matcher: "",
1672
- hooks: [
1673
- {
1674
- type: "command",
1675
- command: `${hooksCmd} session-start`,
1676
- timeout: 10,
1677
- },
1678
- ],
1679
- },
1680
1639
  {
1681
1640
  matcher: "",
1682
1641
  hooks: [
@@ -1688,29 +1647,7 @@ async function setupHooks(cwd, isUpdate = false) {
1688
1647
  ],
1689
1648
  },
1690
1649
  ],
1691
- UserPromptSubmit: [
1692
- {
1693
- matcher: "",
1694
- hooks: [
1695
- {
1696
- type: "command",
1697
- command: `${hooksCmd} user-prompt`,
1698
- timeout: 5,
1699
- },
1700
- ],
1701
- },
1702
- ],
1703
1650
  Stop: [
1704
- {
1705
- matcher: "",
1706
- hooks: [
1707
- {
1708
- type: "command",
1709
- command: `${hooksCmd} stop`,
1710
- timeout: 10,
1711
- },
1712
- ],
1713
- },
1714
1651
  {
1715
1652
  matcher: "",
1716
1653
  hooks: [
@@ -1722,19 +1659,37 @@ async function setupHooks(cwd, isUpdate = false) {
1722
1659
  ],
1723
1660
  },
1724
1661
  ],
1725
- SessionEnd: [
1726
- {
1727
- matcher: "",
1728
- hooks: [
1729
- {
1730
- type: "command",
1731
- command: `${hooksCmd} session-end`,
1732
- timeout: 10,
1733
- },
1734
- ],
1735
- },
1736
- ],
1737
1662
  };
1663
+ // semo-hooks 빌드 (선택적 — semo-system 레포에서만 동작)
1664
+ const hooksDir = path.join(cwd, "semo-system", "semo-hooks");
1665
+ if (fs.existsSync(hooksDir)) {
1666
+ let hooksBuilt = false;
1667
+ try {
1668
+ (0, child_process_1.execSync)("npm install", { cwd: hooksDir, stdio: ["pipe", "pipe", "pipe"] });
1669
+ (0, child_process_1.execSync)("npm run build", { cwd: hooksDir, stdio: ["pipe", "pipe", "pipe"] });
1670
+ hooksBuilt = true;
1671
+ }
1672
+ catch {
1673
+ console.log(chalk_1.default.yellow(" ⚠ semo-hooks 빌드 실패 (core 훅만 등록)"));
1674
+ }
1675
+ if (hooksBuilt) {
1676
+ const hooksCmd = `node ${path.join(hooksDir, "dist", "index.js")}`;
1677
+ hooksConfig.SessionStart.unshift({
1678
+ matcher: "",
1679
+ hooks: [{ type: "command", command: `${hooksCmd} session-start`, timeout: 10 }],
1680
+ });
1681
+ hooksConfig.UserPromptSubmit = [
1682
+ { matcher: "", hooks: [{ type: "command", command: `${hooksCmd} user-prompt`, timeout: 5 }] },
1683
+ ];
1684
+ hooksConfig.Stop.unshift({
1685
+ matcher: "",
1686
+ hooks: [{ type: "command", command: `${hooksCmd} stop`, timeout: 10 }],
1687
+ });
1688
+ hooksConfig.SessionEnd = [
1689
+ { matcher: "", hooks: [{ type: "command", command: `${hooksCmd} session-end`, timeout: 10 }] },
1690
+ ];
1691
+ }
1692
+ }
1738
1693
  // 기존 설정 로드 또는 새로 생성
1739
1694
  let existingSettings = {};
1740
1695
  const claudeConfigDir = path.join(homeDir, ".claude");
@@ -1935,133 +1890,132 @@ async function setupClaudeMd(cwd, _extensions, force) {
1935
1890
  return;
1936
1891
  }
1937
1892
  }
1938
- const orchestratorRefSection = `**반드시 읽어야 할 파일**: \`semo-system/semo-core/agents/orchestrator/orchestrator.md\`
1939
-
1940
- 파일에서 라우팅 테이블, 의도 분류, 메시지 포맷을 확인하세요.`;
1941
- const claudeMdContent = `# SEMO Project Configuration
1893
+ const projectName = path.basename(cwd);
1894
+ const installDate = new Date().toISOString().split("T")[0];
1895
+ const claudeMdContent = `# ${projectName} Claude Configuration
1942
1896
 
1943
- > SEMO (Semicolon Orchestrate) - AI Agent Orchestration Framework v${VERSION}
1897
+ > SEMO v${VERSION} 설치됨 (${installDate})
1944
1898
 
1945
1899
  ---
1946
1900
 
1947
- ## 🔴 MANDATORY: Memory Context (항시 참조)
1948
-
1949
- > **⚠️ 세션 시작 시 반드시 \`.claude/memory/\` 폴더의 파일들을 먼저 읽으세요. 예외 없음.**
1901
+ ## SEMO란?
1950
1902
 
1951
- ### 필수 참조 파일
1903
+ **SEMO (Semicolon Orchestrate)** 는 OpenClaw 봇팀과 로컬 Claude Code 세션이
1904
+ **팀 Core DB를 단일 진실 공급원(Single Source of Truth)으로 공유**하는 컨텍스트 동기화 시스템이다.
1952
1905
 
1953
1906
  \`\`\`
1954
- .claude/memory/
1955
- ├── context.md # 프로젝트 상태, 기술 스택, 진행 중 작업
1956
- ├── decisions.md # 아키텍처 결정 기록 (ADR)
1957
- ├── projects.md # GitHub Projects 설정
1958
- └── rules/ # 프로젝트별 커스텀 규칙
1907
+ 로컬 Claude Code 세션
1908
+ semo context sync / push
1909
+ Core DB (PostgreSQL, semo 스키마)
1910
+ 세션 시작/종료 훅
1911
+ OpenClaw 봇팀 (7개 봇)
1912
+ workclaw · reviewclaw · planclaw · designclaw
1913
+ infraclaw · growthclaw · semiclaw
1959
1914
  \`\`\`
1960
1915
 
1961
- **이 파일들은 세션의 컨텍스트를 유지하는 장기 기억입니다. 세션마다 반드시 읽고 시작하세요.**
1916
+ **이 CLAUDE.md가 설치된 프로젝트는 OpenClaw 봇팀의 컨텍스트를 실시간으로 공유받는다.**
1962
1917
 
1963
1918
  ---
1964
1919
 
1965
- ## 🔴 MANDATORY: Orchestrator-First Execution
1920
+ ## 자동 동기화
1966
1921
 
1967
- > **⚠️ 규칙은 모든 사용자 요청에 적용됩니다. 예외 없음.**
1922
+ 세션 시작/종료 Core DB와 자동 동기화됩니다.
1968
1923
 
1969
- ### 실행 흐름 (필수)
1924
+ | 시점 | 동작 |
1925
+ |------|------|
1926
+ | 세션 시작 | \`semo context sync\` → \`.claude/memory/\` 최신화 |
1927
+ | 세션 종료 | \`semo context push\` → \`decisions.md\` 변경분 DB 저장 |
1928
+
1929
+ ---
1930
+
1931
+ ## Memory Context
1932
+
1933
+ \`.claude/memory/\` 파일들은 **팀 Core DB (\`semo\` 스키마)에서 자동으로 채워집니다**.
1934
+ 직접 편집하지 마세요 — 세션 시작 시 덮어씌워집니다.
1935
+
1936
+ | 파일 | DB 소스 | 방향 |
1937
+ |------|---------|------|
1938
+ | \`team.md\` | \`kb WHERE domain='team'\` | DB → 로컬 (읽기 전용) |
1939
+ | \`projects.md\` | \`kb WHERE domain='project'\` | DB → 로컬 (읽기 전용) |
1940
+ | \`decisions.md\` | \`kb WHERE domain='decision'\` | **양방향** (편집 가능, Stop 시 DB 저장) |
1941
+ | \`infra.md\` | \`kb WHERE domain='infra'\` | DB → 로컬 (읽기 전용) |
1942
+ | \`process.md\` | \`kb WHERE domain='process'\` | DB → 로컬 (읽기 전용) |
1943
+ | \`bots.md\` | \`semo.bot_status\` | DB → 로컬 (봇 상태) |
1944
+ | \`ontology.md\` | \`semo.ontology\` | DB → 로컬 (읽기 전용) |
1945
+
1946
+ **decisions.md 만 편집 가능합니다.** 아키텍처 결정(ADR)을 여기에 기록하세요.
1947
+
1948
+ ---
1949
+
1950
+ ## 설치된 구성
1970
1951
 
1971
1952
  \`\`\`
1972
- 1. 사용자 요청 수신
1973
- 2. Orchestrator가 의도 분석 후 적절한 Agent/Skill 라우팅
1974
- 3. Agent/Skill이 작업 수행
1975
- 4. 실행 결과 반환
1953
+ .claude/
1954
+ ├── CLAUDE.md # 파일
1955
+ ├── settings.json # MCP 서버 설정 + SessionStart/Stop
1956
+ ├── memory/ # Core DB → 로컬 자동 동기화 컨텍스트
1957
+ ├── skills/ # SEMO 스킬 (semo-system/semo-skills/ 링크)
1958
+ ├── agents/ # SEMO 에이전트 (semo-system/meta/agents/ 링크)
1959
+ └── commands/SEMO # 슬래시 커맨드 (semo-system/semo-core/commands/)
1976
1960
  \`\`\`
1977
1961
 
1978
- ### Orchestrator 참조
1962
+ ---
1979
1963
 
1980
- ${orchestratorRefSection}
1964
+ ## 프로젝트 규칙 (팀이 채워야 함)
1981
1965
 
1982
- ---
1966
+ > 아래 섹션은 이 프로젝트 고유의 규칙을 기록하세요.
1967
+ > 팀 공통 규칙은 \`memory/process.md\`에 있습니다.
1983
1968
 
1984
- ## 🔴 NON-NEGOTIABLE RULES
1969
+ ### 기술 스택
1985
1970
 
1986
- ### 1. Orchestrator-First Policy
1971
+ <!-- 예: Next.js 14, PostgreSQL, TypeScript strict mode -->
1987
1972
 
1988
- > **모든 요청은 반드시 Orchestrator를 통해 라우팅됩니다. 직접 처리 금지.**
1973
+ ### 브랜치 전략
1989
1974
 
1990
- **직접 처리 금지 항목**:
1991
- - 코드 작성/수정 → \`implementation-master\` 또는 \`coder\` 스킬
1992
- - Git 커밋/푸시 → \`git-workflow\` 스킬
1993
- - 품질 검증 → \`quality-master\` 또는 \`verify\` 스킬
1994
- - 명세 작성 → \`spec-master\`
1995
- - 일반 작업 → Orchestrator 분석 후 라우팅
1975
+ <!-- 예: main(prod) / dev(staging) / feat/* -->
1996
1976
 
1997
- ### 2. Pre-Commit Quality Gate
1977
+ ### 코딩 컨벤션
1998
1978
 
1999
- > **코드 변경이 포함된 커밋 반드시 Quality Gate를 통과해야 합니다.**
1979
+ <!-- 예: ESLint airbnb, 함수형 컴포넌트 필수, any 금지 -->
2000
1980
 
2001
- \`\`\`bash
2002
- # 필수 검증 순서
2003
- npm run lint # 1. ESLint 검사
2004
- npx tsc --noEmit # 2. TypeScript 타입 체크
2005
- npm run build # 3. 빌드 검증 (Next.js/TypeScript 프로젝트)
2006
- \`\`\`
1981
+ ### 아키텍처 특이사항
2007
1982
 
2008
- **차단 항목**:
2009
- - \`--no-verify\` 플래그 사용 금지
2010
- - Quality Gate 우회 시도 거부
2011
- - "그냥 커밋해줘", "빌드 생략해줘" 등 거부
1983
+ <!-- 예: DB 직접 접근 금지 — 반드시 API route 통해야 함 -->
2012
1984
 
2013
1985
  ---
2014
1986
 
2015
- ## 설치된 구성
2016
-
2017
- ### Standard (필수)
2018
- - **semo-core**: 원칙, 오케스트레이터, 공통 커맨드
2019
- - **semo-skills**: 13개 통합 스킬
2020
- - 행동: coder, tester, planner, deployer, writer
2021
- - 운영: memory, notify-slack, feedback, version-updater, semo-help, semo-architecture-checker, circuit-breaker, list-bugs
1987
+ ## Quality Gate
2022
1988
 
2023
- ## 구조
1989
+ 코드 변경 커밋 전 필수:
2024
1990
 
2025
- \`\`\`
2026
- .claude/
2027
- ├── settings.json # MCP 서버 설정 (Black Box)
2028
- ├── memory/ # Context Mesh (장기 기억)
2029
- │ ├── context.md # 프로젝트 상태
2030
- │ ├── decisions.md # 아키텍처 결정
2031
- │ └── rules/ # 프로젝트별 규칙
2032
- ├── agents → semo-system/semo-core/agents
2033
- ├── skills → semo-system/semo-skills
2034
- └── commands/SEMO → semo-system/semo-core/commands/SEMO
2035
-
2036
- semo-system/ # White Box (읽기 전용)
2037
- ├── semo-core/ # Layer 0: 원칙, 오케스트레이션
2038
- └── semo-skills/ # Layer 1: 통합 스킬
1991
+ \`\`\`bash
1992
+ npm run lint # ESLint
1993
+ npx tsc --noEmit # TypeScript
1994
+ npm run build # 빌드 검증
2039
1995
  \`\`\`
2040
1996
 
2041
- ## 사용 가능한 커맨드
1997
+ \`--no-verify\` 사용 금지.
1998
+
1999
+ ---
2000
+
2001
+ ## 슬래시 커맨드
2042
2002
 
2043
2003
  | 커맨드 | 설명 |
2044
2004
  |--------|------|
2045
2005
  | \`/SEMO:help\` | 도움말 |
2046
2006
  | \`/SEMO:feedback\` | 피드백 제출 |
2047
- | \`/SEMO:update\` | SEMO 업데이트 |
2048
- | \`/SEMO:onboarding\` | 온보딩 가이드 |
2049
- | \`/SEMO:dry-run {프롬프트}\` | 명령 검증 (라우팅 시뮬레이션) |
2050
-
2051
- ## Context Mesh 사용
2052
-
2053
- SEMO는 \`.claude/memory/\`를 통해 세션 간 컨텍스트를 유지합니다:
2007
+ | \`/SEMO:health\` | 환경 헬스체크 |
2054
2008
 
2055
- - **context.md**: 프로젝트 상태, 진행 중인 작업
2056
- - **decisions.md**: 아키텍처 결정 기록 (ADR)
2057
- - **rules/**: 프로젝트별 커스텀 규칙
2058
-
2059
- memory 스킬이 자동으로 이 파일들을 관리합니다.
2009
+ ---
2060
2010
 
2061
- ## References
2011
+ ## 복구 명령어
2062
2012
 
2063
- - [SEMO Principles](semo-system/semo-core/principles/PRINCIPLES.md)
2064
- - [SEMO Skills](semo-system/semo-skills/)
2013
+ \`\`\`bash
2014
+ semo doctor # 환경 진단 (DB 연결, 설치 상태)
2015
+ semo config db # DB URL 재설정
2016
+ semo context sync # memory/ 수동 최신화
2017
+ semo bots status # 봇 상태 조회
2018
+ \`\`\`
2065
2019
  `;
2066
2020
  fs.writeFileSync(claudeMdPath, claudeMdContent);
2067
2021
  console.log(chalk_1.default.green("✓ .claude/CLAUDE.md 생성됨"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-semicolon/semo-cli",
3
- "version": "4.1.1",
3
+ "version": "4.1.3",
4
4
  "description": "SEMO CLI - AI Agent Orchestration Framework Installer",
5
5
  "main": "dist/index.js",
6
6
  "bin": {