@team-semicolon/semo-cli 3.0.28 → 3.0.30
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/README.md +231 -231
- package/dist/index.js +472 -349
- package/package.json +48 -48
package/dist/index.js
CHANGED
|
@@ -450,6 +450,9 @@ const EXTENSION_PACKAGES = {
|
|
|
450
450
|
"ops/improve": { name: "Improve", desc: "개선 제안", layer: "ops", detect: [] },
|
|
451
451
|
// Meta
|
|
452
452
|
meta: { name: "Meta", desc: "SEMO 프레임워크 자체 개발/관리", layer: "meta", detect: ["semo-core", "semo-skills"] },
|
|
453
|
+
// System (semo-system 하위 패키지)
|
|
454
|
+
"semo-hooks": { name: "Hooks", desc: "Claude Code Hooks 기반 로깅 시스템", layer: "system", detect: [] },
|
|
455
|
+
"semo-remote": { name: "Remote", desc: "Claude Code 원격 제어 (모바일 PWA)", layer: "system", detect: [] },
|
|
453
456
|
};
|
|
454
457
|
// 단축명 → 전체 패키지 경로 매핑
|
|
455
458
|
const SHORTNAME_MAPPING = {
|
|
@@ -469,9 +472,12 @@ const SHORTNAME_MAPPING = {
|
|
|
469
472
|
next: "eng/nextjs",
|
|
470
473
|
backend: "eng/spring",
|
|
471
474
|
mvp: "biz/poc",
|
|
475
|
+
// System 패키지 단축명
|
|
476
|
+
hooks: "semo-hooks",
|
|
477
|
+
remote: "semo-remote",
|
|
472
478
|
};
|
|
473
|
-
// 그룹 이름 목록 (biz, eng, ops)
|
|
474
|
-
const PACKAGE_GROUPS = ["biz", "eng", "ops", "meta"];
|
|
479
|
+
// 그룹 이름 목록 (biz, eng, ops, meta, system)
|
|
480
|
+
const PACKAGE_GROUPS = ["biz", "eng", "ops", "meta", "system"];
|
|
475
481
|
// 그룹명 → 해당 그룹의 모든 패키지 반환
|
|
476
482
|
function getPackagesByGroup(group) {
|
|
477
483
|
return Object.entries(EXTENSION_PACKAGES)
|
|
@@ -766,7 +772,7 @@ async function confirmOverwrite(itemName, itemPath) {
|
|
|
766
772
|
type: "confirm",
|
|
767
773
|
name: "shouldOverwrite",
|
|
768
774
|
message: chalk_1.default.yellow(`${itemName} 이미 존재합니다. SEMO 기준으로 덮어쓰시겠습니까?`),
|
|
769
|
-
default:
|
|
775
|
+
default: true,
|
|
770
776
|
},
|
|
771
777
|
]);
|
|
772
778
|
return shouldOverwrite;
|
|
@@ -975,13 +981,15 @@ program
|
|
|
975
981
|
if (options.gitignore !== false) {
|
|
976
982
|
updateGitignore(cwd);
|
|
977
983
|
}
|
|
978
|
-
// 9.
|
|
984
|
+
// 9. Hooks 설치 (대화 로깅)
|
|
985
|
+
await setupHooks(cwd, false);
|
|
986
|
+
// 10. CLAUDE.md 생성
|
|
979
987
|
await setupClaudeMd(cwd, extensionsToInstall, options.force);
|
|
980
|
-
//
|
|
988
|
+
// 11. Extensions 심볼릭 링크 (agents/skills 병합)
|
|
981
989
|
if (extensionsToInstall.length > 0) {
|
|
982
990
|
await setupExtensionSymlinks(cwd, extensionsToInstall);
|
|
983
991
|
}
|
|
984
|
-
//
|
|
992
|
+
// 12. 설치 검증
|
|
985
993
|
const verificationResult = verifyInstallation(cwd, extensionsToInstall);
|
|
986
994
|
printVerificationResult(verificationResult);
|
|
987
995
|
// 완료 메시지
|
|
@@ -1445,89 +1453,89 @@ function createMergedOrchestrator(claudeAgentsDir, orchestratorSources) {
|
|
|
1445
1453
|
}
|
|
1446
1454
|
}
|
|
1447
1455
|
// 병합된 orchestrator.md 생성
|
|
1448
|
-
const mergedContent = `---
|
|
1449
|
-
name: orchestrator
|
|
1450
|
-
description: |
|
|
1451
|
-
SEMO Merged Orchestrator - Routes all user requests to appropriate agents/skills.
|
|
1452
|
-
This orchestrator combines routing tables from ${orchestratorSources.length} packages.
|
|
1453
|
-
PROACTIVELY delegate on ALL requests. Never process directly.
|
|
1454
|
-
tools:
|
|
1455
|
-
- read_file
|
|
1456
|
-
- list_dir
|
|
1457
|
-
- run_command
|
|
1458
|
-
- glob
|
|
1459
|
-
- grep
|
|
1460
|
-
- task
|
|
1461
|
-
- skill
|
|
1462
|
-
model: inherit
|
|
1463
|
-
---
|
|
1464
|
-
|
|
1465
|
-
# SEMO Merged Orchestrator
|
|
1466
|
-
|
|
1467
|
-
> 이 파일은 **자동 생성**되었습니다. 직접 수정하지 마세요.
|
|
1468
|
-
> 원본 파일: \`_packages/\` 디렉토리 참조
|
|
1469
|
-
|
|
1470
|
-
모든 사용자 요청을 분석하고 적절한 Agent 또는 Skill로 라우팅하는 **Primary Router**입니다.
|
|
1471
|
-
|
|
1472
|
-
## 🔴 설치된 패키지
|
|
1473
|
-
|
|
1474
|
-
${orchestratorSources.map(s => `- **${EXTENSION_PACKAGES[s.pkg]?.name || s.pkg}**: \`semo-system/${s.pkg}\``).join("\n")}
|
|
1475
|
-
|
|
1476
|
-
## �� Quick Routing Table (Merged)
|
|
1477
|
-
|
|
1478
|
-
> 키워드 매칭 시 **첫 번째 매칭된 패키지**로 라우팅됩니다.
|
|
1479
|
-
|
|
1480
|
-
${routingTables.join("\n\n---\n\n")}
|
|
1481
|
-
|
|
1482
|
-
## SEMO 메시지 포맷
|
|
1483
|
-
|
|
1484
|
-
### Agent 위임
|
|
1485
|
-
|
|
1486
|
-
\`\`\`markdown
|
|
1487
|
-
[SEMO] Orchestrator: 의도 분석 완료 → {intent_category}
|
|
1488
|
-
|
|
1489
|
-
[SEMO] Agent 위임: {agent_name} (사유: {reason})
|
|
1490
|
-
\`\`\`
|
|
1491
|
-
|
|
1492
|
-
### Skill 호출
|
|
1493
|
-
|
|
1494
|
-
\`\`\`markdown
|
|
1495
|
-
[SEMO] Orchestrator: 의도 분석 완료 → {intent_category}
|
|
1496
|
-
|
|
1497
|
-
[SEMO] Skill 호출: {skill_name}
|
|
1498
|
-
\`\`\`
|
|
1499
|
-
|
|
1500
|
-
### 라우팅 실패
|
|
1501
|
-
|
|
1502
|
-
\`\`\`markdown
|
|
1503
|
-
[SEMO] Orchestrator: 라우팅 실패 → 적절한 Agent/Skill 없음
|
|
1504
|
-
|
|
1505
|
-
⚠️ 직접 처리 필요
|
|
1506
|
-
\`\`\`
|
|
1507
|
-
|
|
1508
|
-
## Critical Rules
|
|
1509
|
-
|
|
1510
|
-
1. **Routing-Only**: 직접 작업 수행 금지
|
|
1511
|
-
2. **SEMO 메시지 필수**: 모든 위임에 SEMO 메시지 포함
|
|
1512
|
-
3. **Package Priority**: 라우팅 충돌 시 설치 순서대로 우선순위 적용
|
|
1513
|
-
4. **Cross-Package**: 다른 패키지 전문 영역 요청 시 인계 권유
|
|
1514
|
-
|
|
1515
|
-
${crossPackageRouting.length > 0 ? `## 🔄 Cross-Package Routing
|
|
1516
|
-
|
|
1517
|
-
${crossPackageRouting[0]}` : ""}
|
|
1518
|
-
|
|
1519
|
-
${availableAgents.length > 0 ? `## Available Agents (All Packages)
|
|
1520
|
-
|
|
1521
|
-
${availableAgents.join("\n\n")}` : ""}
|
|
1522
|
-
|
|
1523
|
-
${availableSkills.length > 0 ? `## Available Skills (All Packages)
|
|
1524
|
-
|
|
1525
|
-
${availableSkills.join("\n\n")}` : ""}
|
|
1526
|
-
|
|
1527
|
-
## References
|
|
1528
|
-
|
|
1529
|
-
- 원본 Orchestrator: \`_packages/\` 디렉토리
|
|
1530
|
-
- 병합된 References: \`references/\` 디렉토리
|
|
1456
|
+
const mergedContent = `---
|
|
1457
|
+
name: orchestrator
|
|
1458
|
+
description: |
|
|
1459
|
+
SEMO Merged Orchestrator - Routes all user requests to appropriate agents/skills.
|
|
1460
|
+
This orchestrator combines routing tables from ${orchestratorSources.length} packages.
|
|
1461
|
+
PROACTIVELY delegate on ALL requests. Never process directly.
|
|
1462
|
+
tools:
|
|
1463
|
+
- read_file
|
|
1464
|
+
- list_dir
|
|
1465
|
+
- run_command
|
|
1466
|
+
- glob
|
|
1467
|
+
- grep
|
|
1468
|
+
- task
|
|
1469
|
+
- skill
|
|
1470
|
+
model: inherit
|
|
1471
|
+
---
|
|
1472
|
+
|
|
1473
|
+
# SEMO Merged Orchestrator
|
|
1474
|
+
|
|
1475
|
+
> 이 파일은 **자동 생성**되었습니다. 직접 수정하지 마세요.
|
|
1476
|
+
> 원본 파일: \`_packages/\` 디렉토리 참조
|
|
1477
|
+
|
|
1478
|
+
모든 사용자 요청을 분석하고 적절한 Agent 또는 Skill로 라우팅하는 **Primary Router**입니다.
|
|
1479
|
+
|
|
1480
|
+
## 🔴 설치된 패키지
|
|
1481
|
+
|
|
1482
|
+
${orchestratorSources.map(s => `- **${EXTENSION_PACKAGES[s.pkg]?.name || s.pkg}**: \`semo-system/${s.pkg}\``).join("\n")}
|
|
1483
|
+
|
|
1484
|
+
## �� Quick Routing Table (Merged)
|
|
1485
|
+
|
|
1486
|
+
> 키워드 매칭 시 **첫 번째 매칭된 패키지**로 라우팅됩니다.
|
|
1487
|
+
|
|
1488
|
+
${routingTables.join("\n\n---\n\n")}
|
|
1489
|
+
|
|
1490
|
+
## SEMO 메시지 포맷
|
|
1491
|
+
|
|
1492
|
+
### Agent 위임
|
|
1493
|
+
|
|
1494
|
+
\`\`\`markdown
|
|
1495
|
+
[SEMO] Orchestrator: 의도 분석 완료 → {intent_category}
|
|
1496
|
+
|
|
1497
|
+
[SEMO] Agent 위임: {agent_name} (사유: {reason})
|
|
1498
|
+
\`\`\`
|
|
1499
|
+
|
|
1500
|
+
### Skill 호출
|
|
1501
|
+
|
|
1502
|
+
\`\`\`markdown
|
|
1503
|
+
[SEMO] Orchestrator: 의도 분석 완료 → {intent_category}
|
|
1504
|
+
|
|
1505
|
+
[SEMO] Skill 호출: {skill_name}
|
|
1506
|
+
\`\`\`
|
|
1507
|
+
|
|
1508
|
+
### 라우팅 실패
|
|
1509
|
+
|
|
1510
|
+
\`\`\`markdown
|
|
1511
|
+
[SEMO] Orchestrator: 라우팅 실패 → 적절한 Agent/Skill 없음
|
|
1512
|
+
|
|
1513
|
+
⚠️ 직접 처리 필요
|
|
1514
|
+
\`\`\`
|
|
1515
|
+
|
|
1516
|
+
## Critical Rules
|
|
1517
|
+
|
|
1518
|
+
1. **Routing-Only**: 직접 작업 수행 금지
|
|
1519
|
+
2. **SEMO 메시지 필수**: 모든 위임에 SEMO 메시지 포함
|
|
1520
|
+
3. **Package Priority**: 라우팅 충돌 시 설치 순서대로 우선순위 적용
|
|
1521
|
+
4. **Cross-Package**: 다른 패키지 전문 영역 요청 시 인계 권유
|
|
1522
|
+
|
|
1523
|
+
${crossPackageRouting.length > 0 ? `## 🔄 Cross-Package Routing
|
|
1524
|
+
|
|
1525
|
+
${crossPackageRouting[0]}` : ""}
|
|
1526
|
+
|
|
1527
|
+
${availableAgents.length > 0 ? `## Available Agents (All Packages)
|
|
1528
|
+
|
|
1529
|
+
${availableAgents.join("\n\n")}` : ""}
|
|
1530
|
+
|
|
1531
|
+
${availableSkills.length > 0 ? `## Available Skills (All Packages)
|
|
1532
|
+
|
|
1533
|
+
${availableSkills.join("\n\n")}` : ""}
|
|
1534
|
+
|
|
1535
|
+
## References
|
|
1536
|
+
|
|
1537
|
+
- 원본 Orchestrator: \`_packages/\` 디렉토리
|
|
1538
|
+
- 병합된 References: \`references/\` 디렉토리
|
|
1531
1539
|
`;
|
|
1532
1540
|
fs.writeFileSync(path.join(orchestratorDir, "orchestrator.md"), mergedContent);
|
|
1533
1541
|
}
|
|
@@ -1882,12 +1890,12 @@ async function mergeExtensionSettings(cwd, packages) {
|
|
|
1882
1890
|
function updateGitignore(cwd) {
|
|
1883
1891
|
console.log(chalk_1.default.cyan("\n📝 .gitignore 업데이트"));
|
|
1884
1892
|
const gitignorePath = path.join(cwd, ".gitignore");
|
|
1885
|
-
const semoIgnoreBlock = `
|
|
1886
|
-
# === SEMO ===
|
|
1887
|
-
.claude/*
|
|
1888
|
-
!.claude/memory/
|
|
1889
|
-
!.claude/memory/**
|
|
1890
|
-
semo-system/
|
|
1893
|
+
const semoIgnoreBlock = `
|
|
1894
|
+
# === SEMO ===
|
|
1895
|
+
.claude/*
|
|
1896
|
+
!.claude/memory/
|
|
1897
|
+
!.claude/memory/**
|
|
1898
|
+
semo-system/
|
|
1891
1899
|
`;
|
|
1892
1900
|
if (fs.existsSync(gitignorePath)) {
|
|
1893
1901
|
const content = fs.readFileSync(gitignorePath, "utf-8");
|
|
@@ -1906,6 +1914,117 @@ semo-system/
|
|
|
1906
1914
|
console.log(chalk_1.default.green("✓ .gitignore 생성됨 (SEMO 규칙 포함)"));
|
|
1907
1915
|
}
|
|
1908
1916
|
}
|
|
1917
|
+
// === Hooks 설치/업데이트 ===
|
|
1918
|
+
async function setupHooks(cwd, isUpdate = false) {
|
|
1919
|
+
const action = isUpdate ? "업데이트" : "설치";
|
|
1920
|
+
console.log(chalk_1.default.cyan(`\n🪝 Claude Code Hooks ${action}`));
|
|
1921
|
+
console.log(chalk_1.default.gray(" 전체 대화 로깅 시스템\n"));
|
|
1922
|
+
const hooksDir = path.join(cwd, "semo-system", "semo-hooks");
|
|
1923
|
+
// semo-hooks 디렉토리 확인
|
|
1924
|
+
if (!fs.existsSync(hooksDir)) {
|
|
1925
|
+
console.log(chalk_1.default.yellow(" ⚠ semo-hooks 디렉토리 없음 (건너뜀)"));
|
|
1926
|
+
return;
|
|
1927
|
+
}
|
|
1928
|
+
// 1. npm install
|
|
1929
|
+
console.log(chalk_1.default.gray(" → 의존성 설치 중..."));
|
|
1930
|
+
try {
|
|
1931
|
+
(0, child_process_1.execSync)("npm install", {
|
|
1932
|
+
cwd: hooksDir,
|
|
1933
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1936
|
+
catch {
|
|
1937
|
+
console.log(chalk_1.default.yellow(" ⚠ npm install 실패 (건너뜀)"));
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
// 2. 빌드
|
|
1941
|
+
console.log(chalk_1.default.gray(" → 빌드 중..."));
|
|
1942
|
+
try {
|
|
1943
|
+
(0, child_process_1.execSync)("npm run build", {
|
|
1944
|
+
cwd: hooksDir,
|
|
1945
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
1946
|
+
});
|
|
1947
|
+
}
|
|
1948
|
+
catch {
|
|
1949
|
+
console.log(chalk_1.default.yellow(" ⚠ 빌드 실패 (건너뜀)"));
|
|
1950
|
+
return;
|
|
1951
|
+
}
|
|
1952
|
+
// 3. settings.local.json 설정
|
|
1953
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
1954
|
+
const settingsPath = path.join(homeDir, ".claude", "settings.local.json");
|
|
1955
|
+
const hooksCmd = `node ${path.join(hooksDir, "dist", "index.js")}`;
|
|
1956
|
+
// hooks 설정 객체
|
|
1957
|
+
const hooksConfig = {
|
|
1958
|
+
SessionStart: [
|
|
1959
|
+
{
|
|
1960
|
+
matcher: "",
|
|
1961
|
+
hooks: [
|
|
1962
|
+
{
|
|
1963
|
+
type: "command",
|
|
1964
|
+
command: `${hooksCmd} session-start`,
|
|
1965
|
+
timeout: 10,
|
|
1966
|
+
},
|
|
1967
|
+
],
|
|
1968
|
+
},
|
|
1969
|
+
],
|
|
1970
|
+
UserPromptSubmit: [
|
|
1971
|
+
{
|
|
1972
|
+
matcher: "",
|
|
1973
|
+
hooks: [
|
|
1974
|
+
{
|
|
1975
|
+
type: "command",
|
|
1976
|
+
command: `${hooksCmd} user-prompt`,
|
|
1977
|
+
timeout: 5,
|
|
1978
|
+
},
|
|
1979
|
+
],
|
|
1980
|
+
},
|
|
1981
|
+
],
|
|
1982
|
+
Stop: [
|
|
1983
|
+
{
|
|
1984
|
+
matcher: "",
|
|
1985
|
+
hooks: [
|
|
1986
|
+
{
|
|
1987
|
+
type: "command",
|
|
1988
|
+
command: `${hooksCmd} stop`,
|
|
1989
|
+
timeout: 10,
|
|
1990
|
+
},
|
|
1991
|
+
],
|
|
1992
|
+
},
|
|
1993
|
+
],
|
|
1994
|
+
SessionEnd: [
|
|
1995
|
+
{
|
|
1996
|
+
matcher: "",
|
|
1997
|
+
hooks: [
|
|
1998
|
+
{
|
|
1999
|
+
type: "command",
|
|
2000
|
+
command: `${hooksCmd} session-end`,
|
|
2001
|
+
timeout: 10,
|
|
2002
|
+
},
|
|
2003
|
+
],
|
|
2004
|
+
},
|
|
2005
|
+
],
|
|
2006
|
+
};
|
|
2007
|
+
// 기존 설정 로드 또는 새로 생성
|
|
2008
|
+
let existingSettings = {};
|
|
2009
|
+
const claudeConfigDir = path.join(homeDir, ".claude");
|
|
2010
|
+
if (!fs.existsSync(claudeConfigDir)) {
|
|
2011
|
+
fs.mkdirSync(claudeConfigDir, { recursive: true });
|
|
2012
|
+
}
|
|
2013
|
+
if (fs.existsSync(settingsPath)) {
|
|
2014
|
+
try {
|
|
2015
|
+
existingSettings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
2016
|
+
}
|
|
2017
|
+
catch {
|
|
2018
|
+
existingSettings = {};
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
// hooks 설정 병합
|
|
2022
|
+
existingSettings.hooks = hooksConfig;
|
|
2023
|
+
// 설정 저장
|
|
2024
|
+
fs.writeFileSync(settingsPath, JSON.stringify(existingSettings, null, 2));
|
|
2025
|
+
console.log(chalk_1.default.green(` ✓ Hooks ${action} 완료`));
|
|
2026
|
+
console.log(chalk_1.default.gray(` 설정: ${settingsPath}`));
|
|
2027
|
+
}
|
|
1909
2028
|
// === Context Mesh 초기화 ===
|
|
1910
2029
|
async function setupContextMesh(cwd) {
|
|
1911
2030
|
console.log(chalk_1.default.cyan("\n🧠 Context Mesh 초기화"));
|
|
@@ -1915,36 +2034,36 @@ async function setupContextMesh(cwd) {
|
|
|
1915
2034
|
// context.md
|
|
1916
2035
|
const contextPath = path.join(memoryDir, "context.md");
|
|
1917
2036
|
if (!fs.existsSync(contextPath)) {
|
|
1918
|
-
const contextContent = `# Project Context
|
|
1919
|
-
|
|
1920
|
-
> 세션 간 영속화되는 프로젝트 컨텍스트
|
|
1921
|
-
> SEMO의 memory 스킬이 이 파일을 자동으로 업데이트합니다.
|
|
1922
|
-
|
|
1923
|
-
---
|
|
1924
|
-
|
|
1925
|
-
## 프로젝트 정보
|
|
1926
|
-
|
|
1927
|
-
| 항목 | 값 |
|
|
1928
|
-
|------|-----|
|
|
1929
|
-
| **이름** | ${path.basename(cwd)} |
|
|
1930
|
-
| **SEMO 버전** | ${VERSION} |
|
|
1931
|
-
| **설치일** | ${new Date().toISOString().split("T")[0]} |
|
|
1932
|
-
|
|
1933
|
-
---
|
|
1934
|
-
|
|
1935
|
-
## 현재 작업 상태
|
|
1936
|
-
|
|
1937
|
-
_아직 작업 기록이 없습니다._
|
|
1938
|
-
|
|
1939
|
-
---
|
|
1940
|
-
|
|
1941
|
-
## 기술 스택
|
|
1942
|
-
|
|
1943
|
-
_프로젝트 분석 후 자동으로 채워집니다._
|
|
1944
|
-
|
|
1945
|
-
---
|
|
1946
|
-
|
|
1947
|
-
*마지막 업데이트: ${new Date().toISOString().split("T")[0]}*
|
|
2037
|
+
const contextContent = `# Project Context
|
|
2038
|
+
|
|
2039
|
+
> 세션 간 영속화되는 프로젝트 컨텍스트
|
|
2040
|
+
> SEMO의 memory 스킬이 이 파일을 자동으로 업데이트합니다.
|
|
2041
|
+
|
|
2042
|
+
---
|
|
2043
|
+
|
|
2044
|
+
## 프로젝트 정보
|
|
2045
|
+
|
|
2046
|
+
| 항목 | 값 |
|
|
2047
|
+
|------|-----|
|
|
2048
|
+
| **이름** | ${path.basename(cwd)} |
|
|
2049
|
+
| **SEMO 버전** | ${VERSION} |
|
|
2050
|
+
| **설치일** | ${new Date().toISOString().split("T")[0]} |
|
|
2051
|
+
|
|
2052
|
+
---
|
|
2053
|
+
|
|
2054
|
+
## 현재 작업 상태
|
|
2055
|
+
|
|
2056
|
+
_아직 작업 기록이 없습니다._
|
|
2057
|
+
|
|
2058
|
+
---
|
|
2059
|
+
|
|
2060
|
+
## 기술 스택
|
|
2061
|
+
|
|
2062
|
+
_프로젝트 분석 후 자동으로 채워집니다._
|
|
2063
|
+
|
|
2064
|
+
---
|
|
2065
|
+
|
|
2066
|
+
*마지막 업데이트: ${new Date().toISOString().split("T")[0]}*
|
|
1948
2067
|
`;
|
|
1949
2068
|
fs.writeFileSync(contextPath, contextContent);
|
|
1950
2069
|
console.log(chalk_1.default.green("✓ .claude/memory/context.md 생성됨"));
|
|
@@ -1952,36 +2071,36 @@ _프로젝트 분석 후 자동으로 채워집니다._
|
|
|
1952
2071
|
// decisions.md
|
|
1953
2072
|
const decisionsPath = path.join(memoryDir, "decisions.md");
|
|
1954
2073
|
if (!fs.existsSync(decisionsPath)) {
|
|
1955
|
-
const decisionsContent = `# Architecture Decisions
|
|
1956
|
-
|
|
1957
|
-
> 프로젝트 아키텍처 결정 기록 (ADR)
|
|
1958
|
-
> 중요한 기술적 결정을 여기에 기록합니다.
|
|
1959
|
-
|
|
1960
|
-
---
|
|
1961
|
-
|
|
1962
|
-
## 결정 목록
|
|
1963
|
-
|
|
1964
|
-
_아직 기록된 결정이 없습니다._
|
|
1965
|
-
|
|
1966
|
-
---
|
|
1967
|
-
|
|
1968
|
-
## 템플릿
|
|
1969
|
-
|
|
1970
|
-
\`\`\`markdown
|
|
1971
|
-
### ADR-XXX: 결정 제목
|
|
1972
|
-
|
|
1973
|
-
**날짜**: YYYY-MM-DD
|
|
1974
|
-
**상태**: Proposed | Accepted | Deprecated
|
|
1975
|
-
|
|
1976
|
-
#### 배경
|
|
1977
|
-
결정이 필요한 이유
|
|
1978
|
-
|
|
1979
|
-
#### 결정
|
|
1980
|
-
선택한 방안
|
|
1981
|
-
|
|
1982
|
-
#### 근거
|
|
1983
|
-
선택 이유
|
|
1984
|
-
\`\`\`
|
|
2074
|
+
const decisionsContent = `# Architecture Decisions
|
|
2075
|
+
|
|
2076
|
+
> 프로젝트 아키텍처 결정 기록 (ADR)
|
|
2077
|
+
> 중요한 기술적 결정을 여기에 기록합니다.
|
|
2078
|
+
|
|
2079
|
+
---
|
|
2080
|
+
|
|
2081
|
+
## 결정 목록
|
|
2082
|
+
|
|
2083
|
+
_아직 기록된 결정이 없습니다._
|
|
2084
|
+
|
|
2085
|
+
---
|
|
2086
|
+
|
|
2087
|
+
## 템플릿
|
|
2088
|
+
|
|
2089
|
+
\`\`\`markdown
|
|
2090
|
+
### ADR-XXX: 결정 제목
|
|
2091
|
+
|
|
2092
|
+
**날짜**: YYYY-MM-DD
|
|
2093
|
+
**상태**: Proposed | Accepted | Deprecated
|
|
2094
|
+
|
|
2095
|
+
#### 배경
|
|
2096
|
+
결정이 필요한 이유
|
|
2097
|
+
|
|
2098
|
+
#### 결정
|
|
2099
|
+
선택한 방안
|
|
2100
|
+
|
|
2101
|
+
#### 근거
|
|
2102
|
+
선택 이유
|
|
2103
|
+
\`\`\`
|
|
1985
2104
|
`;
|
|
1986
2105
|
fs.writeFileSync(decisionsPath, decisionsContent);
|
|
1987
2106
|
console.log(chalk_1.default.green("✓ .claude/memory/decisions.md 생성됨"));
|
|
@@ -1989,62 +2108,62 @@ _아직 기록된 결정이 없습니다._
|
|
|
1989
2108
|
// projects.md
|
|
1990
2109
|
const projectsPath = path.join(memoryDir, "projects.md");
|
|
1991
2110
|
if (!fs.existsSync(projectsPath)) {
|
|
1992
|
-
const projectsContent = `# 프로젝트 별칭 매핑
|
|
1993
|
-
|
|
1994
|
-
> 외부 프로젝트 배포 및 GitHub Projects 상태 관리
|
|
1995
|
-
> SEMO의 deployer, project-status 스킬이 이 파일을 참조합니다.
|
|
1996
|
-
|
|
1997
|
-
---
|
|
1998
|
-
|
|
1999
|
-
## GitHub Projects 설정
|
|
2000
|
-
|
|
2001
|
-
> **⚠️ 프로젝트 상태 관리 시 이 설정을 참조합니다.**
|
|
2002
|
-
|
|
2003
|
-
### 기본 프로젝트
|
|
2004
|
-
|
|
2005
|
-
| 프로젝트 | 번호 | Project ID | 용도 |
|
|
2006
|
-
|---------|------|------------|------|
|
|
2007
|
-
| 이슈관리 | #1 | \`PVT_xxx\` | 메인 태스크 관리 (기본값) |
|
|
2008
|
-
|
|
2009
|
-
### Status 옵션
|
|
2010
|
-
|
|
2011
|
-
| Status | 설명 |
|
|
2012
|
-
|--------|------|
|
|
2013
|
-
| 백로그 | 초기 상태 |
|
|
2014
|
-
| 작업중 | 개발 진행 중 |
|
|
2015
|
-
| 리뷰요청 | 코드 리뷰 대기 |
|
|
2016
|
-
| 테스트중 | QA 테스트 단계 |
|
|
2017
|
-
| 완료 | 작업 완료 |
|
|
2018
|
-
|
|
2019
|
-
### 🔴 상태값 Alias (한글 ↔ 영문)
|
|
2020
|
-
|
|
2021
|
-
> **SEMO는 아래 키워드를 자동으로 Status 필드값으로 매핑합니다.**
|
|
2022
|
-
|
|
2023
|
-
| 사용자 입력 | → Status 값 | 비고 |
|
|
2024
|
-
|------------|-------------|------|
|
|
2025
|
-
| 리뷰요청, 리뷰 요청, review | 리뷰요청 | 코드 리뷰 대기 |
|
|
2026
|
-
| 테스트중, 테스트 중, testing, qa | 테스트중 | QA 단계 |
|
|
2027
|
-
| 작업중, 작업 중, 진행중, in progress, wip | 작업중 | 개발 중 |
|
|
2028
|
-
| 완료, done, closed | 완료 | 완료 처리 |
|
|
2029
|
-
| 백로그, 대기, pending, backlog | 백로그 | 초기 상태 |
|
|
2030
|
-
|
|
2031
|
-
**예시:**
|
|
2032
|
-
\`\`\`
|
|
2033
|
-
"리뷰요청 이슈들 테스트중으로 바꿔줘"
|
|
2034
|
-
→ Status == "리뷰요청" 인 항목들을 Status = "테스트중" 으로 변경
|
|
2035
|
-
\`\`\`
|
|
2036
|
-
|
|
2037
|
-
---
|
|
2038
|
-
|
|
2039
|
-
## 프로젝트 별칭
|
|
2040
|
-
|
|
2041
|
-
| 별칭 | 레포지토리 | 환경 | 배포 방법 |
|
|
2042
|
-
|------|-----------|------|----------|
|
|
2043
|
-
| 예시 | owner/repo | stg | Milestone close |
|
|
2044
|
-
|
|
2045
|
-
---
|
|
2046
|
-
|
|
2047
|
-
*마지막 업데이트: ${new Date().toISOString().split("T")[0]}*
|
|
2111
|
+
const projectsContent = `# 프로젝트 별칭 매핑
|
|
2112
|
+
|
|
2113
|
+
> 외부 프로젝트 배포 및 GitHub Projects 상태 관리
|
|
2114
|
+
> SEMO의 deployer, project-status 스킬이 이 파일을 참조합니다.
|
|
2115
|
+
|
|
2116
|
+
---
|
|
2117
|
+
|
|
2118
|
+
## GitHub Projects 설정
|
|
2119
|
+
|
|
2120
|
+
> **⚠️ 프로젝트 상태 관리 시 이 설정을 참조합니다.**
|
|
2121
|
+
|
|
2122
|
+
### 기본 프로젝트
|
|
2123
|
+
|
|
2124
|
+
| 프로젝트 | 번호 | Project ID | 용도 |
|
|
2125
|
+
|---------|------|------------|------|
|
|
2126
|
+
| 이슈관리 | #1 | \`PVT_xxx\` | 메인 태스크 관리 (기본값) |
|
|
2127
|
+
|
|
2128
|
+
### Status 옵션
|
|
2129
|
+
|
|
2130
|
+
| Status | 설명 |
|
|
2131
|
+
|--------|------|
|
|
2132
|
+
| 백로그 | 초기 상태 |
|
|
2133
|
+
| 작업중 | 개발 진행 중 |
|
|
2134
|
+
| 리뷰요청 | 코드 리뷰 대기 |
|
|
2135
|
+
| 테스트중 | QA 테스트 단계 |
|
|
2136
|
+
| 완료 | 작업 완료 |
|
|
2137
|
+
|
|
2138
|
+
### 🔴 상태값 Alias (한글 ↔ 영문)
|
|
2139
|
+
|
|
2140
|
+
> **SEMO는 아래 키워드를 자동으로 Status 필드값으로 매핑합니다.**
|
|
2141
|
+
|
|
2142
|
+
| 사용자 입력 | → Status 값 | 비고 |
|
|
2143
|
+
|------------|-------------|------|
|
|
2144
|
+
| 리뷰요청, 리뷰 요청, review | 리뷰요청 | 코드 리뷰 대기 |
|
|
2145
|
+
| 테스트중, 테스트 중, testing, qa | 테스트중 | QA 단계 |
|
|
2146
|
+
| 작업중, 작업 중, 진행중, in progress, wip | 작업중 | 개발 중 |
|
|
2147
|
+
| 완료, done, closed | 완료 | 완료 처리 |
|
|
2148
|
+
| 백로그, 대기, pending, backlog | 백로그 | 초기 상태 |
|
|
2149
|
+
|
|
2150
|
+
**예시:**
|
|
2151
|
+
\`\`\`
|
|
2152
|
+
"리뷰요청 이슈들 테스트중으로 바꿔줘"
|
|
2153
|
+
→ Status == "리뷰요청" 인 항목들을 Status = "테스트중" 으로 변경
|
|
2154
|
+
\`\`\`
|
|
2155
|
+
|
|
2156
|
+
---
|
|
2157
|
+
|
|
2158
|
+
## 프로젝트 별칭
|
|
2159
|
+
|
|
2160
|
+
| 별칭 | 레포지토리 | 환경 | 배포 방법 |
|
|
2161
|
+
|------|-----------|------|----------|
|
|
2162
|
+
| 예시 | owner/repo | stg | Milestone close |
|
|
2163
|
+
|
|
2164
|
+
---
|
|
2165
|
+
|
|
2166
|
+
*마지막 업데이트: ${new Date().toISOString().split("T")[0]}*
|
|
2048
2167
|
`;
|
|
2049
2168
|
fs.writeFileSync(projectsPath, projectsContent);
|
|
2050
2169
|
console.log(chalk_1.default.green("✓ .claude/memory/projects.md 생성됨"));
|
|
@@ -2054,21 +2173,21 @@ _아직 기록된 결정이 없습니다._
|
|
|
2054
2173
|
fs.mkdirSync(rulesDir, { recursive: true });
|
|
2055
2174
|
const rulesPath = path.join(rulesDir, "project-specific.md");
|
|
2056
2175
|
if (!fs.existsSync(rulesPath)) {
|
|
2057
|
-
const rulesContent = `# Project-Specific Rules
|
|
2058
|
-
|
|
2059
|
-
> 이 프로젝트에만 적용되는 규칙
|
|
2060
|
-
|
|
2061
|
-
---
|
|
2062
|
-
|
|
2063
|
-
## 코딩 규칙
|
|
2064
|
-
|
|
2065
|
-
_프로젝트별 코딩 규칙을 여기에 추가하세요._
|
|
2066
|
-
|
|
2067
|
-
---
|
|
2068
|
-
|
|
2069
|
-
## 예외 사항
|
|
2070
|
-
|
|
2071
|
-
_SEMO 기본 규칙의 예외 사항을 여기에 추가하세요._
|
|
2176
|
+
const rulesContent = `# Project-Specific Rules
|
|
2177
|
+
|
|
2178
|
+
> 이 프로젝트에만 적용되는 규칙
|
|
2179
|
+
|
|
2180
|
+
---
|
|
2181
|
+
|
|
2182
|
+
## 코딩 규칙
|
|
2183
|
+
|
|
2184
|
+
_프로젝트별 코딩 규칙을 여기에 추가하세요._
|
|
2185
|
+
|
|
2186
|
+
---
|
|
2187
|
+
|
|
2188
|
+
## 예외 사항
|
|
2189
|
+
|
|
2190
|
+
_SEMO 기본 규칙의 예외 사항을 여기에 추가하세요._
|
|
2072
2191
|
`;
|
|
2073
2192
|
fs.writeFileSync(rulesPath, rulesContent);
|
|
2074
2193
|
console.log(chalk_1.default.green("✓ .claude/memory/rules/project-specific.md 생성됨"));
|
|
@@ -2204,129 +2323,129 @@ async function setupClaudeMd(cwd, extensions, force) {
|
|
|
2204
2323
|
orchestratorPaths.unshift("semo-system/semo-core/agents/orchestrator/orchestrator.md");
|
|
2205
2324
|
// Orchestrator 참조 섹션 생성
|
|
2206
2325
|
const orchestratorRefSection = orchestratorPaths.length > 1
|
|
2207
|
-
? `**Primary Orchestrator**: \`semo-system/${primaryOrchestratorPath}\`
|
|
2208
|
-
|
|
2209
|
-
> Extension 패키지가 설치되어 해당 패키지의 Orchestrator를 우선 참조합니다.
|
|
2210
|
-
|
|
2211
|
-
**모든 Orchestrator 파일** (라우팅 테이블 병합됨):
|
|
2212
|
-
${orchestratorPaths.map(p => `- \`${p}\``).join("\n")}
|
|
2213
|
-
|
|
2326
|
+
? `**Primary Orchestrator**: \`semo-system/${primaryOrchestratorPath}\`
|
|
2327
|
+
|
|
2328
|
+
> Extension 패키지가 설치되어 해당 패키지의 Orchestrator를 우선 참조합니다.
|
|
2329
|
+
|
|
2330
|
+
**모든 Orchestrator 파일** (라우팅 테이블 병합됨):
|
|
2331
|
+
${orchestratorPaths.map(p => `- \`${p}\``).join("\n")}
|
|
2332
|
+
|
|
2214
2333
|
이 파일들에서 라우팅 테이블, 의도 분류, 메시지 포맷을 확인하세요.`
|
|
2215
|
-
: `**반드시 읽어야 할 파일**: \`semo-system/semo-core/agents/orchestrator/orchestrator.md\`
|
|
2216
|
-
|
|
2334
|
+
: `**반드시 읽어야 할 파일**: \`semo-system/semo-core/agents/orchestrator/orchestrator.md\`
|
|
2335
|
+
|
|
2217
2336
|
이 파일에서 라우팅 테이블, 의도 분류, 메시지 포맷을 확인하세요.`;
|
|
2218
|
-
const claudeMdContent = `# SEMO Project Configuration
|
|
2219
|
-
|
|
2220
|
-
> SEMO (Semicolon Orchestrate) - AI Agent Orchestration Framework v${VERSION}
|
|
2221
|
-
|
|
2222
|
-
---
|
|
2223
|
-
|
|
2224
|
-
## 🔴 MANDATORY: Orchestrator-First Execution
|
|
2225
|
-
|
|
2226
|
-
> **⚠️ 이 규칙은 모든 사용자 요청에 적용됩니다. 예외 없음.**
|
|
2227
|
-
|
|
2228
|
-
### 실행 흐름 (필수)
|
|
2229
|
-
|
|
2230
|
-
\`\`\`
|
|
2231
|
-
1. 사용자 요청 수신
|
|
2232
|
-
2. Orchestrator가 의도 분석 후 적절한 Agent/Skill 라우팅
|
|
2233
|
-
3. Agent/Skill이 작업 수행
|
|
2234
|
-
4. 실행 결과 반환
|
|
2235
|
-
\`\`\`
|
|
2236
|
-
|
|
2237
|
-
### Orchestrator 참조
|
|
2238
|
-
|
|
2239
|
-
${orchestratorRefSection}
|
|
2240
|
-
|
|
2241
|
-
---
|
|
2242
|
-
|
|
2243
|
-
## 🔴 NON-NEGOTIABLE RULES
|
|
2244
|
-
|
|
2245
|
-
### 1. Orchestrator-First Policy
|
|
2246
|
-
|
|
2247
|
-
> **모든 요청은 반드시 Orchestrator를 통해 라우팅됩니다. 직접 처리 금지.**
|
|
2248
|
-
|
|
2249
|
-
**직접 처리 금지 항목**:
|
|
2250
|
-
- 코드 작성/수정 → \`implementation-master\` 또는 \`coder\` 스킬
|
|
2251
|
-
- Git 커밋/푸시 → \`git-workflow\` 스킬
|
|
2252
|
-
- 품질 검증 → \`quality-master\` 또는 \`verify\` 스킬
|
|
2253
|
-
- 명세 작성 → \`spec-master\`
|
|
2254
|
-
- 일반 작업 → Orchestrator 분석 후 라우팅
|
|
2255
|
-
|
|
2256
|
-
### 2. Pre-Commit Quality Gate
|
|
2257
|
-
|
|
2258
|
-
> **코드 변경이 포함된 커밋 전 반드시 Quality Gate를 통과해야 합니다.**
|
|
2259
|
-
|
|
2260
|
-
\`\`\`bash
|
|
2261
|
-
# 필수 검증 순서
|
|
2262
|
-
npm run lint # 1. ESLint 검사
|
|
2263
|
-
npx tsc --noEmit # 2. TypeScript 타입 체크
|
|
2264
|
-
npm run build # 3. 빌드 검증 (Next.js/TypeScript 프로젝트)
|
|
2265
|
-
\`\`\`
|
|
2266
|
-
|
|
2267
|
-
**차단 항목**:
|
|
2268
|
-
- \`--no-verify\` 플래그 사용 금지
|
|
2269
|
-
- Quality Gate 우회 시도 거부
|
|
2270
|
-
- "그냥 커밋해줘", "빌드 생략해줘" 등 거부
|
|
2271
|
-
|
|
2272
|
-
---
|
|
2273
|
-
|
|
2274
|
-
## 설치된 구성
|
|
2275
|
-
|
|
2276
|
-
### Standard (필수)
|
|
2277
|
-
- **semo-core**: 원칙, 오케스트레이터, 공통 커맨드
|
|
2278
|
-
- **semo-skills**: 13개 통합 스킬
|
|
2279
|
-
- 행동: coder, tester, planner, deployer, writer
|
|
2280
|
-
- 운영: memory, notify-slack, feedback, version-updater, semo-help, semo-architecture-checker, circuit-breaker, list-bugs
|
|
2281
|
-
|
|
2282
|
-
${extensions.length > 0 ? `### Extensions (선택)
|
|
2283
|
-
${extensions.map(pkg => `- **${pkg}**: ${EXTENSION_PACKAGES[pkg].desc}`).join("\n")}` : ""}
|
|
2284
|
-
|
|
2285
|
-
## 구조
|
|
2286
|
-
|
|
2287
|
-
\`\`\`
|
|
2288
|
-
.claude/
|
|
2289
|
-
├── settings.json # MCP 서버 설정 (Black Box)
|
|
2290
|
-
├── memory/ # Context Mesh (장기 기억)
|
|
2291
|
-
│ ├── context.md # 프로젝트 상태
|
|
2292
|
-
│ ├── decisions.md # 아키텍처 결정
|
|
2293
|
-
│ └── rules/ # 프로젝트별 규칙
|
|
2294
|
-
├── agents → semo-system/semo-core/agents
|
|
2295
|
-
├── skills → semo-system/semo-skills
|
|
2296
|
-
└── commands/SEMO → semo-system/semo-core/commands/SEMO
|
|
2297
|
-
|
|
2298
|
-
semo-system/ # White Box (읽기 전용)
|
|
2299
|
-
├── semo-core/ # Layer 0: 원칙, 오케스트레이션
|
|
2300
|
-
├── semo-skills/ # Layer 1: 통합 스킬
|
|
2301
|
-
${extensionsList}
|
|
2302
|
-
\`\`\`
|
|
2303
|
-
|
|
2304
|
-
## 사용 가능한 커맨드
|
|
2305
|
-
|
|
2306
|
-
| 커맨드 | 설명 |
|
|
2307
|
-
|--------|------|
|
|
2308
|
-
| \`/SEMO:help\` | 도움말 |
|
|
2309
|
-
| \`/SEMO:feedback\` | 피드백 제출 |
|
|
2310
|
-
| \`/SEMO:update\` | SEMO 업데이트 |
|
|
2311
|
-
| \`/SEMO:onboarding\` | 온보딩 가이드 |
|
|
2312
|
-
| \`/SEMO:dry-run {프롬프트}\` | 명령 검증 (라우팅 시뮬레이션) |
|
|
2313
|
-
|
|
2314
|
-
## Context Mesh 사용
|
|
2315
|
-
|
|
2316
|
-
SEMO는 \`.claude/memory/\`를 통해 세션 간 컨텍스트를 유지합니다:
|
|
2317
|
-
|
|
2318
|
-
- **context.md**: 프로젝트 상태, 진행 중인 작업
|
|
2319
|
-
- **decisions.md**: 아키텍처 결정 기록 (ADR)
|
|
2320
|
-
- **rules/**: 프로젝트별 커스텀 규칙
|
|
2321
|
-
|
|
2322
|
-
memory 스킬이 자동으로 이 파일들을 관리합니다.
|
|
2323
|
-
|
|
2324
|
-
## References
|
|
2325
|
-
|
|
2326
|
-
- [SEMO Principles](semo-system/semo-core/principles/PRINCIPLES.md)
|
|
2327
|
-
- [SEMO Skills](semo-system/semo-skills/)
|
|
2328
|
-
${extensions.length > 0 ? extensions.map(pkg => `- [${EXTENSION_PACKAGES[pkg].name} Package](semo-system/${pkg}/)`).join("\n") : ""}
|
|
2329
|
-
${packageClaudeMdSections}
|
|
2337
|
+
const claudeMdContent = `# SEMO Project Configuration
|
|
2338
|
+
|
|
2339
|
+
> SEMO (Semicolon Orchestrate) - AI Agent Orchestration Framework v${VERSION}
|
|
2340
|
+
|
|
2341
|
+
---
|
|
2342
|
+
|
|
2343
|
+
## 🔴 MANDATORY: Orchestrator-First Execution
|
|
2344
|
+
|
|
2345
|
+
> **⚠️ 이 규칙은 모든 사용자 요청에 적용됩니다. 예외 없음.**
|
|
2346
|
+
|
|
2347
|
+
### 실행 흐름 (필수)
|
|
2348
|
+
|
|
2349
|
+
\`\`\`
|
|
2350
|
+
1. 사용자 요청 수신
|
|
2351
|
+
2. Orchestrator가 의도 분석 후 적절한 Agent/Skill 라우팅
|
|
2352
|
+
3. Agent/Skill이 작업 수행
|
|
2353
|
+
4. 실행 결과 반환
|
|
2354
|
+
\`\`\`
|
|
2355
|
+
|
|
2356
|
+
### Orchestrator 참조
|
|
2357
|
+
|
|
2358
|
+
${orchestratorRefSection}
|
|
2359
|
+
|
|
2360
|
+
---
|
|
2361
|
+
|
|
2362
|
+
## 🔴 NON-NEGOTIABLE RULES
|
|
2363
|
+
|
|
2364
|
+
### 1. Orchestrator-First Policy
|
|
2365
|
+
|
|
2366
|
+
> **모든 요청은 반드시 Orchestrator를 통해 라우팅됩니다. 직접 처리 금지.**
|
|
2367
|
+
|
|
2368
|
+
**직접 처리 금지 항목**:
|
|
2369
|
+
- 코드 작성/수정 → \`implementation-master\` 또는 \`coder\` 스킬
|
|
2370
|
+
- Git 커밋/푸시 → \`git-workflow\` 스킬
|
|
2371
|
+
- 품질 검증 → \`quality-master\` 또는 \`verify\` 스킬
|
|
2372
|
+
- 명세 작성 → \`spec-master\`
|
|
2373
|
+
- 일반 작업 → Orchestrator 분석 후 라우팅
|
|
2374
|
+
|
|
2375
|
+
### 2. Pre-Commit Quality Gate
|
|
2376
|
+
|
|
2377
|
+
> **코드 변경이 포함된 커밋 전 반드시 Quality Gate를 통과해야 합니다.**
|
|
2378
|
+
|
|
2379
|
+
\`\`\`bash
|
|
2380
|
+
# 필수 검증 순서
|
|
2381
|
+
npm run lint # 1. ESLint 검사
|
|
2382
|
+
npx tsc --noEmit # 2. TypeScript 타입 체크
|
|
2383
|
+
npm run build # 3. 빌드 검증 (Next.js/TypeScript 프로젝트)
|
|
2384
|
+
\`\`\`
|
|
2385
|
+
|
|
2386
|
+
**차단 항목**:
|
|
2387
|
+
- \`--no-verify\` 플래그 사용 금지
|
|
2388
|
+
- Quality Gate 우회 시도 거부
|
|
2389
|
+
- "그냥 커밋해줘", "빌드 생략해줘" 등 거부
|
|
2390
|
+
|
|
2391
|
+
---
|
|
2392
|
+
|
|
2393
|
+
## 설치된 구성
|
|
2394
|
+
|
|
2395
|
+
### Standard (필수)
|
|
2396
|
+
- **semo-core**: 원칙, 오케스트레이터, 공통 커맨드
|
|
2397
|
+
- **semo-skills**: 13개 통합 스킬
|
|
2398
|
+
- 행동: coder, tester, planner, deployer, writer
|
|
2399
|
+
- 운영: memory, notify-slack, feedback, version-updater, semo-help, semo-architecture-checker, circuit-breaker, list-bugs
|
|
2400
|
+
|
|
2401
|
+
${extensions.length > 0 ? `### Extensions (선택)
|
|
2402
|
+
${extensions.map(pkg => `- **${pkg}**: ${EXTENSION_PACKAGES[pkg].desc}`).join("\n")}` : ""}
|
|
2403
|
+
|
|
2404
|
+
## 구조
|
|
2405
|
+
|
|
2406
|
+
\`\`\`
|
|
2407
|
+
.claude/
|
|
2408
|
+
├── settings.json # MCP 서버 설정 (Black Box)
|
|
2409
|
+
├── memory/ # Context Mesh (장기 기억)
|
|
2410
|
+
│ ├── context.md # 프로젝트 상태
|
|
2411
|
+
│ ├── decisions.md # 아키텍처 결정
|
|
2412
|
+
│ └── rules/ # 프로젝트별 규칙
|
|
2413
|
+
├── agents → semo-system/semo-core/agents
|
|
2414
|
+
├── skills → semo-system/semo-skills
|
|
2415
|
+
└── commands/SEMO → semo-system/semo-core/commands/SEMO
|
|
2416
|
+
|
|
2417
|
+
semo-system/ # White Box (읽기 전용)
|
|
2418
|
+
├── semo-core/ # Layer 0: 원칙, 오케스트레이션
|
|
2419
|
+
├── semo-skills/ # Layer 1: 통합 스킬
|
|
2420
|
+
${extensionsList}
|
|
2421
|
+
\`\`\`
|
|
2422
|
+
|
|
2423
|
+
## 사용 가능한 커맨드
|
|
2424
|
+
|
|
2425
|
+
| 커맨드 | 설명 |
|
|
2426
|
+
|--------|------|
|
|
2427
|
+
| \`/SEMO:help\` | 도움말 |
|
|
2428
|
+
| \`/SEMO:feedback\` | 피드백 제출 |
|
|
2429
|
+
| \`/SEMO:update\` | SEMO 업데이트 |
|
|
2430
|
+
| \`/SEMO:onboarding\` | 온보딩 가이드 |
|
|
2431
|
+
| \`/SEMO:dry-run {프롬프트}\` | 명령 검증 (라우팅 시뮬레이션) |
|
|
2432
|
+
|
|
2433
|
+
## Context Mesh 사용
|
|
2434
|
+
|
|
2435
|
+
SEMO는 \`.claude/memory/\`를 통해 세션 간 컨텍스트를 유지합니다:
|
|
2436
|
+
|
|
2437
|
+
- **context.md**: 프로젝트 상태, 진행 중인 작업
|
|
2438
|
+
- **decisions.md**: 아키텍처 결정 기록 (ADR)
|
|
2439
|
+
- **rules/**: 프로젝트별 커스텀 규칙
|
|
2440
|
+
|
|
2441
|
+
memory 스킬이 자동으로 이 파일들을 관리합니다.
|
|
2442
|
+
|
|
2443
|
+
## References
|
|
2444
|
+
|
|
2445
|
+
- [SEMO Principles](semo-system/semo-core/principles/PRINCIPLES.md)
|
|
2446
|
+
- [SEMO Skills](semo-system/semo-skills/)
|
|
2447
|
+
${extensions.length > 0 ? extensions.map(pkg => `- [${EXTENSION_PACKAGES[pkg].name} Package](semo-system/${pkg}/)`).join("\n") : ""}
|
|
2448
|
+
${packageClaudeMdSections}
|
|
2330
2449
|
`;
|
|
2331
2450
|
fs.writeFileSync(claudeMdPath, claudeMdContent);
|
|
2332
2451
|
console.log(chalk_1.default.green("✓ .claude/CLAUDE.md 생성됨"));
|
|
@@ -2337,7 +2456,7 @@ ${packageClaudeMdSections}
|
|
|
2337
2456
|
// === add 명령어 ===
|
|
2338
2457
|
program
|
|
2339
2458
|
.command("add <packages>")
|
|
2340
|
-
.description("Extension 패키지를 추가로 설치합니다 (그룹: biz, eng, ops / 개별: biz/discovery, eng/nextjs)")
|
|
2459
|
+
.description("Extension 패키지를 추가로 설치합니다 (그룹: biz, eng, ops, system / 개별: biz/discovery, eng/nextjs, semo-hooks)")
|
|
2341
2460
|
.option("-f, --force", "기존 설정 덮어쓰기")
|
|
2342
2461
|
.action(async (packagesInput, options) => {
|
|
2343
2462
|
const cwd = process.cwd();
|
|
@@ -2444,6 +2563,7 @@ program
|
|
|
2444
2563
|
eng: { title: "Engineering Layer", emoji: "⚙️" },
|
|
2445
2564
|
ops: { title: "Operations Layer", emoji: "📊" },
|
|
2446
2565
|
meta: { title: "Meta", emoji: "🔧" },
|
|
2566
|
+
system: { title: "System", emoji: "🔩" },
|
|
2447
2567
|
};
|
|
2448
2568
|
for (const [layerKey, layerInfo] of Object.entries(layers)) {
|
|
2449
2569
|
const layerPackages = Object.entries(EXTENSION_PACKAGES).filter(([, pkg]) => pkg.layer === layerKey);
|
|
@@ -2465,6 +2585,7 @@ program
|
|
|
2465
2585
|
console.log(chalk_1.default.gray(" semo add biz → Business 전체 (discovery, design, management, poc)"));
|
|
2466
2586
|
console.log(chalk_1.default.gray(" semo add eng → Engineering 전체 (nextjs, spring, ms, infra)"));
|
|
2467
2587
|
console.log(chalk_1.default.gray(" semo add ops → Operations 전체 (qa, monitor, improve)"));
|
|
2588
|
+
console.log(chalk_1.default.gray(" semo add system → System 전체 (hooks, remote)"));
|
|
2468
2589
|
console.log();
|
|
2469
2590
|
// 단축명 안내
|
|
2470
2591
|
console.log(chalk_1.default.gray("─".repeat(50)));
|
|
@@ -2731,7 +2852,9 @@ program
|
|
|
2731
2852
|
}
|
|
2732
2853
|
}
|
|
2733
2854
|
}
|
|
2734
|
-
// ===
|
|
2855
|
+
// === 6. Hooks 업데이트 ===
|
|
2856
|
+
await setupHooks(cwd, true);
|
|
2857
|
+
// === 7. 설치 검증 ===
|
|
2735
2858
|
const verificationResult = verifyInstallation(cwd, installedExtensions);
|
|
2736
2859
|
printVerificationResult(verificationResult);
|
|
2737
2860
|
if (verificationResult.success) {
|