claudeos-core 1.5.0 → 1.5.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.
- package/CHANGELOG.md +12 -0
- package/bin/commands/init.js +1 -1
- package/bin/lib/cli-utils.js +1 -1
- package/content-validator/index.js +2 -2
- package/health-checker/index.js +1 -1
- package/lib/safe-fs.js +2 -2
- package/manifest-generator/index.js +2 -2
- package/package.json +87 -87
- package/pass-json-validator/index.js +2 -2
- package/plan-installer/scanners/scan-frontend.js +4 -4
- package/plan-installer/scanners/scan-java.js +6 -1
- package/plan-installer/stack-detector.js +2 -0
- package/plan-validator/index.js +1 -1
- package/sync-checker/index.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.5.1] — 2026-04-06
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- **Remove 13 bare catch blocks** — `catch { }` → `catch (_e) { }` across 9 files; enables error variable access during debugging
|
|
7
|
+
- **Windows backslash glob fix (3 locations)** — `scan-frontend.js` missing `dir.replace(/\\/g, "/")` at App/Pages Router (line 63), FSD (line 84), and components (line 98) scans; other locations already had this fix
|
|
8
|
+
- **Pattern C flat MyBatis XML detection** — `scan-java.js` xmlGlob now matches flat XML layout (e.g., `mapper/OrderMapper.xml`) in addition to domain subdirectory layout for Pattern C projects
|
|
9
|
+
- **Next.js reserved segment false positives** — Added `not-found`, `error`, `loading` to `skipPages` in `scan-frontend.js` to prevent Next.js App Router reserved directories from being detected as domains
|
|
10
|
+
- **cap variable shadowing** — Renamed outer-scope `cap` to `capDn` in `scan-java.js` to avoid shadowing the block-scoped `cap` in Pattern C branch
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- **Gradle DB detection comment** — Added 2-line comment explaining postgres/sqlite exclusion rationale in `stack-detector.js` line 118
|
|
14
|
+
|
|
3
15
|
## [1.5.0] — 2026-04-05
|
|
4
16
|
- feat: initial release claudeos-core v1.5.0
|
package/bin/commands/init.js
CHANGED
|
@@ -217,7 +217,7 @@ async function cmdInit(parsedArgs) {
|
|
|
217
217
|
log(` ⏭️ pass1-${i}.json already exists, skipping`);
|
|
218
218
|
continue;
|
|
219
219
|
}
|
|
220
|
-
} catch { /* malformed — re-run */ }
|
|
220
|
+
} catch (_e) { /* malformed — re-run */ }
|
|
221
221
|
log(` ⚠️ pass1-${i}.json exists but is malformed, re-running`);
|
|
222
222
|
}
|
|
223
223
|
|
package/bin/lib/cli-utils.js
CHANGED
|
@@ -110,7 +110,7 @@ function countFiles() {
|
|
|
110
110
|
const scan = (dir) => {
|
|
111
111
|
if (!fs.existsSync(dir)) return;
|
|
112
112
|
let realDir;
|
|
113
|
-
try { realDir = fs.realpathSync(dir); } catch { realDir = dir; }
|
|
113
|
+
try { realDir = fs.realpathSync(dir); } catch (_e) { realDir = dir; }
|
|
114
114
|
if (visited.has(realDir)) return;
|
|
115
115
|
visited.add(realDir);
|
|
116
116
|
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
@@ -50,7 +50,7 @@ async function main() {
|
|
|
50
50
|
const pa = JSON.parse(fs.readFileSync(paPath, "utf-8"));
|
|
51
51
|
detectedLanguage = pa.stack?.language || null;
|
|
52
52
|
outputLang = pa.lang || "en";
|
|
53
|
-
} catch { /* ignore */ }
|
|
53
|
+
} catch (_e) { /* ignore */ }
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
// Language-aware section keywords for CLAUDE.md validation
|
|
@@ -327,7 +327,7 @@ async function main() {
|
|
|
327
327
|
const rp = path.join(GEN_DIR, "stale-report.json");
|
|
328
328
|
let ex = {};
|
|
329
329
|
if (fs.existsSync(rp)) {
|
|
330
|
-
try { ex = JSON.parse(fs.readFileSync(rp, "utf-8")); } catch { ex = {}; }
|
|
330
|
+
try { ex = JSON.parse(fs.readFileSync(rp, "utf-8")); } catch (_e) { ex = {}; }
|
|
331
331
|
}
|
|
332
332
|
ex.contentValidation = { checkedAt: new Date().toISOString(), checked, errors: errors.length, warnings: warnings.length, details: { errors, warnings } };
|
|
333
333
|
ex.summary = { ...ex.summary, contentErrors: errors.length, contentWarnings: warnings.length };
|
package/health-checker/index.js
CHANGED
|
@@ -108,7 +108,7 @@ function main() {
|
|
|
108
108
|
const rp = path.join(GEN, "stale-report.json");
|
|
109
109
|
let ex = {};
|
|
110
110
|
if (fs.existsSync(rp)) {
|
|
111
|
-
try { ex = JSON.parse(fs.readFileSync(rp, "utf-8")); } catch { ex = {}; }
|
|
111
|
+
try { ex = JSON.parse(fs.readFileSync(rp, "utf-8")); } catch (_e) { ex = {}; }
|
|
112
112
|
}
|
|
113
113
|
ex.generatedAt = new Date().toISOString();
|
|
114
114
|
ex.healthCheck = { results, status: hasErr ? "fail" : "pass" };
|
package/lib/safe-fs.js
CHANGED
|
@@ -50,7 +50,7 @@ function readJsonSafe(filePath, fallback = null) {
|
|
|
50
50
|
function existsSafe(filePath) {
|
|
51
51
|
try {
|
|
52
52
|
return fs.existsSync(filePath);
|
|
53
|
-
} catch {
|
|
53
|
+
} catch (_e) {
|
|
54
54
|
return false;
|
|
55
55
|
}
|
|
56
56
|
}
|
|
@@ -95,7 +95,7 @@ function statSafe(filePath) {
|
|
|
95
95
|
bytes: s.size,
|
|
96
96
|
modified: s.mtime.toISOString().split("T")[0],
|
|
97
97
|
};
|
|
98
|
-
} catch {
|
|
98
|
+
} catch (_e) {
|
|
99
99
|
return null;
|
|
100
100
|
}
|
|
101
101
|
}
|
|
@@ -48,7 +48,7 @@ function stat(f) {
|
|
|
48
48
|
function frontmatter(f) {
|
|
49
49
|
try {
|
|
50
50
|
return matter(fs.readFileSync(f, "utf-8")).data || {};
|
|
51
|
-
} catch {
|
|
51
|
+
} catch (_e) {
|
|
52
52
|
return {};
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -169,7 +169,7 @@ async function main() {
|
|
|
169
169
|
const srPath = path.join(GEN, "stale-report.json");
|
|
170
170
|
let sr = {};
|
|
171
171
|
if (fs.existsSync(srPath)) {
|
|
172
|
-
try { sr = JSON.parse(fs.readFileSync(srPath, "utf-8")); } catch { sr = {}; }
|
|
172
|
+
try { sr = JSON.parse(fs.readFileSync(srPath, "utf-8")); } catch (_e) { sr = {}; }
|
|
173
173
|
}
|
|
174
174
|
sr.generatedAt = new Date().toISOString();
|
|
175
175
|
if (!sr.summary) sr.summary = {};
|
package/package.json
CHANGED
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "claudeos-core",
|
|
3
|
-
"version": "1.5.
|
|
4
|
-
"description": "Auto-generate Claude Code documentation from your actual source code — Standards, Rules, Skills, and Guides tailored to your project",
|
|
5
|
-
"main": "bin/cli.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"claudeos-core": "bin/cli.js"
|
|
8
|
-
},
|
|
9
|
-
"files": [
|
|
10
|
-
"bin/",
|
|
11
|
-
"lib/",
|
|
12
|
-
"content-validator/",
|
|
13
|
-
"health-checker/",
|
|
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 --test tests/*.test.js",
|
|
42
|
-
"test:health": "node health-checker/index.js"
|
|
43
|
-
},
|
|
44
|
-
"keywords": [
|
|
45
|
-
"claude-code",
|
|
46
|
-
"automation",
|
|
47
|
-
"code-analysis",
|
|
48
|
-
"CLAUDE.md",
|
|
49
|
-
"standards",
|
|
50
|
-
"rules",
|
|
51
|
-
"skills",
|
|
52
|
-
"scaffolding",
|
|
53
|
-
"i18n",
|
|
54
|
-
"multi-language",
|
|
55
|
-
"spring-boot",
|
|
56
|
-
"kotlin",
|
|
57
|
-
"exposed",
|
|
58
|
-
"jooq",
|
|
59
|
-
"cqrs",
|
|
60
|
-
"bff",
|
|
61
|
-
"multi-module",
|
|
62
|
-
"monorepo",
|
|
63
|
-
"nextjs",
|
|
64
|
-
"express",
|
|
65
|
-
"fastify",
|
|
66
|
-
"angular",
|
|
67
|
-
"django",
|
|
68
|
-
"fastapi"
|
|
69
|
-
],
|
|
70
|
-
"author": "claudeos-core <claudeoscore@gmail.com> (https://github.com/claudeos-core)",
|
|
71
|
-
"license": "ISC",
|
|
72
|
-
"repository": {
|
|
73
|
-
"type": "git",
|
|
74
|
-
"url": "git+https://github.com/claudeos-core/claudeos-core.git"
|
|
75
|
-
},
|
|
76
|
-
"homepage": "https://github.com/claudeos-core/claudeos-core#readme",
|
|
77
|
-
"bugs": {
|
|
78
|
-
"url": "https://github.com/claudeos-core/claudeos-core/issues"
|
|
79
|
-
},
|
|
80
|
-
"engines": {
|
|
81
|
-
"node": ">=18.0.0"
|
|
82
|
-
},
|
|
83
|
-
"dependencies": {
|
|
84
|
-
"glob": "^13.0.6",
|
|
85
|
-
"gray-matter": "^4.0.3"
|
|
86
|
-
}
|
|
87
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "claudeos-core",
|
|
3
|
+
"version": "1.5.1",
|
|
4
|
+
"description": "Auto-generate Claude Code documentation from your actual source code — Standards, Rules, Skills, and Guides tailored to your project",
|
|
5
|
+
"main": "bin/cli.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"claudeos-core": "bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin/",
|
|
11
|
+
"lib/",
|
|
12
|
+
"content-validator/",
|
|
13
|
+
"health-checker/",
|
|
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 --test tests/*.test.js",
|
|
42
|
+
"test:health": "node health-checker/index.js"
|
|
43
|
+
},
|
|
44
|
+
"keywords": [
|
|
45
|
+
"claude-code",
|
|
46
|
+
"automation",
|
|
47
|
+
"code-analysis",
|
|
48
|
+
"CLAUDE.md",
|
|
49
|
+
"standards",
|
|
50
|
+
"rules",
|
|
51
|
+
"skills",
|
|
52
|
+
"scaffolding",
|
|
53
|
+
"i18n",
|
|
54
|
+
"multi-language",
|
|
55
|
+
"spring-boot",
|
|
56
|
+
"kotlin",
|
|
57
|
+
"exposed",
|
|
58
|
+
"jooq",
|
|
59
|
+
"cqrs",
|
|
60
|
+
"bff",
|
|
61
|
+
"multi-module",
|
|
62
|
+
"monorepo",
|
|
63
|
+
"nextjs",
|
|
64
|
+
"express",
|
|
65
|
+
"fastify",
|
|
66
|
+
"angular",
|
|
67
|
+
"django",
|
|
68
|
+
"fastapi"
|
|
69
|
+
],
|
|
70
|
+
"author": "claudeos-core <claudeoscore@gmail.com> (https://github.com/claudeos-core)",
|
|
71
|
+
"license": "ISC",
|
|
72
|
+
"repository": {
|
|
73
|
+
"type": "git",
|
|
74
|
+
"url": "git+https://github.com/claudeos-core/claudeos-core.git"
|
|
75
|
+
},
|
|
76
|
+
"homepage": "https://github.com/claudeos-core/claudeos-core#readme",
|
|
77
|
+
"bugs": {
|
|
78
|
+
"url": "https://github.com/claudeos-core/claudeos-core/issues"
|
|
79
|
+
},
|
|
80
|
+
"engines": {
|
|
81
|
+
"node": ">=18.0.0"
|
|
82
|
+
},
|
|
83
|
+
"dependencies": {
|
|
84
|
+
"glob": "^13.0.6",
|
|
85
|
+
"gray-matter": "^4.0.3"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -197,7 +197,7 @@ async function main() {
|
|
|
197
197
|
isBackend = !frontend || ["express", "nestjs", "django", "fastapi", "spring-boot"].includes(framework);
|
|
198
198
|
isKotlin = language === "kotlin";
|
|
199
199
|
isKotlinCqrs = isKotlin && (architecture === "cqrs" || paData.stack?.multiModule);
|
|
200
|
-
} catch { /* If project-analysis parsing fails, conservatively assume backend */ }
|
|
200
|
+
} catch (_e) { /* If project-analysis parsing fails, conservatively assume backend */ }
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
const sectionsToCheck = [
|
|
@@ -286,7 +286,7 @@ async function main() {
|
|
|
286
286
|
const rp = path.join(GEN_DIR, "stale-report.json");
|
|
287
287
|
let ex = {};
|
|
288
288
|
if (fs.existsSync(rp)) {
|
|
289
|
-
try { ex = JSON.parse(fs.readFileSync(rp, "utf-8")); } catch { ex = {}; }
|
|
289
|
+
try { ex = JSON.parse(fs.readFileSync(rp, "utf-8")); } catch (_e) { ex = {}; }
|
|
290
290
|
}
|
|
291
291
|
ex.jsonValidation = { checkedAt: new Date().toISOString(), checked, errors: errors.length, warnings: warnings.length };
|
|
292
292
|
ex.summary = { ...ex.summary, jsonErrors: errors.length, jsonWarnings: warnings.length };
|
|
@@ -56,11 +56,11 @@ async function scanFrontendDomains(stack, ROOT) {
|
|
|
56
56
|
...await glob("{app,src/app}/*/", { cwd: ROOT }),
|
|
57
57
|
...await glob("{pages,src/pages}/*/", { cwd: ROOT }),
|
|
58
58
|
];
|
|
59
|
-
const skipPages = ["api", "_app", "_document", "fonts"];
|
|
59
|
+
const skipPages = ["api", "_app", "_document", "fonts", "not-found", "error", "loading"];
|
|
60
60
|
for (const dir of allDirs) {
|
|
61
61
|
const name = path.basename(dir);
|
|
62
62
|
if (skipPages.includes(name) || name.startsWith("(") || name.startsWith("[") || name.startsWith("_") || name.startsWith(".")) continue;
|
|
63
|
-
const files = await glob(`${dir}**/*.{tsx,jsx,ts,js,vue}`, { cwd: ROOT });
|
|
63
|
+
const files = await glob(`${dir.replace(/\\/g, "/")}**/*.{tsx,jsx,ts,js,vue}`, { cwd: ROOT });
|
|
64
64
|
if (files.length > 0) {
|
|
65
65
|
const pages = files.filter(f => /page\.|index\./.test(f)).length;
|
|
66
66
|
const layouts = files.filter(f => /layout\./.test(f)).length;
|
|
@@ -81,7 +81,7 @@ async function scanFrontendDomains(stack, ROOT) {
|
|
|
81
81
|
for (const dir of fsdDirs) {
|
|
82
82
|
const name = path.basename(dir);
|
|
83
83
|
if (["ui", "common", "shared", "lib", "config", "index"].includes(name)) continue;
|
|
84
|
-
const files = await glob(`${dir}**/*.{tsx,jsx,ts,js,vue}`, { cwd: ROOT, ignore: ["**/*.spec.*", "**/*.test.*", "**/*.stories.*"] });
|
|
84
|
+
const files = await glob(`${dir.replace(/\\/g, "/")}**/*.{tsx,jsx,ts,js,vue}`, { cwd: ROOT, ignore: ["**/*.spec.*", "**/*.test.*", "**/*.stories.*"] });
|
|
85
85
|
if (files.length > 0) {
|
|
86
86
|
const uiFiles = files.filter(f => /\bui\b/.test(f)).length;
|
|
87
87
|
const modelFiles = files.filter(f => /model|store|hook/.test(f)).length;
|
|
@@ -95,7 +95,7 @@ async function scanFrontendDomains(stack, ROOT) {
|
|
|
95
95
|
for (const dir of compDirs) {
|
|
96
96
|
const name = path.basename(dir);
|
|
97
97
|
if (["ui", "common", "shared", "layout", "icons"].includes(name)) continue;
|
|
98
|
-
const files = await glob(`${dir}**/*.{tsx,jsx,vue}`, { cwd: ROOT });
|
|
98
|
+
const files = await glob(`${dir.replace(/\\/g, "/")}**/*.{tsx,jsx,vue}`, { cwd: ROOT });
|
|
99
99
|
if (files.length >= 2) {
|
|
100
100
|
frontendDomains.push({ name: `comp-${name}`, type: "frontend", components: files.length, totalFiles: files.length });
|
|
101
101
|
}
|
|
@@ -148,7 +148,12 @@ async function scanJavaDomains(stack, ROOT) {
|
|
|
148
148
|
dtoGlob = `src/main/java/**/dto/${cap}*.java`;
|
|
149
149
|
aggGlob = `src/main/java/**/aggregator/${cap}*.java`;
|
|
150
150
|
}
|
|
151
|
-
|
|
151
|
+
// Pattern C (flat): XML may be in flat directory without domain subdirectory (e.g., mapper/OrderMapper.xml)
|
|
152
|
+
// Other patterns: XML is in domain subdirectory (e.g., mapper/order/OrderMapper.xml)
|
|
153
|
+
const capDn = dn.charAt(0).toUpperCase() + dn.slice(1);
|
|
154
|
+
const xmlGlob = p === "C"
|
|
155
|
+
? `src/main/resources/{mapper,mybatis}/**/{${dn}/${capDn}*.xml,${capDn}*.xml}`
|
|
156
|
+
: `src/main/resources/{mapper,mybatis}/**/${dn}/*.xml`;
|
|
152
157
|
|
|
153
158
|
const svc = await glob(svcGlob, { cwd: ROOT });
|
|
154
159
|
const mpr = await glob(mprGlob, { cwd: ROOT });
|
|
@@ -115,6 +115,8 @@ async function detectStack(ROOT) {
|
|
|
115
115
|
if (jv) stack.languageVersion = jv[1];
|
|
116
116
|
|
|
117
117
|
detectFirst(stack, "orm", g, GRADLE_ORM_RULES);
|
|
118
|
+
// Exclude "postgres" (substring of postgresql — false positive on r2dbc-postgres) and "sqlite" (rare in Gradle deps)
|
|
119
|
+
// "postgresql" is still matched via DB_KEYWORD_RULES; h2 uses word-boundary check separately
|
|
118
120
|
detectDb(stack, g, DB_KEYWORD_RULES.filter(([kw]) => !["postgres", "sqlite"].includes(kw)));
|
|
119
121
|
|
|
120
122
|
// Kotlin detection: override language if Kotlin plugin found
|
package/plan-validator/index.js
CHANGED
|
@@ -247,7 +247,7 @@ async function main() {
|
|
|
247
247
|
const rp = path.join(GEN, "stale-report.json");
|
|
248
248
|
let ex = {};
|
|
249
249
|
if (fs.existsSync(rp)) {
|
|
250
|
-
try { ex = JSON.parse(fs.readFileSync(rp, "utf-8")); } catch { ex = {}; }
|
|
250
|
+
try { ex = JSON.parse(fs.readFileSync(rp, "utf-8")); } catch (_e) { ex = {}; }
|
|
251
251
|
}
|
|
252
252
|
ex.planValidation = { checkedAt: new Date().toISOString(), mode, total, synced, drift, missing };
|
|
253
253
|
if (!ex.summary) ex.summary = {};
|
package/sync-checker/index.js
CHANGED
|
@@ -109,7 +109,7 @@ async function main() {
|
|
|
109
109
|
const rp = path.join(GEN, "stale-report.json");
|
|
110
110
|
let ex = {};
|
|
111
111
|
if (fs.existsSync(rp)) {
|
|
112
|
-
try { ex = JSON.parse(fs.readFileSync(rp, "utf-8")); } catch { ex = {}; }
|
|
112
|
+
try { ex = JSON.parse(fs.readFileSync(rp, "utf-8")); } catch (_e) { ex = {}; }
|
|
113
113
|
}
|
|
114
114
|
ex.syncMisses = {
|
|
115
115
|
checkedAt: new Date().toISOString(),
|