claudeos-core 1.0.1 → 1.0.2
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/package.json +75 -75
- package/plan-installer/index.js +101 -8
package/package.json
CHANGED
|
@@ -1,75 +1,75 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "claudeos-core",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Auto-generate Claude Code documentation from your actual source code — Standards, Rules, Skills, and Guides tailored to your project",
|
|
5
|
-
"main": "health-checker/index.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"claudeos-core": "bin/cli.js"
|
|
8
|
-
},
|
|
9
|
-
"files": [
|
|
10
|
-
"bin/",
|
|
11
|
-
"content-validator/",
|
|
12
|
-
"health-checker/",
|
|
13
|
-
"import-linter/",
|
|
14
|
-
"manifest-generator/",
|
|
15
|
-
"pass-json-validator/",
|
|
16
|
-
"pass-prompts/",
|
|
17
|
-
"plan-installer/",
|
|
18
|
-
"plan-validator/",
|
|
19
|
-
"sync-checker/",
|
|
20
|
-
"bootstrap.sh",
|
|
21
|
-
"README.md",
|
|
22
|
-
"README.ko.md",
|
|
23
|
-
"LICENSE",
|
|
24
|
-
"CHANGELOG.md",
|
|
25
|
-
"CONTRIBUTING.md",
|
|
26
|
-
"README.zh-CN.md",
|
|
27
|
-
"README.ja.md",
|
|
28
|
-
"README.es.md",
|
|
29
|
-
"README.vi.md",
|
|
30
|
-
"README.hi.md",
|
|
31
|
-
"README.ru.md",
|
|
32
|
-
"README.fr.md",
|
|
33
|
-
"README.de.md"
|
|
34
|
-
],
|
|
35
|
-
"scripts": {
|
|
36
|
-
"init": "node bin/cli.js init",
|
|
37
|
-
"health": "node bin/cli.js health",
|
|
38
|
-
"validate": "node bin/cli.js validate",
|
|
39
|
-
"refresh": "node bin/cli.js refresh",
|
|
40
|
-
"restore": "node bin/cli.js restore",
|
|
41
|
-
"test": "node health-checker/index.js"
|
|
42
|
-
},
|
|
43
|
-
"keywords": [
|
|
44
|
-
"claude-code",
|
|
45
|
-
"automation",
|
|
46
|
-
"code-analysis",
|
|
47
|
-
"CLAUDE.md",
|
|
48
|
-
"standards",
|
|
49
|
-
"rules",
|
|
50
|
-
"skills",
|
|
51
|
-
"scaffolding",
|
|
52
|
-
"spring-boot",
|
|
53
|
-
"nextjs",
|
|
54
|
-
"express",
|
|
55
|
-
"django",
|
|
56
|
-
"fastapi"
|
|
57
|
-
],
|
|
58
|
-
"author": "claudeos-core <claudeoscore@gmail.com> (https://github.com/claudeos-core)",
|
|
59
|
-
"license": "ISC",
|
|
60
|
-
"repository": {
|
|
61
|
-
"type": "git",
|
|
62
|
-
"url": "git+https://github.com/claudeos-core/claudeos-core.git"
|
|
63
|
-
},
|
|
64
|
-
"homepage": "https://github.com/claudeos-core/claudeos-core#readme",
|
|
65
|
-
"bugs": {
|
|
66
|
-
"url": "https://github.com/claudeos-core/claudeos-core/issues"
|
|
67
|
-
},
|
|
68
|
-
"engines": {
|
|
69
|
-
"node": ">=18.0.0"
|
|
70
|
-
},
|
|
71
|
-
"dependencies": {
|
|
72
|
-
"glob": "^13.0.6",
|
|
73
|
-
"gray-matter": "^4.0.3"
|
|
74
|
-
}
|
|
75
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "claudeos-core",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Auto-generate Claude Code documentation from your actual source code — Standards, Rules, Skills, and Guides tailored to your project",
|
|
5
|
+
"main": "health-checker/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"claudeos-core": "bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin/",
|
|
11
|
+
"content-validator/",
|
|
12
|
+
"health-checker/",
|
|
13
|
+
"import-linter/",
|
|
14
|
+
"manifest-generator/",
|
|
15
|
+
"pass-json-validator/",
|
|
16
|
+
"pass-prompts/",
|
|
17
|
+
"plan-installer/",
|
|
18
|
+
"plan-validator/",
|
|
19
|
+
"sync-checker/",
|
|
20
|
+
"bootstrap.sh",
|
|
21
|
+
"README.md",
|
|
22
|
+
"README.ko.md",
|
|
23
|
+
"LICENSE",
|
|
24
|
+
"CHANGELOG.md",
|
|
25
|
+
"CONTRIBUTING.md",
|
|
26
|
+
"README.zh-CN.md",
|
|
27
|
+
"README.ja.md",
|
|
28
|
+
"README.es.md",
|
|
29
|
+
"README.vi.md",
|
|
30
|
+
"README.hi.md",
|
|
31
|
+
"README.ru.md",
|
|
32
|
+
"README.fr.md",
|
|
33
|
+
"README.de.md"
|
|
34
|
+
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"init": "node bin/cli.js init",
|
|
37
|
+
"health": "node bin/cli.js health",
|
|
38
|
+
"validate": "node bin/cli.js validate",
|
|
39
|
+
"refresh": "node bin/cli.js refresh",
|
|
40
|
+
"restore": "node bin/cli.js restore",
|
|
41
|
+
"test": "node health-checker/index.js"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"claude-code",
|
|
45
|
+
"automation",
|
|
46
|
+
"code-analysis",
|
|
47
|
+
"CLAUDE.md",
|
|
48
|
+
"standards",
|
|
49
|
+
"rules",
|
|
50
|
+
"skills",
|
|
51
|
+
"scaffolding",
|
|
52
|
+
"spring-boot",
|
|
53
|
+
"nextjs",
|
|
54
|
+
"express",
|
|
55
|
+
"django",
|
|
56
|
+
"fastapi"
|
|
57
|
+
],
|
|
58
|
+
"author": "claudeos-core <claudeoscore@gmail.com> (https://github.com/claudeos-core)",
|
|
59
|
+
"license": "ISC",
|
|
60
|
+
"repository": {
|
|
61
|
+
"type": "git",
|
|
62
|
+
"url": "git+https://github.com/claudeos-core/claudeos-core.git"
|
|
63
|
+
},
|
|
64
|
+
"homepage": "https://github.com/claudeos-core/claudeos-core#readme",
|
|
65
|
+
"bugs": {
|
|
66
|
+
"url": "https://github.com/claudeos-core/claudeos-core/issues"
|
|
67
|
+
},
|
|
68
|
+
"engines": {
|
|
69
|
+
"node": ">=18.0.0"
|
|
70
|
+
},
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"glob": "^13.0.6",
|
|
73
|
+
"gray-matter": "^4.0.3"
|
|
74
|
+
}
|
|
75
|
+
}
|
package/plan-installer/index.js
CHANGED
|
@@ -194,24 +194,117 @@ async function scanStructure(stack) {
|
|
|
194
194
|
if (stack.language === "java") {
|
|
195
195
|
const javaFiles = await glob("src/main/java/**/*.java", { cwd: ROOT });
|
|
196
196
|
for (const f of javaFiles) {
|
|
197
|
-
const m = f.match(/src\/main\/java\/(.+?)\/(controller|service|mapper|dto|entity|repository)/);
|
|
197
|
+
const m = f.match(/src\/main\/java\/(.+?)\/(controller|service|mapper|dto|entity|repository|adapter)/);
|
|
198
198
|
if (m) { rootPackage = m[1].replace(/\//g, "."); break; }
|
|
199
199
|
}
|
|
200
|
-
const controllers = await glob("src/main/java/**/controller/*/*.java", { cwd: ROOT });
|
|
201
200
|
const domainMap = {};
|
|
202
|
-
|
|
201
|
+
let detectedPattern = null;
|
|
202
|
+
|
|
203
|
+
// Pattern A: controller/{domain}/*.java (레이어 우선 — controller 아래에 도메인)
|
|
204
|
+
const controllersA = await glob("src/main/java/**/controller/*/*.java", { cwd: ROOT });
|
|
205
|
+
for (const f of controllersA) {
|
|
203
206
|
const m = f.match(/controller\/([^/]+)\//);
|
|
204
207
|
if (m) {
|
|
205
208
|
const d = m[1];
|
|
206
|
-
if (!domainMap[d]) domainMap[d] = { controllers: 0, services: 0, mappers: 0, dtos: 0, xmlMappers: 0 };
|
|
209
|
+
if (!domainMap[d]) domainMap[d] = { controllers: 0, services: 0, mappers: 0, dtos: 0, xmlMappers: 0, pattern: "A" };
|
|
207
210
|
domainMap[d].controllers++;
|
|
208
211
|
}
|
|
209
212
|
}
|
|
213
|
+
if (Object.keys(domainMap).length > 0) detectedPattern = "A";
|
|
214
|
+
|
|
215
|
+
// Pattern B/D: {domain}/controller/*.java (도메인 우선 — 도메인 아래에 controller)
|
|
216
|
+
// D는 B의 확장: {module}/{domain}/controller/ — 동일 도메인명 충돌 시 module/domain 형태로 전환
|
|
217
|
+
if (!detectedPattern) {
|
|
218
|
+
const controllersB = await glob("src/main/java/**/*/controller/*.java", { cwd: ROOT });
|
|
219
|
+
const domainPaths = {};
|
|
220
|
+
for (const f of controllersB) {
|
|
221
|
+
const m = f.match(/\/([^/]+)\/controller\/[^/]+\.java$/);
|
|
222
|
+
if (m) {
|
|
223
|
+
const d = m[1];
|
|
224
|
+
const parentMatch = f.match(/\/([^/]+)\/([^/]+)\/controller\//);
|
|
225
|
+
const parentModule = parentMatch ? parentMatch[1] : null;
|
|
226
|
+
if (!domainPaths[d]) domainPaths[d] = [];
|
|
227
|
+
domainPaths[d].push({ file: f, module: parentModule });
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// 동일 도메인명이 여러 모듈에서 발견되면 module/domain 형태로 (Pattern D)
|
|
232
|
+
for (const [d, entries] of Object.entries(domainPaths)) {
|
|
233
|
+
const modules = [...new Set(entries.map(e => e.module).filter(Boolean))];
|
|
234
|
+
if (modules.length > 1) {
|
|
235
|
+
// Pattern D: 충돌 — module/domain 형태로 등록
|
|
236
|
+
for (const entry of entries) {
|
|
237
|
+
const fullName = entry.module ? `${entry.module}/${d}` : d;
|
|
238
|
+
if (!domainMap[fullName]) domainMap[fullName] = { controllers: 0, services: 0, mappers: 0, dtos: 0, xmlMappers: 0, pattern: "D", modulePath: entry.module, domainName: d };
|
|
239
|
+
domainMap[fullName].controllers++;
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
if (!domainMap[d]) domainMap[d] = { controllers: 0, services: 0, mappers: 0, dtos: 0, xmlMappers: 0, pattern: "B" };
|
|
243
|
+
domainMap[d].controllers += entries.length;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (Object.keys(domainMap).length > 0) detectedPattern = domainMap[Object.keys(domainMap)[0]].pattern;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Pattern E: DDD/헥사고날 — {domain}/adapter/in/web/*.java 또는 {domain}/adapter/in/rest/*.java
|
|
250
|
+
if (!detectedPattern) {
|
|
251
|
+
const controllersE = await glob("src/main/java/**/adapter/in/{web,rest}/*.java", { cwd: ROOT });
|
|
252
|
+
for (const f of controllersE) {
|
|
253
|
+
const m = f.match(/\/([^/]+)\/adapter\/in\/(web|rest)\/[^/]+\.java$/);
|
|
254
|
+
if (m) {
|
|
255
|
+
const d = m[1];
|
|
256
|
+
if (!domainMap[d]) domainMap[d] = { controllers: 0, services: 0, mappers: 0, dtos: 0, xmlMappers: 0, pattern: "E" };
|
|
257
|
+
domainMap[d].controllers++;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (Object.keys(domainMap).length > 0) detectedPattern = "E";
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Pattern C: 플랫 구조 — controller/*.java (도메인 디렉토리 없음, 클래스명에서 도메인 추출)
|
|
264
|
+
if (!detectedPattern) {
|
|
265
|
+
const controllersC = await glob("src/main/java/**/controller/*.java", { cwd: ROOT });
|
|
266
|
+
for (const f of controllersC) {
|
|
267
|
+
const m = f.match(/\/([A-Z][a-zA-Z]*)Controller\.java$/);
|
|
268
|
+
if (m) {
|
|
269
|
+
const d = m[1].toLowerCase();
|
|
270
|
+
if (!domainMap[d]) domainMap[d] = { controllers: 0, services: 0, mappers: 0, dtos: 0, xmlMappers: 0, pattern: "C" };
|
|
271
|
+
domainMap[d].controllers++;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (Object.keys(domainMap).length > 0) detectedPattern = "C";
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// 각 도메인의 service/mapper/dto/xml 파일 스캔
|
|
210
278
|
for (const d of Object.keys(domainMap)) {
|
|
211
|
-
const
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
279
|
+
const p = domainMap[d].pattern;
|
|
280
|
+
const dn = domainMap[d].domainName || d;
|
|
281
|
+
let svcGlob, mprGlob, dtoGlob;
|
|
282
|
+
|
|
283
|
+
if (p === "A") {
|
|
284
|
+
svcGlob = `src/main/java/**/service/${d}/*.java`;
|
|
285
|
+
mprGlob = `src/main/java/**/{mapper,repository}/${d}/*.java`;
|
|
286
|
+
dtoGlob = `src/main/java/**/dto/${d}/**/*.java`;
|
|
287
|
+
} else if (p === "B" || p === "D") {
|
|
288
|
+
svcGlob = `src/main/java/**/${dn}/service/*.java`;
|
|
289
|
+
mprGlob = `src/main/java/**/${dn}/{mapper,repository}/*.java`;
|
|
290
|
+
dtoGlob = `src/main/java/**/${dn}/dto/**/*.java`;
|
|
291
|
+
} else if (p === "E") {
|
|
292
|
+
svcGlob = `src/main/java/**/${d}/{application,domain}/**/*.java`;
|
|
293
|
+
mprGlob = `src/main/java/**/${d}/adapter/out/{persistence,repository}/*.java`;
|
|
294
|
+
dtoGlob = `src/main/java/**/${d}/**/{dto,command,query}/**/*.java`;
|
|
295
|
+
} else {
|
|
296
|
+
// Pattern C: 플랫 — 도메인명으로 파일명 매칭
|
|
297
|
+
const cap = d.charAt(0).toUpperCase() + d.slice(1);
|
|
298
|
+
svcGlob = `src/main/java/**/service/${cap}*.java`;
|
|
299
|
+
mprGlob = `src/main/java/**/{mapper,repository}/${cap}*.java`;
|
|
300
|
+
dtoGlob = `src/main/java/**/dto/${cap}*.java`;
|
|
301
|
+
}
|
|
302
|
+
const xmlGlob = `src/main/resources/mapper/**/${dn}/*.xml`;
|
|
303
|
+
|
|
304
|
+
const svc = await glob(svcGlob, { cwd: ROOT });
|
|
305
|
+
const mpr = await glob(mprGlob, { cwd: ROOT });
|
|
306
|
+
const dto = await glob(dtoGlob, { cwd: ROOT });
|
|
307
|
+
const xml = await glob(xmlGlob, { cwd: ROOT });
|
|
215
308
|
domainMap[d].services = svc.length;
|
|
216
309
|
domainMap[d].mappers = mpr.length;
|
|
217
310
|
domainMap[d].dtos = dto.length;
|