docuking-mcp 2.7.0 → 2.8.1

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.
@@ -12,8 +12,8 @@ import {
12
12
  getAiBasePath,
13
13
  } from '../lib/config.js';
14
14
 
15
- // 킹캐스트 대상 폴더
16
- const KINGCAST_FOLDERS = ['_Infra_Config', '_Policy'];
15
+ // 킹캐스트 대상 폴더 (xx_ 접두사로 루트 레벨에 위치)
16
+ const KINGCAST_FOLDERS = ['xx_Infra_Config', 'xx_Policy'];
17
17
 
18
18
  // 킹캐스트 해시 저장 파일
19
19
  const KINGCAST_HASH_FILE = '.docuking/kingcast_hashes.json';
@@ -32,14 +32,13 @@ function calculateFileHash(filePath) {
32
32
 
33
33
  /**
34
34
  * 킹캐스트 대상 파일 수집
35
- * yy_All_Docu/_Infra_Config/, yy_All_Docu/_Policy/ 내의 모든 파일
35
+ * xx_Infra_Config/, xx_Policy/ (루트 레벨) 내의 모든 파일
36
36
  */
37
37
  function collectKingcastFiles(localPath) {
38
- const allDocuPath = path.join(localPath, 'yy_All_Docu');
39
38
  const files = {};
40
39
 
41
40
  for (const folder of KINGCAST_FOLDERS) {
42
- const folderPath = path.join(allDocuPath, folder);
41
+ const folderPath = path.join(localPath, folder);
43
42
  if (!fs.existsSync(folderPath)) continue;
44
43
 
45
44
  const collectRecursive = (dir, relativePath = '') => {
@@ -171,25 +170,25 @@ function updateLocalRules(localPath, currentFiles, changes, config) {
171
170
  const coworkerFolder = config?.coworkerFolder || '';
172
171
  const projectName = config?.projectName || 'Unknown Project';
173
172
 
174
- // _Policy 파일들 분류 (번호순 정렬)
173
+ // xx_Policy 파일들 분류 (번호순 정렬)
175
174
  const policyFiles = Object.entries(currentFiles)
176
- .filter(([key]) => key.startsWith('_Policy/'))
175
+ .filter(([key]) => key.startsWith('xx_Policy/'))
177
176
  .map(([key, file]) => ({ key, ...file }))
178
177
  .sort((a, b) => a.key.localeCompare(b.key));
179
178
 
180
- // _Infra_Config 파일들 분류
179
+ // xx_Infra_Config 파일들 분류
181
180
  const infraConfigFiles = Object.entries(currentFiles)
182
- .filter(([key]) => key.startsWith('_Infra_Config/'))
181
+ .filter(([key]) => key.startsWith('xx_Infra_Config/'))
183
182
  .map(([key, file]) => ({ key, ...file }));
184
183
 
185
184
  const createdFiles = [];
186
185
 
187
186
  // ========================================
188
- // 1. _Policy 파일들을 서브파일 구조로 복사
187
+ // 1. xx_Policy 파일들을 서브파일 구조로 복사
189
188
  // ========================================
190
189
  for (const file of policyFiles) {
191
- // _Policy/00_project_overview.md → 00_project_overview.md
192
- const relativePath = file.key.replace('_Policy/', '');
190
+ // xx_Policy/00_project_overview.md → 00_project_overview.md
191
+ const relativePath = file.key.replace('xx_Policy/', '');
193
192
  const targetPath = path.join(localRulesPath, relativePath);
194
193
 
195
194
  // 디렉토리 생성
@@ -206,6 +205,12 @@ function updateLocalRules(localPath, currentFiles, changes, config) {
206
205
  }
207
206
  }
208
207
 
208
+ // ========================================
209
+ // 1.5. xx_Infra_Config는 복사하지 않음
210
+ // 이미 Pull 후 xx_Infra_Config/에 존재함
211
+ // AI가 변경 감지 시 직접 읽고 로컬 환경에 맞게 적용
212
+ // ========================================
213
+
209
214
  // ========================================
210
215
  // 2. 협업자용 설정 파일 생성 (_coworker_config.md)
211
216
  // ========================================
@@ -271,13 +276,13 @@ git checkout -b coworker/${coworkerFolder}
271
276
  ## 환경 정보 (읽기 전용 참고)
272
277
  `;
273
278
 
274
- // _Infra_Config에서 민감하지 않은 정보 추가
279
+ // xx_Infra_Config에서 민감하지 않은 정보 추가
275
280
  let infraInfo = '';
276
281
  for (const file of infraConfigFiles) {
277
282
  const fileName = path.basename(file.key);
278
283
  // 배포 관련 정보만 참조 (민감 정보 제외)
279
284
  if (fileName.includes('deploy') || fileName.includes('README')) {
280
- infraInfo += `\n참고 문서: yy_All_Docu/${file.key}`;
285
+ infraInfo += `\n참고 문서: ${file.key}`;
281
286
  }
282
287
  }
283
288
 
@@ -316,11 +321,22 @@ git checkout -b coworker/${coworkerFolder}
316
321
  indexContent += '\n(정책 문서가 없습니다)\n';
317
322
  } else {
318
323
  for (const file of policyFiles) {
319
- const relativePath = file.key.replace('_Policy/', '');
324
+ const relativePath = file.key.replace('xx_Policy/', '');
320
325
  indexContent += `- [${relativePath}](./${relativePath})\n`;
321
326
  }
322
327
  }
323
328
 
329
+ // 인프라 설정 파일 안내 (복사하지 않으므로 원본 경로 표시)
330
+ if (infraConfigFiles.length > 0) {
331
+ indexContent += '\n## 인프라 설정 (xx_Infra_Config/)\n';
332
+ indexContent += '> 아래 파일들은 복사되지 않습니다. 원본 경로에서 직접 읽으세요.\n';
333
+ indexContent += '> 변경 감지 시 AI가 내용을 읽고 로컬 환경에 맞게 적용해야 합니다.\n\n';
334
+ for (const file of infraConfigFiles) {
335
+ const relativePath = file.key.replace('xx_Infra_Config/', '');
336
+ indexContent += `- xx_Infra_Config/${relativePath}\n`;
337
+ }
338
+ }
339
+
324
340
  if (isCoworker) {
325
341
  indexContent += `\n## 협업자 설정\n- [_coworker_config.md](./_coworker_config.md)\n`;
326
342
  }
@@ -329,12 +345,13 @@ git checkout -b coworker/${coworkerFolder}
329
345
  createdFiles.push('00_index.md');
330
346
 
331
347
  // ========================================
332
- // 4. 삭제된 정책에 해당하는 로컬 파일 삭제
348
+ // 4. 삭제된 정책/인프라에 해당하는 로컬 파일 삭제
333
349
  // ========================================
334
350
  if (changes.deleted.length > 0) {
335
351
  for (const deletedKey of changes.deleted) {
336
- if (deletedKey.startsWith('_Policy/')) {
337
- const relativePath = deletedKey.replace('_Policy/', '');
352
+ // xx_Policy 삭제
353
+ if (deletedKey.startsWith('xx_Policy/')) {
354
+ const relativePath = deletedKey.replace('xx_Policy/', '');
338
355
  const targetPath = path.join(localRulesPath, relativePath);
339
356
  if (fs.existsSync(targetPath)) {
340
357
  try {
@@ -345,6 +362,8 @@ git checkout -b coworker/${coworkerFolder}
345
362
  }
346
363
  }
347
364
  }
365
+ // xx_Infra_Config는 복사하지 않으므로 삭제 처리 불필요
366
+ // Pull 시 자동으로 원본 폴더에서 제거됨
348
367
  }
349
368
  }
350
369
 
@@ -454,8 +473,23 @@ export async function executeKingcast(localPath) {
454
473
  message += `\n 📄 정책 파일 ${result.policyCount}개 → .claude/rules/local/`;
455
474
  }
456
475
 
476
+ // xx_Infra_Config 변경 감지 시 안내
477
+ const infraChanges = [
478
+ ...changes.added.filter(k => k.startsWith('xx_Infra_Config/')),
479
+ ...changes.modified.filter(k => k.startsWith('xx_Infra_Config/')),
480
+ ];
481
+ if (infraChanges.length > 0) {
482
+ message += `\n\n🔧 인프라 설정 변경 감지 (${infraChanges.length}개):`;
483
+ for (const file of infraChanges) {
484
+ message += `\n - ${file}`;
485
+ }
486
+ message += `\n\n 👉 AI는 위 파일들을 읽고 로컬 환경에 맞게 적용하세요.`;
487
+ message += `\n 👉 예: .env 변수 추가/변경, 배포 설정 확인 등`;
488
+ }
489
+
457
490
  // 정책 변경 시 경고 메시지 추가
458
- if (changes.modified.length > 0) {
491
+ const policyModified = changes.modified.filter(k => k.startsWith('xx_Policy/'));
492
+ if (policyModified.length > 0) {
459
493
  message += `\n\n⚠️ 중요: 정책이 변경되었습니다!`;
460
494
  message += `\n 기존 코드가 새 정책과 맞지 않을 수 있습니다.`;
461
495
  message += `\n 변경된 정책 파일을 읽고, 기존 코드에도 새 정책을 적용하세요.`;
@@ -511,9 +545,9 @@ export async function handleKingcastStatus(args) {
511
545
  ## 킹캐스트 대상 파일
512
546
  `;
513
547
 
514
- // _Infra_Config 파일
515
- statusText += '\n### _Infra_Config/\n';
516
- const infraConfigFiles = Object.keys(currentFiles).filter(k => k.startsWith('_Infra_Config/'));
548
+ // xx_Infra_Config 파일
549
+ statusText += '\n### xx_Infra_Config/\n';
550
+ const infraConfigFiles = Object.keys(currentFiles).filter(k => k.startsWith('xx_Infra_Config/'));
517
551
  if (infraConfigFiles.length === 0) {
518
552
  statusText += '(없음)\n';
519
553
  } else {
@@ -522,9 +556,9 @@ export async function handleKingcastStatus(args) {
522
556
  }
523
557
  }
524
558
 
525
- // _Policy 파일
526
- statusText += '\n### _Policy/\n';
527
- const policyFiles = Object.keys(currentFiles).filter(k => k.startsWith('_Policy/'));
559
+ // xx_Policy 파일
560
+ statusText += '\n### xx_Policy/\n';
561
+ const policyFiles = Object.keys(currentFiles).filter(k => k.startsWith('xx_Policy/'));
528
562
  if (policyFiles.length === 0) {
529
563
  statusText += '(없음)\n';
530
564
  } else {
package/handlers/sync.js CHANGED
@@ -88,6 +88,9 @@ docuking_init 호출 시 apiKey 파라미터를 포함해주세요.`,
88
88
  // zz_ai_* 폴더 목록
89
89
  const aiFolders = ['zz_ai_1_Talk', 'zz_ai_2_Todo', 'zz_ai_3_Plan'];
90
90
 
91
+ // xx_ 시스템 폴더 목록 (오너 전용)
92
+ const systemFolders = ['xx_Infra_Config', 'xx_Policy'];
93
+
91
94
  if (isCoworker) {
92
95
  // 협업자: yy_Coworker_{폴더명}/ 폴더를 yy_All_Docu/ 밖에 별도 생성
93
96
  coworkerFolderName = `yy_Coworker_${coworkerFolder}`;
@@ -108,15 +111,14 @@ docuking_init 호출 시 apiKey 파라미터를 포함해주세요.`,
108
111
  }
109
112
  }
110
113
  } else {
111
- // 오너: yy_All_Docu/ 안에 _Infra_Config/, _Policy/, _Private/ 생성
112
- const infraConfigPath = path.join(mainFolderPath, '_Infra_Config');
113
- if (!fs.existsSync(infraConfigPath)) {
114
- fs.mkdirSync(infraConfigPath, { recursive: true });
115
- }
116
- const policyPath = path.join(mainFolderPath, '_Policy');
117
- if (!fs.existsSync(policyPath)) {
118
- fs.mkdirSync(policyPath, { recursive: true });
114
+ // 오너: xx_ 시스템 폴더 (루트에 생성)
115
+ for (const folder of systemFolders) {
116
+ const folderPath = path.join(localPath, folder);
117
+ if (!fs.existsSync(folderPath)) {
118
+ fs.mkdirSync(folderPath, { recursive: true });
119
+ }
119
120
  }
121
+ // 오너: yy_All_Docu/ 안에 _Private/ 생성
120
122
  const ownerPrivatePath = path.join(mainFolderPath, '_Private');
121
123
  if (!fs.existsSync(ownerPrivatePath)) {
122
124
  fs.mkdirSync(ownerPrivatePath, { recursive: true });
@@ -296,27 +298,27 @@ docuking_init을 먼저 실행하세요.`,
296
298
  };
297
299
  }
298
300
 
299
- // 오너 Push 대상: yy_All_Docu/ + zz_ai_*/ 폴더들
301
+ // 오너 Push 대상: xx_*/ + yy_All_Docu/ + zz_ai_*/ 폴더들
300
302
  pushTargetFolders.push({ localPath: mainFolderPath, serverPrefix: 'yy_All_Docu' });
301
303
 
302
- // zz_ai_* 폴더들 찾기
304
+ // xx_*, zz_ai_* 폴더들 찾기
303
305
  const rootEntries = fs.readdirSync(localPath, { withFileTypes: true });
304
306
  for (const entry of rootEntries) {
305
- if (entry.isDirectory() && entry.name.startsWith('zz_ai_')) {
306
- const zzPath = path.join(localPath, entry.name);
307
- pushTargetFolders.push({ localPath: zzPath, serverPrefix: entry.name });
307
+ if (entry.isDirectory() && (entry.name.startsWith('xx_') || entry.name.startsWith('zz_ai_'))) {
308
+ const folderPath = path.join(localPath, entry.name);
309
+ pushTargetFolders.push({ localPath: folderPath, serverPrefix: entry.name });
308
310
  }
309
311
  }
310
312
  }
311
313
 
312
- // .env 파일 자동 백업: _Infra_Config/ 폴더에 복사
313
- // 오너만 가능 (협업자는 _Infra_Config/ 에 접근 불가)
314
+ // .env 파일 자동 백업: xx_Infra_Config/ 폴더에 복사
315
+ // 오너만 가능 (협업자는 xx_Infra_Config/ 에 접근 불가)
314
316
  if (!isCoworker) {
315
317
  const envFilePath = path.join(localPath, '.env');
316
- const infraConfigPath = path.join(mainFolderPath, '_Infra_Config');
318
+ const infraConfigPath = path.join(localPath, 'xx_Infra_Config');
317
319
 
318
320
  if (fs.existsSync(envFilePath)) {
319
- // _Infra_Config 폴더 생성
321
+ // xx_Infra_Config 폴더 생성
320
322
  if (!fs.existsSync(infraConfigPath)) {
321
323
  fs.mkdirSync(infraConfigPath, { recursive: true });
322
324
  }
@@ -325,7 +327,7 @@ docuking_init을 먼저 실행하세요.`,
325
327
  const envBackupPath = path.join(infraConfigPath, '.env');
326
328
  try {
327
329
  fs.copyFileSync(envFilePath, envBackupPath);
328
- console.error(`[DocuKing] .env → _Infra_Config/.env 자동 백업 완료`);
330
+ console.error(`[DocuKing] .env → xx_Infra_Config/.env 자동 백업 완료`);
329
331
  } catch (err) {
330
332
  console.error(`[DocuKing] .env 백업 실패: ${err.message}`);
331
333
  }
@@ -341,7 +343,7 @@ docuking_init을 먼저 실행하세요.`,
341
343
  const backendEnvBackupPath = path.join(infraConfigPath, 'backend.env');
342
344
  try {
343
345
  fs.copyFileSync(backendEnvPath, backendEnvBackupPath);
344
- console.error(`[DocuKing] backend/.env → _Infra_Config/backend.env 자동 백업 완료`);
346
+ console.error(`[DocuKing] backend/.env → xx_Infra_Config/backend.env 자동 백업 완료`);
345
347
  } catch (err) {
346
348
  console.error(`[DocuKing] backend/.env 백업 실패: ${err.message}`);
347
349
  }
@@ -357,7 +359,7 @@ docuking_init을 먼저 실행하세요.`,
357
359
  const frontendEnvBackupPath = path.join(infraConfigPath, 'frontend.env.local');
358
360
  try {
359
361
  fs.copyFileSync(frontendEnvPath, frontendEnvBackupPath);
360
- console.error(`[DocuKing] frontend/.env.local → _Infra_Config/frontend.env.local 자동 백업 완료`);
362
+ console.error(`[DocuKing] frontend/.env.local → xx_Infra_Config/frontend.env.local 자동 백업 완료`);
361
363
  } catch (err) {
362
364
  console.error(`[DocuKing] frontend/.env.local 백업 실패: ${err.message}`);
363
365
  }
@@ -373,7 +375,7 @@ docuking_init을 먼저 실행하세요.`,
373
375
  const packageJsonBackupPath = path.join(infraConfigPath, 'package.json');
374
376
  try {
375
377
  fs.copyFileSync(packageJsonPath, packageJsonBackupPath);
376
- console.error(`[DocuKing] package.json → _Infra_Config/package.json 자동 백업 완료`);
378
+ console.error(`[DocuKing] package.json → xx_Infra_Config/package.json 자동 백업 완료`);
377
379
  } catch (err) {
378
380
  console.error(`[DocuKing] package.json 백업 실패: ${err.message}`);
379
381
  }
@@ -389,7 +391,7 @@ docuking_init을 먼저 실행하세요.`,
389
391
  const backendPackageJsonBackupPath = path.join(infraConfigPath, 'backend.package.json');
390
392
  try {
391
393
  fs.copyFileSync(backendPackageJsonPath, backendPackageJsonBackupPath);
392
- console.error(`[DocuKing] backend/package.json → _Infra_Config/backend.package.json 자동 백업 완료`);
394
+ console.error(`[DocuKing] backend/package.json → xx_Infra_Config/backend.package.json 자동 백업 완료`);
393
395
  } catch (err) {
394
396
  console.error(`[DocuKing] backend/package.json 백업 실패: ${err.message}`);
395
397
  }
@@ -405,7 +407,7 @@ docuking_init을 먼저 실행하세요.`,
405
407
  const frontendPackageJsonBackupPath = path.join(infraConfigPath, 'frontend.package.json');
406
408
  try {
407
409
  fs.copyFileSync(frontendPackageJsonPath, frontendPackageJsonBackupPath);
408
- console.error(`[DocuKing] frontend/package.json → _Infra_Config/frontend.package.json 자동 백업 완료`);
410
+ console.error(`[DocuKing] frontend/package.json → xx_Infra_Config/frontend.package.json 자동 백업 완료`);
409
411
  } catch (err) {
410
412
  console.error(`[DocuKing] frontend/package.json 백업 실패: ${err.message}`);
411
413
  }
@@ -1026,11 +1028,14 @@ export async function handlePullInternal(args) {
1026
1028
 
1027
1029
  // 서버 경로에 따라 로컬 저장 위치 결정
1028
1030
  // 프로젝트 루트 기준 절대경로 그대로 사용
1031
+ // - xx_Infra_Config/xxx → xx_Infra_Config/xxx (시스템/인프라)
1032
+ // - xx_Policy/xxx → xx_Policy/xxx (정책)
1029
1033
  // - yy_All_Docu/xxx → yy_All_Docu/xxx (오너 문서)
1030
1034
  // - yy_Coworker_xxx/yyy → yy_Coworker_xxx/yyy (협업자 폴더)
1031
1035
  // - zz_ai_xxx/yyy → zz_ai_xxx/yyy (AI 폴더)
1032
1036
  let fullPath;
1033
- if (file.path.startsWith('yy_All_Docu/') ||
1037
+ if (file.path.startsWith('xx_') ||
1038
+ file.path.startsWith('yy_All_Docu/') ||
1034
1039
  file.path.startsWith('yy_Coworker_') ||
1035
1040
  file.path.startsWith('zz_ai_')) {
1036
1041
  // 서버 경로 그대로 로컬에 저장
@@ -1168,7 +1173,8 @@ export async function handlePullInternal(args) {
1168
1173
  try {
1169
1174
  // 서버 경로에 따라 로컬 경로 결정
1170
1175
  let fullPath;
1171
- if (deletedFile.path.startsWith('yy_All_Docu/') ||
1176
+ if (deletedFile.path.startsWith('xx_') ||
1177
+ deletedFile.path.startsWith('yy_All_Docu/') ||
1172
1178
  deletedFile.path.startsWith('yy_Coworker_') ||
1173
1179
  deletedFile.path.startsWith('zz_ai_')) {
1174
1180
  fullPath = path.join(localPath, deletedFile.path);
@@ -1460,16 +1466,16 @@ export async function handleStatus(args) {
1460
1466
  }
1461
1467
  pushableFiles = localFiles; // 협업자는 자기 폴더의 모든 파일 Push 가능
1462
1468
  } else {
1463
- // 오너: yy_All_Docu/ + zz_ai_*/ 폴더에서 파일 수집
1469
+ // 오너: xx_*/ + yy_All_Docu/ + zz_ai_*/ 폴더에서 파일 수집
1464
1470
  if (fs.existsSync(mainFolderPath)) {
1465
1471
  collectFilesSimple(mainFolderPath, '', localFiles);
1466
1472
  }
1467
- // zz_ai_* 폴더들도 수집
1473
+ // xx_*, zz_ai_* 폴더들도 수집
1468
1474
  const rootEntries = fs.readdirSync(localPath, { withFileTypes: true });
1469
1475
  for (const entry of rootEntries) {
1470
- if (entry.isDirectory() && entry.name.startsWith('zz_ai_')) {
1471
- const zzPath = path.join(localPath, entry.name);
1472
- collectFilesSimple(zzPath, '', localFiles);
1476
+ if (entry.isDirectory() && (entry.name.startsWith('xx_') || entry.name.startsWith('zz_ai_'))) {
1477
+ const folderPath = path.join(localPath, entry.name);
1478
+ collectFilesSimple(folderPath, '', localFiles);
1473
1479
  }
1474
1480
  }
1475
1481
  pushableFiles = localFiles; // 오너는 모든 파일 Push 가능
package/index.js CHANGED
@@ -6,8 +6,9 @@
6
6
  * AI 시대의 문서 협업 플랫폼 - AI가 문서를 Push/Pull 할 수 있게 해주는 MCP 서버
7
7
  *
8
8
  * 폴더 구조:
9
+ * - xx_Infra_Config/ : 시스템 설정 (.env 백업, 배포 정보 등) - Push 대상
10
+ * - xx_Policy/ : 정책 문서 (AI 행동 지침) - Push 대상, 킹캐스트 대상
9
11
  * - yy_All_Docu/ : 문서 동기화 폴더 (Push/Pull 대상)
10
- * - yy_All_Docu/_Infra_Config/: 민감 정보 백업 (.env 자동 복사, 팀 공유)
11
12
  * - yy_All_Docu/_Private/ : 오너 비공개 폴더 (오너만 접근)
12
13
  * - yy_Coworker_{폴더명}/ : 협업자 폴더 (yy_All_Docu와 별도, 동기화 대상)
13
14
  * - zz_ai_1_Talk/ : AI 대화록 (킹톡, Push 대상)
@@ -15,6 +16,7 @@
15
16
  * - zz_ai_3_Plan/ : AI 플랜 (킹플랜, Push 대상)
16
17
  *
17
18
  * 접두사 규칙:
19
+ * - xx_ : 시스템용 폴더 (인프라, 정책) - Push 대상
18
20
  * - yy_ : 사람용 폴더 (문서, 협업자) - Push 대상
19
21
  * - zz_ai_ : AI용 폴더 (Talk, Todo, Plan) - Push 대상
20
22
  * - _ : 비공개 폴더 (본인만 접근)
@@ -87,7 +89,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
87
89
  - localPath: 로컬 프로젝트 경로
88
90
 
89
91
  **오너 초기화 시:**
90
- - yy_All_Docu/, _Infra_Config/, _Policy/, _Private/ 폴더 생성
92
+ - xx_Infra_Config/, xx_Policy/ 폴더 생성 (시스템 설정)
93
+ - yy_All_Docu/, yy_All_Docu/_Private/ 폴더 생성
91
94
  - zz_ai_1_Talk/, zz_ai_2_Todo/, zz_ai_3_Plan/ 폴더 생성
92
95
  - CLAUDE.md에 DocuKing 연결 안내 추가
93
96
  - 초기화 완료 후 정책 문서 작성 가이드 제공
@@ -97,7 +100,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
97
100
  - CLAUDE.md에 DocuKing 연결 안내 추가
98
101
  - "Pull을 실행하세요" 안내 (오너 정책이 킹캐스트로 로컬화됨)
99
102
 
100
- **정책 문서 템플릿 (오너용, _Policy/ 폴더에 작성):**
103
+ **정책 문서 템플릿 (오너용, xx_Policy/ 폴더에 작성):**
101
104
 
102
105
  [필수]
103
106
  - 00_project_overview.md - 프로젝트 개요, 기술 스택, 팀 구성, 주요 URL
@@ -188,7 +191,7 @@ init 완료 후 오너에게 "정책 문서를 작성하시겠습니까?" 제안
188
191
  },
189
192
  {
190
193
  name: 'docuking_pull',
191
- description: '서버에서 문서를 다운로드하여 yy_All_Docu/ 폴더에 저장합니다. "DocuKing에서 가져와" 요청 시 사용.\n\n**킹캐스트**: Pull 후 _Policy/ 폴더 변경이 감지되면 자동으로 .claude/rules/local/에 로컬화됩니다. _Infra_Config/는 참조용으로 내려오지만 로컬화하지 않습니다.',
194
+ description: '서버에서 문서를 다운로드합니다. "DocuKing에서 가져와" 요청 시 사용.\n\n**킹캐스트**: Pull 후 xx_Policy/, xx_Infra_Config/ 폴더 변경이 감지되면 자동으로 .claude/rules/local/에 로컬화됩니다.',
192
195
  inputSchema: {
193
196
  type: 'object',
194
197
  properties: {
@@ -451,7 +454,7 @@ init 완료 후 오너에게 "정책 문서를 작성하시겠습니까?" 제안
451
454
 
452
455
  **검증 대상:**
453
456
  - .claude/rules/local/ 의 정책 파일 기준 (킹캐스트로 로컬화된 정책)
454
- - yy_All_Docu/_Policy/ 정책 파일도 참조
457
+ - xx_Policy/ 정책 파일도 참조
455
458
  - 폴더 구조, 명명 규칙, API 규칙, DB 스키마 등
456
459
 
457
460
  **출력:**
@@ -577,7 +580,7 @@ zz_ai_3_Plan/
577
580
 
578
581
  ### 3. docuking_pull
579
582
  서버 문서를 로컬로 다운로드합니다.
580
- **킹캐스트**: Pull 후 _Policy/ 폴더 변경이 감지되면 자동으로 .claude/rules/local/에 로컬화됩니다. _Infra_Config/는 참조용으로 내려오지만 로컬화하지 않습니다.
583
+ **킹캐스트**: Pull 후 xx_Policy/, xx_Infra_Config/ 폴더 변경이 감지되면 자동으로 .claude/rules/local/에 로컬화됩니다.
581
584
 
582
585
  ### 4. docuking_list
583
586
  서버 파일 목록을 조회합니다.
@@ -653,7 +656,7 @@ DocuKing 협업의 핵심 원칙입니다. **각자 자기 영역만 수정할
653
656
 
654
657
  ## 킹캐스트 (KingCast) - 정책 자동 배포
655
658
 
656
- 오너가 \`yy_All_Docu/_Policy/\` 폴더에 정책을 작성하고 Push하면,
659
+ 오너가 \`xx_Policy/\` 폴더에 정책을 작성하고 Push하면,
657
660
  협업자가 Pull할 때 자동으로 \`.claude/rules/local/\`에 서브파일 구조로 로컬화됩니다.
658
661
 
659
662
  ### 킹캐스트 동작 원리
@@ -662,12 +665,12 @@ DocuKing 협업의 핵심 원칙입니다. **각자 자기 영역만 수정할
662
665
  \`\`\`
663
666
 
664
667
  ### 킹캐스트 대상 폴더
665
- - \`yy_All_Docu/_Infra_Config/\` - 환경 설정 (참조용, 로컬화하지 않음)
666
- - \`yy_All_Docu/_Policy/\` - AI 행동 지침 (로컬화 대상)
668
+ - \`xx_Infra_Config/\` - 환경 설정 (.env 백업, 배포 정보 등) → 변경 감지만 (복사X)
669
+ - \`xx_Policy/\` - AI 행동 지침 .claude/rules/local/에 복사
667
670
 
668
671
  ### 정책 파일 작성 템플릿 (오너용)
669
672
  \`\`\`
670
- _Policy/
673
+ xx_Policy/
671
674
  ├── 00_project_overview.md # 프로젝트 개요
672
675
  ├── 01_folder_structure.md # 폴더 구조
673
676
  ├── 02_api_convention.md # API 규칙
@@ -681,9 +684,11 @@ _Policy/
681
684
  - \`.claude/rules/local/_coworker_config.md\` - 협업자 설정 (협업자만)
682
685
 
683
686
  ### AI 필독: 킹캐스트 후 행동
684
- 1. Pull 후 "📢 킹캐스트" 메시지가 표시되면, 정책 변경이 감지된 것
687
+ 1. Pull 후 "📢 킹캐스트" 메시지가 표시되면, 정책/환경 변경이 감지된 것
685
688
  2. \`.claude/rules/local/00_index.md\`를 읽고 정책 목록 확인
686
689
  3. 각 정책 파일을 **읽어서** 내용을 숙지하고 규칙을 따라 작업
690
+ 4. **xx_Infra_Config 변경 시**: 원본 경로(xx_Infra_Config/)에서 직접 읽고 로컬 환경에 맞게 적용
691
+ - 예: .env 변수 추가/수정, 배포 설정 확인 등
687
692
 
688
693
  웹 탐색기: https://docuking.ai
689
694
  `;
package/lib/init.js CHANGED
@@ -64,7 +64,7 @@ ${marker}
64
64
  - 의미 있는 작업 시작 시 (추적용)
65
65
 
66
66
  ### 규칙
67
- 1. 동기화 대상: yy_All_Docu/ + zz_ai_*/ 폴더 모두
67
+ 1. 동기화 대상: xx_*/ + yy_All_Docu/ + zz_ai_*/ 폴더 모두
68
68
  2. 킹푸시는 Plan 완료(done) 시 자동 실행
69
69
  3. **Talk → Todo → Plan → Done** 순서 준수
70
70
  4. Plan 전에 반드시 Talk로 배경 기록
@@ -85,7 +85,7 @@ ${marker}
85
85
 
86
86
  | 역할 | Push (올리기) | Pull (내리기) | 삭제 |
87
87
  |------|---------------|---------------|------|
88
- | **오너** | \`yy_All_Docu/\` + \`zz_ai_*/\` | 합집합 전체 | 자기 영역만 |
88
+ | **오너** | \`xx_*/\` + \`yy_All_Docu/\` + \`zz_ai_*/\` | 합집합 전체 | 자기 영역만 |
89
89
  | **협업자** | \`yy_Coworker_{본인}/\` (안에 zz_ai_* 포함) | 합집합 전체 | 자기 영역만 |
90
90
 
91
91
  ### 합집합이란?
@@ -103,6 +103,8 @@ ${marker}
103
103
  ### 폴더 구조 (Pull 후)
104
104
  \`\`\`
105
105
  project/
106
+ ├── xx_Infra_Config/ ← 시스템 설정 (오너 관리)
107
+ ├── xx_Policy/ ← 정책 문서 (오너 관리, 킹캐스트 대상)
106
108
  ├── yy_All_Docu/ ← 오너 문서 (읽기만)
107
109
  ├── yy_Coworker_a_Kim/ ← 협업자 Kim
108
110
  │ ├── 작업문서.md
@@ -120,19 +122,19 @@ project/
120
122
 
121
123
  ## 킹캐스트 (KingCast) - 정책 자동 배포
122
124
 
123
- 오너가 \`yy_All_Docu/_Policy/\` 폴더에 정책을 작성하고 Push하면,
125
+ 오너가 \`xx_Policy/\` 폴더에 정책을 작성하고 Push하면,
124
126
  협업자가 Pull할 때 자동으로 \`.claude/rules/local/\`에 로컬화됩니다.
125
127
 
126
128
  ### 킹캐스트 대상 폴더
127
- - \`yy_All_Docu/_Infra_Config/\` - 환경 설정 (참조용, 로컬화하지 않음)
128
- - \`yy_All_Docu/_Policy/\` - AI 행동 지침 (로컬화 대상)
129
+ - \`xx_Infra_Config/\` - 환경 설정 (.env 백업, 배포 정보 등) → 변경 감지만
130
+ - \`xx_Policy/\` - AI 행동 지침 .claude/rules/local/에 복사
129
131
 
130
132
  ### 킹캐스트 동작
131
133
  1. Pull 실행
132
- 2. _Infra_Config/, _Policy/ 폴더 변경 감지
133
- 3. \`_Policy/\` 파일들을 \`.claude/rules/local/\`에 서브파일 구조로 복사
134
- 4. 협업자의 경우 변수 치환 (폴더명, 브랜치명 로컬화)
135
- 5. \`_Infra_Config/\`는 참조용으로 내려오지만, 협업자가 직접 다룰 정보가 아니므로 로컬화하지 않음
134
+ 2. xx_Infra_Config/, xx_Policy/ 폴더 변경 감지 (해시 비교)
135
+ 3. \`xx_Policy/\` 파일들을 \`.claude/rules/local/\`에 서브파일 구조로 복사
136
+ 4. \`xx_Infra_Config/\` 변경 AI에게 알림 (복사X, 원본 경로에서 직접 읽음)
137
+ 5. 협업자의 경우 AI가 내용을 읽고 로컬 환경에 맞게 적용
136
138
 
137
139
  ### Git 제외 정책
138
140
 
@@ -144,9 +146,11 @@ project/
144
146
  - \`.claude/rules/local/*.md\` - 정책 파일 (폴더구조, API규칙 등 민감정보 없음)
145
147
 
146
148
  ### AI 필독
147
- - Pull 후 "📢 킹캐스트" 메시지가 표시되면, 정책 파일의 내용을 읽어 변경사항을 확인하세요.
149
+ - Pull 후 "📢 킹캐스트" 메시지가 표시되면 반드시 확인하세요.
148
150
  - \`.claude/rules/local/00_index.md\`를 읽고 정책 문서 목록을 확인하세요.
149
151
  - 각 정책 파일의 내용을 읽고 규칙을 따라 작업하세요.
152
+ - **xx_Infra_Config 변경 감지 시**: 해당 파일을 직접 읽고 로컬 환경에 맞게 적용하세요.
153
+ - 예: .env 변수 추가/수정, 배포 설정 확인 등
150
154
  `;
151
155
 
152
156
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docuking-mcp",
3
- "version": "2.7.0",
3
+ "version": "2.8.1",
4
4
  "description": "DocuKing MCP Server - AI 시대의 문서 협업 플랫폼",
5
5
  "type": "module",
6
6
  "main": "index.js",