claudeos-core 2.2.0 → 2.3.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +1649 -907
  2. package/CONTRIBUTING.md +92 -92
  3. package/README.de.md +32 -0
  4. package/README.es.md +32 -0
  5. package/README.fr.md +32 -0
  6. package/README.hi.md +32 -0
  7. package/README.ja.md +32 -0
  8. package/README.ko.md +1018 -986
  9. package/README.md +1020 -987
  10. package/README.ru.md +32 -0
  11. package/README.vi.md +1019 -987
  12. package/README.zh-CN.md +32 -0
  13. package/bin/cli.js +152 -148
  14. package/bin/commands/init.js +1673 -1554
  15. package/bin/commands/lint.js +62 -0
  16. package/bin/commands/memory.js +438 -438
  17. package/bin/lib/cli-utils.js +206 -206
  18. package/claude-md-validator/index.js +184 -0
  19. package/claude-md-validator/reporter.js +66 -0
  20. package/claude-md-validator/structural-checks.js +528 -0
  21. package/content-validator/index.js +666 -441
  22. package/lib/expected-guides.js +23 -23
  23. package/lib/expected-outputs.js +90 -90
  24. package/lib/language-config.js +35 -35
  25. package/lib/memory-scaffold.js +1058 -1054
  26. package/lib/plan-parser.js +165 -165
  27. package/lib/staged-rules.js +118 -118
  28. package/manifest-generator/index.js +174 -174
  29. package/package.json +90 -87
  30. package/pass-json-validator/index.js +337 -337
  31. package/pass-prompts/templates/common/claude-md-scaffold.md +52 -10
  32. package/pass-prompts/templates/common/pass3-footer.md +402 -224
  33. package/pass-prompts/templates/common/pass3b-core-header.md +43 -0
  34. package/pass-prompts/templates/common/pass4.md +375 -305
  35. package/pass-prompts/templates/common/staging-override.md +26 -26
  36. package/pass-prompts/templates/node-vite/pass1.md +117 -117
  37. package/pass-prompts/templates/node-vite/pass2.md +78 -78
  38. package/pass-prompts/templates/python-flask/pass1.md +119 -119
  39. package/pass-prompts/templates/python-flask/pass2.md +85 -85
  40. package/plan-installer/domain-grouper.js +76 -76
  41. package/plan-installer/index.js +137 -137
  42. package/plan-installer/prompt-generator.js +188 -145
  43. package/plan-installer/scanners/scan-frontend.js +505 -473
  44. package/plan-installer/scanners/scan-java.js +226 -226
  45. package/plan-installer/scanners/scan-node.js +57 -57
  46. package/plan-installer/scanners/scan-python.js +85 -85
  47. package/plan-installer/stack-detector.js +482 -482
  48. package/plan-installer/structure-scanner.js +65 -65
  49. package/sync-checker/index.js +177 -177
