docuking-mcp 2.7.0 → 2.8.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.
@@ -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,33 @@ function updateLocalRules(localPath, currentFiles, changes, config) {
206
205
  }
207
206
  }
208
207
 
208
+ // ========================================
209
+ // 1.5. xx_Infra_Config 파일들을 infra/ 서브폴더로 복사
210
+ // ========================================
211
+ const infraLocalPath = path.join(localRulesPath, 'infra');
212
+ if (infraConfigFiles.length > 0) {
213
+ fs.mkdirSync(infraLocalPath, { recursive: true });
214
+
215
+ for (const file of infraConfigFiles) {
216
+ // xx_Infra_Config/deploy.md → infra/deploy.md
217
+ const relativePath = file.key.replace('xx_Infra_Config/', '');
218
+ const targetPath = path.join(infraLocalPath, relativePath);
219
+
220
+ // 디렉토리 생성
221
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
222
+
223
+ // 파일 읽기 및 로컬화
224
+ try {
225
+ const content = fs.readFileSync(file.fullPath, 'utf-8');
226
+ const localizedContent = localizeContent(content, config);
227
+ fs.writeFileSync(targetPath, localizedContent, 'utf-8');
228
+ createdFiles.push(`infra/${relativePath}`);
229
+ } catch (e) {
230
+ console.error(`[KingCast] 인프라 설정 파일 복사 실패: ${file.key} - ${e.message}`);
231
+ }
232
+ }
233
+ }
234
+
209
235
  // ========================================
210
236
  // 2. 협업자용 설정 파일 생성 (_coworker_config.md)
211
237
  // ========================================
@@ -271,13 +297,13 @@ git checkout -b coworker/${coworkerFolder}
271
297
  ## 환경 정보 (읽기 전용 참고)
272
298
  `;
273
299
 
274
- // _Infra_Config에서 민감하지 않은 정보 추가
300
+ // xx_Infra_Config에서 민감하지 않은 정보 추가
275
301
  let infraInfo = '';
276
302
  for (const file of infraConfigFiles) {
277
303
  const fileName = path.basename(file.key);
278
304
  // 배포 관련 정보만 참조 (민감 정보 제외)
279
305
  if (fileName.includes('deploy') || fileName.includes('README')) {
280
- infraInfo += `\n참고 문서: yy_All_Docu/${file.key}`;
306
+ infraInfo += `\n참고 문서: ${file.key}`;
281
307
  }
282
308
  }
283
309
 
@@ -316,11 +342,20 @@ git checkout -b coworker/${coworkerFolder}
316
342
  indexContent += '\n(정책 문서가 없습니다)\n';
317
343
  } else {
318
344
  for (const file of policyFiles) {
319
- const relativePath = file.key.replace('_Policy/', '');
345
+ const relativePath = file.key.replace('xx_Policy/', '');
320
346
  indexContent += `- [${relativePath}](./${relativePath})\n`;
321
347
  }
322
348
  }
323
349
 
350
+ // 인프라 설정 파일 목록 추가
351
+ if (infraConfigFiles.length > 0) {
352
+ indexContent += '\n## 인프라 설정 (참조용)\n';
353
+ for (const file of infraConfigFiles) {
354
+ const relativePath = file.key.replace('xx_Infra_Config/', '');
355
+ indexContent += `- [${relativePath}](./infra/${relativePath})\n`;
356
+ }
357
+ }
358
+
324
359
  if (isCoworker) {
325
360
  indexContent += `\n## 협업자 설정\n- [_coworker_config.md](./_coworker_config.md)\n`;
326
361
  }
@@ -329,12 +364,13 @@ git checkout -b coworker/${coworkerFolder}
329
364
  createdFiles.push('00_index.md');
330
365
 
331
366
  // ========================================
332
- // 4. 삭제된 정책에 해당하는 로컬 파일 삭제
367
+ // 4. 삭제된 정책/인프라에 해당하는 로컬 파일 삭제
333
368
  // ========================================
334
369
  if (changes.deleted.length > 0) {
335
370
  for (const deletedKey of changes.deleted) {
336
- if (deletedKey.startsWith('_Policy/')) {
337
- const relativePath = deletedKey.replace('_Policy/', '');
371
+ // xx_Policy 삭제
372
+ if (deletedKey.startsWith('xx_Policy/')) {
373
+ const relativePath = deletedKey.replace('xx_Policy/', '');
338
374
  const targetPath = path.join(localRulesPath, relativePath);
339
375
  if (fs.existsSync(targetPath)) {
340
376
  try {
@@ -345,6 +381,19 @@ git checkout -b coworker/${coworkerFolder}
345
381
  }
346
382
  }
347
383
  }
384
+ // xx_Infra_Config 삭제
385
+ if (deletedKey.startsWith('xx_Infra_Config/')) {
386
+ const relativePath = deletedKey.replace('xx_Infra_Config/', '');
387
+ const targetPath = path.join(localRulesPath, 'infra', relativePath);
388
+ if (fs.existsSync(targetPath)) {
389
+ try {
390
+ fs.unlinkSync(targetPath);
391
+ console.error(`[KingCast] 삭제된 인프라 설정 제거: infra/${relativePath}`);
392
+ } catch (e) {
393
+ console.error(`[KingCast] 파일 삭제 실패: infra/${relativePath} - ${e.message}`);
394
+ }
395
+ }
396
+ }
348
397
  }
349
398
  }
350
399
 
@@ -511,9 +560,9 @@ export async function handleKingcastStatus(args) {
511
560
  ## 킹캐스트 대상 파일
512
561
  `;
513
562
 
514
- // _Infra_Config 파일
515
- statusText += '\n### _Infra_Config/\n';
516
- const infraConfigFiles = Object.keys(currentFiles).filter(k => k.startsWith('_Infra_Config/'));
563
+ // xx_Infra_Config 파일
564
+ statusText += '\n### xx_Infra_Config/\n';
565
+ const infraConfigFiles = Object.keys(currentFiles).filter(k => k.startsWith('xx_Infra_Config/'));
517
566
  if (infraConfigFiles.length === 0) {
518
567
  statusText += '(없음)\n';
519
568
  } else {
@@ -522,9 +571,9 @@ export async function handleKingcastStatus(args) {
522
571
  }
523
572
  }
524
573
 
525
- // _Policy 파일
526
- statusText += '\n### _Policy/\n';
527
- const policyFiles = Object.keys(currentFiles).filter(k => k.startsWith('_Policy/'));
574
+ // xx_Policy 파일
575
+ statusText += '\n### xx_Policy/\n';
576
+ const policyFiles = Object.keys(currentFiles).filter(k => k.startsWith('xx_Policy/'));
528
577
  if (policyFiles.length === 0) {
529
578
  statusText += '(없음)\n';
530
579
  } 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 백업, 배포 정보 등) → .claude/rules/local/infra/에 로컬화
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 규칙
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 행동 지침 로컬화 대상
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/\` 파일들도 \`.claude/rules/local/infra/\`에 복사 (환경변수, 배포 설정 등)
137
+ 5. 협업자의 경우 변수 치환 (폴더명, 브랜치명 로컬화)
136
138
 
137
139
  ### Git 제외 정책
138
140
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docuking-mcp",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "description": "DocuKing MCP Server - AI 시대의 문서 협업 플랫폼",
5
5
  "type": "module",
6
6
  "main": "index.js",