@@ -1,174 +1,174 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * ClaudeOS-Core — Manifest Generator
5
- *
6
- * Role: Generate metadata JSON + initialize stale-report
7
- * Output (claudeos-core/generated/):
8
- * - rule-manifest.json : rules/standard/skills/guide file list + frontmatter
9
- * - sync-map.json : plan/ <file> block → file path mapping (empty since
10
- * master plan generation was removed in v2.1.0;
11
- * kept for sync-checker backward compatibility)
12
- * - stale-report.json : initialized (each verification tool appends results)
13
- *
14
- * v2.1.0 removed plan-manifest.json generation (master plan aggregation gone).
15
- *
16
- * Usage: npx claudeos-core <cmd> or node claudeos-core-tools/manifest-generator/index.js
17
- */
18
-
19
- const fs = require("fs");
20
- const path = require("path");
21
- const matter = require("gray-matter");
22
- const { glob } = require("glob");
23
- const { parseFileBlocks, parseCodeBlocks, CODE_BLOCK_PLANS } = require("../lib/plan-parser");
24
- const { updateStaleReport } = require("../lib/stale-report");
25
-
26
- const ROOT = process.env.CLAUDEOS_ROOT || path.resolve(__dirname, "../..");
27
- const GEN = path.join(ROOT, "claudeos-core/generated");
28
-
29
- const DIRS = {
30
- rules: path.join(ROOT, ".claude/rules"),
31
- standard: path.join(ROOT, "claudeos-core/standard"),
32
- skills: path.join(ROOT, "claudeos-core/skills"),
33
- plan: path.join(ROOT, "claudeos-core/plan"),
34
- guide: path.join(ROOT, "claudeos-core/guide"),
35
- database: path.join(ROOT, "claudeos-core/database"),
36
- mcpGuide: path.join(ROOT, "claudeos-core/mcp-guide"),
37
- memory: path.join(ROOT, "claudeos-core/memory"),
38
- };
39
-
40
- function rel(p) {
41
- return path.relative(ROOT, p).replace(/\\/g, "/");
42
- }
43
-
44
- function stat(f) {
45
- try {
46
- const s = fs.statSync(f);
47
- const c = fs.readFileSync(f, "utf-8");
48
- return {
49
- lines: c.endsWith("\n") ? c.split("\n").length - 1 : c.split("\n").length,
50
- bytes: s.size,
51
- modified: s.mtime.toISOString().split("T")[0],
52
- };
53
- } catch (_e) {
54
- return { lines: 0, bytes: 0, modified: "unknown" };
55
- }
56
- }
57
-
58
- function frontmatter(f) {
59
- try {
60
- return matter(fs.readFileSync(f, "utf-8")).data || {};
61
- } catch (_e) {
62
- return {};
63
- }
64
- }
65
-
66
-
67
- // Wrappers: read file → parse → attach planFile metadata
68
- function extractFileBlocksFromFile(f) {
69
- if (!fs.existsSync(f)) return [];
70
- const content = fs.readFileSync(f, "utf-8");
71
- return parseFileBlocks(content).map(b => ({ sourcePath: b.path, planFile: rel(f) }));
72
- }
73
-
74
- function extractCodeBlockPathsFromFile(f) {
75
- if (!fs.existsSync(f)) return [];
76
- const content = fs.readFileSync(f, "utf-8");
77
- return parseCodeBlocks(content).map(b => ({ sourcePath: b.path, planFile: rel(f) }));
78
- }
79
-
80
- async function main() {
81
- console.log("\n╔═══════════════════════════════════════╗");
82
- console.log("║ ClaudeOS-Core — Manifest Generator ║");
83
- console.log("╚═══════════════════════════════════════╝\n");
84
-
85
- if (!fs.existsSync(GEN)) fs.mkdirSync(GEN, { recursive: true });
86
-
87
- // ─── rule-manifest.json ────────────────────────────────
88
- const mf = {
89
- generatedAt: new Date().toISOString(),
90
- rules: [], standards: [], skills: [], guides: [], database: [], mcpGuide: [],
91
- memory: [],
92
- };
93
-
94
- const scanTargets = [
95
- ["rules", DIRS.rules],
96
- ["standards", DIRS.standard],
97
- ["skills", DIRS.skills],
98
- ["guides", DIRS.guide],
99
- ["database", DIRS.database],
100
- ["mcpGuide", DIRS.mcpGuide],
101
- ["memory", DIRS.memory],
102
- ];
103
-
104
- for (const [key, dir] of scanTargets) {
105
- if (!fs.existsSync(dir)) continue;
106
- for (const f of await glob("**/*.md", { cwd: dir, absolute: true })) {
107
- const r = rel(f);
108
- const s = stat(f);
109
- const fm = frontmatter(f);
110
- mf[key].push({
111
- path: r,
112
- paths: fm.paths || undefined,
113
- name: fm.name || undefined,
114
- ...s,
115
- });
116
- }
117
- }
118
-
119
- mf.summary = {
120
- totalRules: mf.rules.length,
121
- totalStandards: mf.standards.length,
122
- totalSkills: mf.skills.length,
123
- totalGuides: mf.guides.length,
124
- totalDatabase: mf.database.length,
125
- totalMcpGuide: mf.mcpGuide.length,
126
- totalMemory: mf.memory.length,
127
- total: mf.rules.length + mf.standards.length + mf.skills.length +
128
- mf.guides.length + mf.database.length + mf.mcpGuide.length +
129
- mf.memory.length,
130
- };
131
- fs.writeFileSync(path.join(GEN, "rule-manifest.json"), JSON.stringify(mf, null, 2));
132
- console.log(` ✅ rule-manifest.json — ${mf.summary.total} files indexed`);
133
-
134
- // import-graph.json removed — @import was never a Claude Code feature
135
-
136
- // ─── sync-map.json ─────────────────────────────────────
137
- // Master plan aggregation was removed in v2.1.0 (plan/ directory is no longer
138
- // populated). sync-map.json is still produced with an empty `mappings` array
139
- // for sync-checker backward compatibility — sync-checker treats an empty map
140
- // as "nothing to sync" and exits cleanly (see master-plan-removal tests).
141
- // CODE_BLOCK_PLANS imported from lib/plan-parser.js
142
- const sm = { generatedAt: new Date().toISOString(), mappings: [] };
143
- if (fs.existsSync(DIRS.plan)) {
144
- for (const p of await glob("*.md", { cwd: DIRS.plan, absolute: true })) {
145
- const bn = path.basename(p);
146
- if (CODE_BLOCK_PLANS.includes(bn)) {
147
- sm.mappings.push(...extractCodeBlockPathsFromFile(p));
148
- } else {
149
- sm.mappings.push(...extractFileBlocksFromFile(p));
150
- }
151
- }
152
- }
153
- sm.summary = { totalMappings: sm.mappings.length };
154
- fs.writeFileSync(path.join(GEN, "sync-map.json"), JSON.stringify(sm, null, 2));
155
- console.log(` ✅ sync-map.json — ${sm.summary.totalMappings} mappings`);
156
-
157
- // ─── plan-manifest.json ─ REMOVED in v2.1.0 ─────────────
158
- // Master plan generation was removed; a plan-manifest with an empty plans
159
- // array is noise — nothing reads it, nothing validates it. The two-file
160
- // stale output (62 B plan-manifest + 147 B plan-sync-status) was removed
161
- // to match the declared v2.1.0 contract "plan/ directory is no longer
162
- // created during init".
163
-
164
- // ─── Initialize stale-report.json (preserve existing sub-tool results) ──
165
- updateStaleReport(GEN, "generatedAt", new Date().toISOString(), { totalIssues: 0, status: "initial" });
166
- console.log(" ✅ stale-report.json — initialized");
167
- console.log("\n 📁 Output: claudeos-core/generated/ (3 files)\n");
168
- }
169
-
170
- if (require.main === module) {
171
- main().catch(e => { console.error(`\n ❌ Manifest Generator failed: ${e.message || e}`); process.exit(1); });
172
- }
173
-
174
- module.exports = { main };
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * ClaudeOS-Core — Manifest Generator
5
+ *
6
+ * Role: Generate metadata JSON + initialize stale-report
7
+ * Output (claudeos-core/generated/):
8
+ * - rule-manifest.json : rules/standard/skills/guide file list + frontmatter
9
+ * - sync-map.json : plan/ <file> block → file path mapping (empty since
10
+ * master plan generation was removed in v2.1.0;
11
+ * kept for sync-checker backward compatibility)
12
+ * - stale-report.json : initialized (each verification tool appends results)
13
+ *
14
+ * v2.1.0 removed plan-manifest.json generation (master plan aggregation gone).
15
+ *
16
+ * Usage: npx claudeos-core <cmd> or node claudeos-core-tools/manifest-generator/index.js
17
+ */
18
+
19
+ const fs = require("fs");
20
+ const path = require("path");
21
+ const matter = require("gray-matter");
22
+ const { glob } = require("glob");
23
+ const { parseFileBlocks, parseCodeBlocks, CODE_BLOCK_PLANS } = require("../lib/plan-parser");
24
+ const { updateStaleReport } = require("../lib/stale-report");
25
+
26
+ const ROOT = process.env.CLAUDEOS_ROOT || path.resolve(__dirname, "../..");
27
+ const GEN = path.join(ROOT, "claudeos-core/generated");
28
+
29
+ const DIRS = {
30
+ rules: path.join(ROOT, ".claude/rules"),
31
+ standard: path.join(ROOT, "claudeos-core/standard"),
32
+ skills: path.join(ROOT, "claudeos-core/skills"),
33
+ plan: path.join(ROOT, "claudeos-core/plan"),
34
+ guide: path.join(ROOT, "claudeos-core/guide"),
35
+ database: path.join(ROOT, "claudeos-core/database"),
36
+ mcpGuide: path.join(ROOT, "claudeos-core/mcp-guide"),
37
+ memory: path.join(ROOT, "claudeos-core/memory"),
38
+ };
39
+
40
+ function rel(p) {
41
+ return path.relative(ROOT, p).replace(/\\/g, "/");
42
+ }
43
+
44
+ function stat(f) {
45
+ try {
46
+ const s = fs.statSync(f);
47
+ const c = fs.readFileSync(f, "utf-8");
48
+ return {
49
+ lines: c.endsWith("\n") ? c.split("\n").length - 1 : c.split("\n").length,
50
+ bytes: s.size,
51
+ modified: s.mtime.toISOString().split("T")[0],
52
+ };
53
+ } catch (_e) {
54
+ return { lines: 0, bytes: 0, modified: "unknown" };
55
+ }
56
+ }
57
+
58
+ function frontmatter(f) {
59
+ try {
60
+ return matter(fs.readFileSync(f, "utf-8")).data || {};
61
+ } catch (_e) {
62
+ return {};
63
+ }
64
+ }
65
+
66
+
67
+ // Wrappers: read file → parse → attach planFile metadata
68
+ function extractFileBlocksFromFile(f) {
69
+ if (!fs.existsSync(f)) return [];
70
+ const content = fs.readFileSync(f, "utf-8");
71
+ return parseFileBlocks(content).map(b => ({ sourcePath: b.path, planFile: rel(f) }));
72
+ }
73
+
74
+ function extractCodeBlockPathsFromFile(f) {
75
+ if (!fs.existsSync(f)) return [];
76
+ const content = fs.readFileSync(f, "utf-8");
77
+ return parseCodeBlocks(content).map(b => ({ sourcePath: b.path, planFile: rel(f) }));
78
+ }
79
+
80
+ async function main() {
81
+ console.log("\n╔═══════════════════════════════════════╗");
82
+ console.log("║ ClaudeOS-Core — Manifest Generator ║");
83
+ console.log("╚═══════════════════════════════════════╝\n");
84
+
85
+ if (!fs.existsSync(GEN)) fs.mkdirSync(GEN, { recursive: true });
86
+
87
+ // ─── rule-manifest.json ────────────────────────────────
88
+ const mf = {
89
+ generatedAt: new Date().toISOString(),
90
+ rules: [], standards: [], skills: [], guides: [], database: [], mcpGuide: [],
91
+ memory: [],
92
+ };
93
+
94
+ const scanTargets = [
95
+ ["rules", DIRS.rules],
96
+ ["standards", DIRS.standard],
97
+ ["skills", DIRS.skills],
98
+ ["guides", DIRS.guide],
99
+ ["database", DIRS.database],
100
+ ["mcpGuide", DIRS.mcpGuide],
101
+ ["memory", DIRS.memory],
102
+ ];
103
+
104
+ for (const [key, dir] of scanTargets) {
105
+ if (!fs.existsSync(dir)) continue;
106
+ for (const f of await glob("**/*.md", { cwd: dir, absolute: true })) {
107
+ const r = rel(f);
108
+ const s = stat(f);
109
+ const fm = frontmatter(f);
110
+ mf[key].push({
111
+ path: r,
112
+ paths: fm.paths || undefined,
113
+ name: fm.name || undefined,
114
+ ...s,
115
+ });
116
+ }
117
+ }
118
+
119
+ mf.summary = {
120
+ totalRules: mf.rules.length,
121
+ totalStandards: mf.standards.length,
122
+ totalSkills: mf.skills.length,
123
+ totalGuides: mf.guides.length,
124
+ totalDatabase: mf.database.length,
125
+ totalMcpGuide: mf.mcpGuide.length,
126
+ totalMemory: mf.memory.length,
127
+ total: mf.rules.length + mf.standards.length + mf.skills.length +
128
+ mf.guides.length + mf.database.length + mf.mcpGuide.length +
129
+ mf.memory.length,
130
+ };
131
+ fs.writeFileSync(path.join(GEN, "rule-manifest.json"), JSON.stringify(mf, null, 2));
132
+ console.log(` ✅ rule-manifest.json — ${mf.summary.total} files indexed`);
133
+
134
+ // import-graph.json removed — @import was never a Claude Code feature
135
+
136
+ // ─── sync-map.json ─────────────────────────────────────
137
+ // Master plan aggregation was removed in v2.1.0 (plan/ directory is no longer
138
+ // populated). sync-map.json is still produced with an empty `mappings` array
139
+ // for sync-checker backward compatibility — sync-checker treats an empty map
140
+ // as "nothing to sync" and exits cleanly (see master-plan-removal tests).
141
+ // CODE_BLOCK_PLANS imported from lib/plan-parser.js
142
+ const sm = { generatedAt: new Date().toISOString(), mappings: [] };
143
+ if (fs.existsSync(DIRS.plan)) {
144
+ for (const p of await glob("*.md", { cwd: DIRS.plan, absolute: true })) {
145
+ const bn = path.basename(p);
146
+ if (CODE_BLOCK_PLANS.includes(bn)) {
147
+ sm.mappings.push(...extractCodeBlockPathsFromFile(p));
148
+ } else {
149
+ sm.mappings.push(...extractFileBlocksFromFile(p));
150
+ }
151
+ }
152
+ }
153
+ sm.summary = { totalMappings: sm.mappings.length };
154
+ fs.writeFileSync(path.join(GEN, "sync-map.json"), JSON.stringify(sm, null, 2));
155
+ console.log(` ✅ sync-map.json — ${sm.summary.totalMappings} mappings`);
156
+
157
+ // ─── plan-manifest.json ─ REMOVED in v2.1.0 ─────────────
158
+ // Master plan generation was removed; a plan-manifest with an empty plans
159
+ // array is noise — nothing reads it, nothing validates it. The two-file
160
+ // stale output (62 B plan-manifest + 147 B plan-sync-status) was removed
161
+ // to match the declared v2.1.0 contract "plan/ directory is no longer
162
+ // created during init".
163
+
164
+ // ─── Initialize stale-report.json (preserve existing sub-tool results) ──
165
+ updateStaleReport(GEN, "generatedAt", new Date().toISOString(), { totalIssues: 0, status: "initial" });
166
+ console.log(" ✅ stale-report.json — initialized");
167
+ console.log("\n 📁 Output: claudeos-core/generated/ (3 files)\n");
168
+ }
169
+
170
+ if (require.main === module) {
171
+ main().catch(e => { console.error(`\n ❌ Manifest Generator failed: ${e.message || e}`); process.exit(1); });
172
+ }
173
+
174
+ module.exports = { main };
package/package.json CHANGED
@@ -1,87 +1,90 @@
1
- {
2
- "name": "claudeos-core",
3
- "version": "2.2.0",
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",
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": "2.3.0",
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
+ "claude-md-validator/",
13
+ "content-validator/",
14
+ "health-checker/",
15
+ "manifest-generator/",
16
+ "pass-json-validator/",
17
+ "pass-prompts/",
18
+ "plan-installer/",
19
+ "plan-validator/",
20
+ "sync-checker/",
21
+ "bootstrap.sh",
22
+ "README.md",
23
+ "README.ko.md",
24
+ "LICENSE",
25
+ "CHANGELOG.md",
26
+ "CONTRIBUTING.md",
27
+ "README.zh-CN.md",
28
+ "README.ja.md",
29
+ "README.es.md",
30
+ "README.vi.md",
31
+ "README.hi.md",
32
+ "README.ru.md",
33
+ "README.fr.md",
34
+ "README.de.md"
35
+ ],
36
+ "scripts": {
37
+ "init": "node bin/cli.js init",
38
+ "lint": "node bin/cli.js lint",
39
+ "health": "node bin/cli.js health",
40
+ "validate": "node bin/cli.js validate",
41
+ "refresh": "node bin/cli.js refresh",
42
+ "restore": "node bin/cli.js restore",
43
+ "pretest": "node -e \"require('glob')\" 2>/dev/null || npm install",
44
+ "test": "node --test tests/*.test.js",
45
+ "test:health": "node health-checker/index.js"
46
+ },
47
+ "keywords": [
48
+ "claude-code",
49
+ "automation",
50
+ "code-analysis",
51
+ "CLAUDE.md",
52
+ "standards",
53
+ "rules",
54
+ "skills",
55
+ "scaffolding",
56
+ "i18n",
57
+ "multi-language",
58
+ "spring-boot",
59
+ "kotlin",
60
+ "exposed",
61
+ "jooq",
62
+ "cqrs",
63
+ "bff",
64
+ "multi-module",
65
+ "monorepo",
66
+ "nextjs",
67
+ "express",
68
+ "fastify",
69
+ "angular",
70
+ "django",
71
+ "fastapi"
72
+ ],
73
+ "author": "claudeos-core <claudeoscore@gmail.com> (https://github.com/claudeos-core)",
74
+ "license": "ISC",
75
+ "repository": {
76
+ "type": "git",
77
+ "url": "git+https://github.com/claudeos-core/claudeos-core.git"
78
+ },
79
+ "homepage": "https://github.com/claudeos-core/claudeos-core#readme",
80
+ "bugs": {
81
+ "url": "https://github.com/claudeos-core/claudeos-core/issues"
82
+ },
83
+ "engines": {
84
+ "node": ">=18.0.0"
85
+ },
86
+ "dependencies": {
87
+ "glob": "^13.0.6",
88
+ "gray-matter": "^4.0.3"
89
+ }
90
+ }