@weavelogic/knowledge-graph-agent 0.1.0 → 0.2.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.
- package/README.md +203 -4
- package/dist/cli/commands/analyze.d.ts +12 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/analyze.js +269 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/convert.d.ts +15 -0
- package/dist/cli/commands/convert.d.ts.map +1 -0
- package/dist/cli/commands/convert.js +203 -0
- package/dist/cli/commands/convert.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +13 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/generators/docs-analyzer.d.ts +75 -0
- package/dist/generators/docs-analyzer.d.ts.map +1 -0
- package/dist/generators/docs-analyzer.js +567 -0
- package/dist/generators/docs-analyzer.js.map +1 -0
- package/dist/generators/docs-convert.d.ts +91 -0
- package/dist/generators/docs-convert.d.ts.map +1 -0
- package/dist/generators/docs-convert.js +474 -0
- package/dist/generators/docs-convert.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync } from "fs";
|
|
2
|
+
import { join, dirname, basename } from "path";
|
|
3
|
+
import fg from "fast-glob";
|
|
4
|
+
import matter from "gray-matter";
|
|
5
|
+
const CATEGORY_STRUCTURE = {
|
|
6
|
+
concepts: {
|
|
7
|
+
type: "concept",
|
|
8
|
+
description: "Abstract concepts, theories, and architectural principles",
|
|
9
|
+
subcategories: ["architecture", "patterns", "principles", "models"]
|
|
10
|
+
},
|
|
11
|
+
components: {
|
|
12
|
+
type: "technical",
|
|
13
|
+
description: "Reusable technical components and implementations",
|
|
14
|
+
subcategories: ["ui", "utilities", "core", "shared"]
|
|
15
|
+
},
|
|
16
|
+
services: {
|
|
17
|
+
type: "service",
|
|
18
|
+
description: "Backend services, APIs, and workers",
|
|
19
|
+
subcategories: ["api", "workers", "handlers", "middleware"]
|
|
20
|
+
},
|
|
21
|
+
features: {
|
|
22
|
+
type: "feature",
|
|
23
|
+
description: "Product features and capabilities",
|
|
24
|
+
subcategories: ["core", "advanced", "experimental"]
|
|
25
|
+
},
|
|
26
|
+
integrations: {
|
|
27
|
+
type: "integration",
|
|
28
|
+
description: "External integrations and adapters",
|
|
29
|
+
subcategories: ["databases", "auth", "storage", "monitoring", "third-party"]
|
|
30
|
+
},
|
|
31
|
+
standards: {
|
|
32
|
+
type: "standard",
|
|
33
|
+
description: "Coding standards, conventions, and best practices",
|
|
34
|
+
subcategories: ["coding", "documentation", "testing", "security"]
|
|
35
|
+
},
|
|
36
|
+
guides: {
|
|
37
|
+
type: "guide",
|
|
38
|
+
description: "How-to guides and tutorials",
|
|
39
|
+
subcategories: ["getting-started", "tutorials", "troubleshooting", "deployment"]
|
|
40
|
+
},
|
|
41
|
+
references: {
|
|
42
|
+
type: "technical",
|
|
43
|
+
description: "API references and technical documentation",
|
|
44
|
+
subcategories: ["api", "cli", "config", "schemas"]
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
async function analyzeDocs(options) {
|
|
48
|
+
const {
|
|
49
|
+
sourceDir,
|
|
50
|
+
targetDir = "docs-nn",
|
|
51
|
+
projectRoot,
|
|
52
|
+
useClaudeFlow = false,
|
|
53
|
+
createMOC = true,
|
|
54
|
+
linkOriginal = true,
|
|
55
|
+
maxDepth = 3,
|
|
56
|
+
dryRun = false,
|
|
57
|
+
verbose = false
|
|
58
|
+
} = options;
|
|
59
|
+
const result = {
|
|
60
|
+
success: true,
|
|
61
|
+
filesAnalyzed: 0,
|
|
62
|
+
filesCreated: 0,
|
|
63
|
+
mocFilesCreated: 0,
|
|
64
|
+
errors: [],
|
|
65
|
+
analyzed: [],
|
|
66
|
+
structure: /* @__PURE__ */ new Map()
|
|
67
|
+
};
|
|
68
|
+
const sourcePath = join(projectRoot, sourceDir);
|
|
69
|
+
const targetPath = join(projectRoot, targetDir);
|
|
70
|
+
if (!existsSync(sourcePath)) {
|
|
71
|
+
result.success = false;
|
|
72
|
+
result.errors.push(`Source directory not found: ${sourcePath}`);
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
if (!dryRun) {
|
|
76
|
+
createFullStructure(targetPath);
|
|
77
|
+
}
|
|
78
|
+
const files = await fg("**/*.md", {
|
|
79
|
+
cwd: sourcePath,
|
|
80
|
+
ignore: ["node_modules/**", ".git/**", "_templates/**", "docs-nn/**"]
|
|
81
|
+
});
|
|
82
|
+
const analyzedDocs = [];
|
|
83
|
+
for (const file of files) {
|
|
84
|
+
result.filesAnalyzed++;
|
|
85
|
+
const sourceFile = join(sourcePath, file);
|
|
86
|
+
try {
|
|
87
|
+
const analyzed = await analyzeDocument(sourceFile, file, sourcePath, {
|
|
88
|
+
useClaudeFlow,
|
|
89
|
+
linkOriginal,
|
|
90
|
+
verbose
|
|
91
|
+
});
|
|
92
|
+
analyzedDocs.push(analyzed);
|
|
93
|
+
const category = analyzed.category.split("/")[0];
|
|
94
|
+
if (!result.structure.has(category)) {
|
|
95
|
+
result.structure.set(category, []);
|
|
96
|
+
}
|
|
97
|
+
result.structure.get(category).push(analyzed.title);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
result.errors.push(`Failed to analyze ${file}: ${error}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
buildCrossReferences(analyzedDocs);
|
|
103
|
+
for (const doc of analyzedDocs) {
|
|
104
|
+
try {
|
|
105
|
+
const targetFile = join(targetPath, doc.newPath);
|
|
106
|
+
if (!dryRun) {
|
|
107
|
+
mkdirSync(dirname(targetFile), { recursive: true });
|
|
108
|
+
const content = generateKnowledgeDoc(doc, sourceDir, linkOriginal, analyzedDocs);
|
|
109
|
+
writeFileSync(targetFile, content, "utf-8");
|
|
110
|
+
}
|
|
111
|
+
result.filesCreated++;
|
|
112
|
+
result.analyzed.push(doc);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
result.errors.push(`Failed to create ${doc.newPath}: ${error}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (createMOC && !dryRun) {
|
|
118
|
+
for (const [category, docs] of result.structure) {
|
|
119
|
+
const mocPath = join(targetPath, category, "_MOC.md");
|
|
120
|
+
const mocContent = generateMOC(category, docs, analyzedDocs);
|
|
121
|
+
writeFileSync(mocPath, mocContent, "utf-8");
|
|
122
|
+
result.mocFilesCreated++;
|
|
123
|
+
}
|
|
124
|
+
const masterMocPath = join(targetPath, "MOC.md");
|
|
125
|
+
const masterMocContent = generateMasterMOC(result.structure, analyzedDocs);
|
|
126
|
+
writeFileSync(masterMocPath, masterMocContent, "utf-8");
|
|
127
|
+
result.mocFilesCreated++;
|
|
128
|
+
const primitivesPath = join(targetPath, "PRIMITIVES.md");
|
|
129
|
+
const primitivesContent = generatePrimitives(analyzedDocs);
|
|
130
|
+
writeFileSync(primitivesPath, primitivesContent, "utf-8");
|
|
131
|
+
}
|
|
132
|
+
result.success = result.errors.length === 0;
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
async function analyzeDocument(filePath, relativePath, sourcePath, options) {
|
|
136
|
+
const content = readFileSync(filePath, "utf-8");
|
|
137
|
+
const { data: existingFrontmatter, content: body } = matter(content);
|
|
138
|
+
const filename = basename(filePath, ".md");
|
|
139
|
+
const title = existingFrontmatter.title || formatTitle(filename);
|
|
140
|
+
const { type, category } = detectTypeAndCategory(relativePath, body, existingFrontmatter);
|
|
141
|
+
const tags = extractAllTags(body, existingFrontmatter, relativePath);
|
|
142
|
+
const related = extractLinks(body);
|
|
143
|
+
const concepts = extractConcepts(body);
|
|
144
|
+
const researchNeeded = findResearchAreas(body);
|
|
145
|
+
const todos = extractAndGenerateTodos(body, content);
|
|
146
|
+
const summary = generateSummary(body, existingFrontmatter);
|
|
147
|
+
const newPath = join(category, formatFilename(filename) + ".md");
|
|
148
|
+
return {
|
|
149
|
+
originalPath: relativePath,
|
|
150
|
+
newPath,
|
|
151
|
+
title,
|
|
152
|
+
type,
|
|
153
|
+
tags,
|
|
154
|
+
related,
|
|
155
|
+
concepts,
|
|
156
|
+
researchNeeded,
|
|
157
|
+
todos,
|
|
158
|
+
summary,
|
|
159
|
+
category
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function createFullStructure(targetPath) {
|
|
163
|
+
for (const [category, config] of Object.entries(CATEGORY_STRUCTURE)) {
|
|
164
|
+
mkdirSync(join(targetPath, category), { recursive: true });
|
|
165
|
+
for (const sub of config.subcategories) {
|
|
166
|
+
mkdirSync(join(targetPath, category, sub), { recursive: true });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
mkdirSync(join(targetPath, "_templates"), { recursive: true });
|
|
170
|
+
mkdirSync(join(targetPath, "_attachments"), { recursive: true });
|
|
171
|
+
mkdirSync(join(targetPath, "_archive"), { recursive: true });
|
|
172
|
+
}
|
|
173
|
+
function detectTypeAndCategory(filePath, content, frontmatter) {
|
|
174
|
+
if (frontmatter.type && frontmatter.category) {
|
|
175
|
+
return {
|
|
176
|
+
type: frontmatter.type,
|
|
177
|
+
category: frontmatter.category
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
content.toLowerCase();
|
|
181
|
+
const lowerPath = filePath.toLowerCase();
|
|
182
|
+
const scores = {};
|
|
183
|
+
for (const [category, config] of Object.entries(CATEGORY_STRUCTURE)) {
|
|
184
|
+
scores[category] = 0;
|
|
185
|
+
if (lowerPath.includes(category)) scores[category] += 10;
|
|
186
|
+
for (const sub of config.subcategories) {
|
|
187
|
+
if (lowerPath.includes(sub)) scores[category] += 5;
|
|
188
|
+
}
|
|
189
|
+
const keywords = getKeywordsForType(config.type);
|
|
190
|
+
for (const keyword of keywords) {
|
|
191
|
+
const regex = new RegExp(`\\b${keyword}\\b`, "gi");
|
|
192
|
+
const matches = content.match(regex);
|
|
193
|
+
if (matches) scores[category] += matches.length;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
let bestCategory = "concepts";
|
|
197
|
+
let bestScore = 0;
|
|
198
|
+
for (const [category, score] of Object.entries(scores)) {
|
|
199
|
+
if (score > bestScore) {
|
|
200
|
+
bestScore = score;
|
|
201
|
+
bestCategory = category;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
type: CATEGORY_STRUCTURE[bestCategory].type,
|
|
206
|
+
category: bestCategory
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function getKeywordsForType(type) {
|
|
210
|
+
const keywords = {
|
|
211
|
+
concept: ["concept", "theory", "principle", "overview", "introduction", "architecture", "design", "pattern"],
|
|
212
|
+
technical: ["component", "implementation", "class", "function", "module", "utility", "helper"],
|
|
213
|
+
feature: ["feature", "capability", "functionality", "user", "requirement", "use case"],
|
|
214
|
+
primitive: ["library", "framework", "dependency", "tool", "sdk"],
|
|
215
|
+
service: ["api", "endpoint", "service", "server", "backend", "worker", "handler"],
|
|
216
|
+
guide: ["how to", "tutorial", "guide", "step", "walkthrough", "getting started"],
|
|
217
|
+
standard: ["standard", "convention", "best practice", "rule", "guideline", "style"],
|
|
218
|
+
integration: ["integration", "connect", "plugin", "adapter", "sync", "import", "export"]
|
|
219
|
+
};
|
|
220
|
+
return keywords[type] || [];
|
|
221
|
+
}
|
|
222
|
+
function extractAllTags(content, frontmatter, filePath) {
|
|
223
|
+
const tags = /* @__PURE__ */ new Set();
|
|
224
|
+
if (Array.isArray(frontmatter.tags)) {
|
|
225
|
+
frontmatter.tags.forEach((t) => tags.add(String(t)));
|
|
226
|
+
}
|
|
227
|
+
const hashTags = content.match(/#[\w-]+/g);
|
|
228
|
+
if (hashTags) {
|
|
229
|
+
hashTags.forEach((t) => tags.add(t.slice(1)));
|
|
230
|
+
}
|
|
231
|
+
const pathParts = filePath.split("/").filter((p) => p && !p.endsWith(".md"));
|
|
232
|
+
pathParts.forEach((p) => {
|
|
233
|
+
if (p.length > 2 && p.length < 20) {
|
|
234
|
+
tags.add(p.replace(/[-_]/g, "-").toLowerCase());
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
if (content.match(/\b(wip|draft|todo)\b/i)) tags.add("needs-work");
|
|
238
|
+
if (content.match(/\b(deprecated|legacy)\b/i)) tags.add("deprecated");
|
|
239
|
+
if (content.match(/\b(experimental|beta)\b/i)) tags.add("experimental");
|
|
240
|
+
return [...tags].slice(0, 15);
|
|
241
|
+
}
|
|
242
|
+
function extractLinks(content) {
|
|
243
|
+
const links = /* @__PURE__ */ new Set();
|
|
244
|
+
const wikilinks = content.match(/\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g);
|
|
245
|
+
if (wikilinks) {
|
|
246
|
+
wikilinks.forEach((link) => {
|
|
247
|
+
const match = link.match(/\[\[([^\]|]+)/);
|
|
248
|
+
if (match) links.add(match[1].trim());
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
const mdLinks = content.match(/\[([^\]]+)\]\(([^)]+)\)/g);
|
|
252
|
+
if (mdLinks) {
|
|
253
|
+
mdLinks.forEach((link) => {
|
|
254
|
+
const match = link.match(/\]\(([^)]+)\)/);
|
|
255
|
+
if (match && !match[1].startsWith("http")) {
|
|
256
|
+
links.add(match[1].replace(/\.md$/, "").trim());
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
return [...links];
|
|
261
|
+
}
|
|
262
|
+
function extractConcepts(content) {
|
|
263
|
+
const concepts = [];
|
|
264
|
+
const headers = content.match(/^##\s+(.+)$/gm);
|
|
265
|
+
if (headers) {
|
|
266
|
+
headers.slice(0, 5).forEach((h) => {
|
|
267
|
+
concepts.push(h.replace(/^##\s+/, "").trim());
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
const boldTerms = content.match(/\*\*([^*]+)\*\*/g);
|
|
271
|
+
if (boldTerms) {
|
|
272
|
+
boldTerms.slice(0, 5).forEach((term) => {
|
|
273
|
+
const clean = term.replace(/\*\*/g, "").trim();
|
|
274
|
+
if (clean.length > 2 && clean.length < 50) {
|
|
275
|
+
concepts.push(clean);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
return [...new Set(concepts)].slice(0, 10);
|
|
280
|
+
}
|
|
281
|
+
function findResearchAreas(content, filename) {
|
|
282
|
+
const areas = [];
|
|
283
|
+
const questions = content.match(/[^.!?]*\?/g);
|
|
284
|
+
if (questions) {
|
|
285
|
+
questions.slice(0, 3).forEach((q) => {
|
|
286
|
+
if (q.length > 10 && q.length < 200) {
|
|
287
|
+
areas.push(q.trim());
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
if (content.match(/\bTBD\b|\bTODO\b|\bFIXME\b/i)) {
|
|
292
|
+
areas.push("Contains placeholders that need completion");
|
|
293
|
+
}
|
|
294
|
+
const emptyHeaders = content.match(/^##[^#\n]+\n\n##/gm);
|
|
295
|
+
if (emptyHeaders) {
|
|
296
|
+
areas.push("Has empty sections that need content");
|
|
297
|
+
}
|
|
298
|
+
if (content.length < 500) {
|
|
299
|
+
areas.push("Document is short - may need expansion");
|
|
300
|
+
}
|
|
301
|
+
return areas;
|
|
302
|
+
}
|
|
303
|
+
function extractAndGenerateTodos(body, fullContent, filename) {
|
|
304
|
+
const todos = [];
|
|
305
|
+
const existingTodos = fullContent.match(/[-*]\s*\[[ x]\]\s*(.+)/g);
|
|
306
|
+
if (existingTodos) {
|
|
307
|
+
existingTodos.forEach((todo) => {
|
|
308
|
+
todos.push(todo.replace(/^[-*]\s*\[[ x]\]\s*/, "").trim());
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
const todoComments = fullContent.match(/(?:TODO|FIXME|XXX):\s*(.+)/gi);
|
|
312
|
+
if (todoComments) {
|
|
313
|
+
todoComments.forEach((todo) => {
|
|
314
|
+
todos.push(todo.replace(/^(?:TODO|FIXME|XXX):\s*/i, "").trim());
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
if (!fullContent.match(/^---[\s\S]*?---/)) {
|
|
318
|
+
todos.push("Add proper frontmatter");
|
|
319
|
+
}
|
|
320
|
+
if (!fullContent.match(/\[\[/)) {
|
|
321
|
+
todos.push("Add wikilinks to related documents");
|
|
322
|
+
}
|
|
323
|
+
if (!fullContent.match(/^##\s/m)) {
|
|
324
|
+
todos.push("Add section structure with headers");
|
|
325
|
+
}
|
|
326
|
+
return [...new Set(todos)].slice(0, 10);
|
|
327
|
+
}
|
|
328
|
+
function generateSummary(body, frontmatter) {
|
|
329
|
+
if (frontmatter.description) {
|
|
330
|
+
return String(frontmatter.description);
|
|
331
|
+
}
|
|
332
|
+
const lines = body.split("\n");
|
|
333
|
+
for (const line of lines) {
|
|
334
|
+
const trimmed = line.trim();
|
|
335
|
+
if (trimmed && !trimmed.startsWith("#") && !trimmed.startsWith("```") && trimmed.length > 30) {
|
|
336
|
+
return trimmed.length > 200 ? trimmed.slice(0, 197) + "..." : trimmed;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return "Documentation requiring summary.";
|
|
340
|
+
}
|
|
341
|
+
function buildCrossReferences(docs) {
|
|
342
|
+
const titleMap = /* @__PURE__ */ new Map();
|
|
343
|
+
docs.forEach((doc) => {
|
|
344
|
+
titleMap.set(doc.title.toLowerCase(), doc);
|
|
345
|
+
titleMap.set(formatFilename(doc.title), doc);
|
|
346
|
+
});
|
|
347
|
+
docs.forEach((doc) => {
|
|
348
|
+
const newRelated = [];
|
|
349
|
+
doc.related.forEach((link) => {
|
|
350
|
+
const linkedDoc = titleMap.get(link.toLowerCase()) || titleMap.get(formatFilename(link));
|
|
351
|
+
if (linkedDoc) {
|
|
352
|
+
newRelated.push(linkedDoc.title);
|
|
353
|
+
} else {
|
|
354
|
+
newRelated.push(link);
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
const sharedTagDocs = docs.filter(
|
|
358
|
+
(other) => other !== doc && other.tags.some((t) => doc.tags.includes(t))
|
|
359
|
+
);
|
|
360
|
+
sharedTagDocs.slice(0, 3).forEach((other) => {
|
|
361
|
+
if (!newRelated.includes(other.title)) {
|
|
362
|
+
newRelated.push(other.title);
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
doc.related = [...new Set(newRelated)].slice(0, 10);
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
function generateKnowledgeDoc(doc, sourceDir, linkOriginal, allDocs) {
|
|
369
|
+
const lines = [];
|
|
370
|
+
lines.push("---");
|
|
371
|
+
lines.push(`title: "${doc.title}"`);
|
|
372
|
+
lines.push(`type: ${doc.type}`);
|
|
373
|
+
lines.push(`status: active`);
|
|
374
|
+
if (doc.tags.length > 0) {
|
|
375
|
+
lines.push("tags:");
|
|
376
|
+
doc.tags.forEach((tag) => lines.push(` - ${tag}`));
|
|
377
|
+
}
|
|
378
|
+
lines.push(`category: ${doc.category}`);
|
|
379
|
+
lines.push(`description: "${doc.summary.replace(/"/g, '\\"')}"`);
|
|
380
|
+
lines.push(`created: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`);
|
|
381
|
+
lines.push(`updated: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`);
|
|
382
|
+
if (linkOriginal) {
|
|
383
|
+
lines.push(`original: "${sourceDir}/${doc.originalPath}"`);
|
|
384
|
+
}
|
|
385
|
+
if (doc.related.length > 0) {
|
|
386
|
+
lines.push("related:");
|
|
387
|
+
doc.related.slice(0, 5).forEach((r) => lines.push(` - "[[${r}]]"`));
|
|
388
|
+
}
|
|
389
|
+
lines.push("---");
|
|
390
|
+
lines.push("");
|
|
391
|
+
lines.push(`# ${doc.title}`);
|
|
392
|
+
lines.push("");
|
|
393
|
+
lines.push("## Overview");
|
|
394
|
+
lines.push("");
|
|
395
|
+
lines.push(doc.summary);
|
|
396
|
+
lines.push("");
|
|
397
|
+
if (linkOriginal) {
|
|
398
|
+
lines.push(`> [!info] Original Documentation`);
|
|
399
|
+
lines.push(`> See [[${sourceDir}/${doc.originalPath}|original document]] for full details.`);
|
|
400
|
+
lines.push("");
|
|
401
|
+
}
|
|
402
|
+
if (doc.concepts.length > 0) {
|
|
403
|
+
lines.push("## Key Concepts");
|
|
404
|
+
lines.push("");
|
|
405
|
+
doc.concepts.forEach((concept) => {
|
|
406
|
+
lines.push(`- **${concept}**`);
|
|
407
|
+
});
|
|
408
|
+
lines.push("");
|
|
409
|
+
}
|
|
410
|
+
if (doc.related.length > 0) {
|
|
411
|
+
lines.push("## Related");
|
|
412
|
+
lines.push("");
|
|
413
|
+
doc.related.forEach((rel) => {
|
|
414
|
+
lines.push(`- [[${rel}]]`);
|
|
415
|
+
});
|
|
416
|
+
lines.push("");
|
|
417
|
+
}
|
|
418
|
+
if (doc.researchNeeded.length > 0) {
|
|
419
|
+
lines.push("## Research Needed");
|
|
420
|
+
lines.push("");
|
|
421
|
+
lines.push("> [!warning] Areas Requiring Further Research");
|
|
422
|
+
doc.researchNeeded.forEach((area) => {
|
|
423
|
+
lines.push(`> - ${area}`);
|
|
424
|
+
});
|
|
425
|
+
lines.push("");
|
|
426
|
+
}
|
|
427
|
+
if (doc.todos.length > 0) {
|
|
428
|
+
lines.push("## TODOs");
|
|
429
|
+
lines.push("");
|
|
430
|
+
doc.todos.forEach((todo) => {
|
|
431
|
+
lines.push(`- [ ] ${todo}`);
|
|
432
|
+
});
|
|
433
|
+
lines.push("");
|
|
434
|
+
}
|
|
435
|
+
lines.push("## Tags");
|
|
436
|
+
lines.push("");
|
|
437
|
+
lines.push(doc.tags.map((t) => `#${t}`).join(" "));
|
|
438
|
+
lines.push("");
|
|
439
|
+
return lines.join("\n");
|
|
440
|
+
}
|
|
441
|
+
function generateMOC(category, docTitles, allDocs) {
|
|
442
|
+
const config = CATEGORY_STRUCTURE[category];
|
|
443
|
+
const categoryDocs = allDocs.filter((d) => d.category.startsWith(category));
|
|
444
|
+
const lines = [];
|
|
445
|
+
lines.push("---");
|
|
446
|
+
lines.push(`title: "${formatTitle(category)} - Map of Content"`);
|
|
447
|
+
lines.push("type: concept");
|
|
448
|
+
lines.push("status: active");
|
|
449
|
+
lines.push("tags:");
|
|
450
|
+
lines.push(" - moc");
|
|
451
|
+
lines.push(` - ${category}`);
|
|
452
|
+
lines.push(`created: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`);
|
|
453
|
+
lines.push("---");
|
|
454
|
+
lines.push("");
|
|
455
|
+
lines.push(`# ${formatTitle(category)}`);
|
|
456
|
+
lines.push("");
|
|
457
|
+
lines.push(config?.description || `Documentation related to ${category}.`);
|
|
458
|
+
lines.push("");
|
|
459
|
+
const bySubcategory = /* @__PURE__ */ new Map();
|
|
460
|
+
categoryDocs.forEach((doc) => {
|
|
461
|
+
const parts = doc.category.split("/");
|
|
462
|
+
const sub = parts[1] || "general";
|
|
463
|
+
if (!bySubcategory.has(sub)) {
|
|
464
|
+
bySubcategory.set(sub, []);
|
|
465
|
+
}
|
|
466
|
+
bySubcategory.get(sub).push(doc);
|
|
467
|
+
});
|
|
468
|
+
for (const [sub, docs] of bySubcategory) {
|
|
469
|
+
lines.push(`## ${formatTitle(sub)}`);
|
|
470
|
+
lines.push("");
|
|
471
|
+
docs.forEach((doc) => {
|
|
472
|
+
lines.push(`- [[${doc.title}]] - ${doc.summary.slice(0, 60)}...`);
|
|
473
|
+
});
|
|
474
|
+
lines.push("");
|
|
475
|
+
}
|
|
476
|
+
lines.push("---");
|
|
477
|
+
lines.push(`*${categoryDocs.length} documents in this category*`);
|
|
478
|
+
return lines.join("\n");
|
|
479
|
+
}
|
|
480
|
+
function generateMasterMOC(structure, allDocs) {
|
|
481
|
+
const lines = [];
|
|
482
|
+
lines.push("---");
|
|
483
|
+
lines.push('title: "Knowledge Graph - Master Index"');
|
|
484
|
+
lines.push("type: concept");
|
|
485
|
+
lines.push("status: active");
|
|
486
|
+
lines.push("tags:");
|
|
487
|
+
lines.push(" - moc");
|
|
488
|
+
lines.push(" - index");
|
|
489
|
+
lines.push(" - knowledge-graph");
|
|
490
|
+
lines.push(`created: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`);
|
|
491
|
+
lines.push("---");
|
|
492
|
+
lines.push("");
|
|
493
|
+
lines.push("# Knowledge Graph");
|
|
494
|
+
lines.push("");
|
|
495
|
+
lines.push("Welcome to the knowledge graph. This is the master index of all documentation.");
|
|
496
|
+
lines.push("");
|
|
497
|
+
lines.push("## Categories");
|
|
498
|
+
lines.push("");
|
|
499
|
+
for (const [category, config] of Object.entries(CATEGORY_STRUCTURE)) {
|
|
500
|
+
const count = structure.get(category)?.length || 0;
|
|
501
|
+
lines.push(`### [[${category}/_MOC|${formatTitle(category)}]]`);
|
|
502
|
+
lines.push("");
|
|
503
|
+
lines.push(`${config.description}`);
|
|
504
|
+
lines.push(`*${count} documents*`);
|
|
505
|
+
lines.push("");
|
|
506
|
+
}
|
|
507
|
+
lines.push("## Quick Links");
|
|
508
|
+
lines.push("");
|
|
509
|
+
lines.push("- [[PRIMITIVES]] - Core building blocks and technologies");
|
|
510
|
+
lines.push("- [[guides/_MOC|Getting Started]]");
|
|
511
|
+
lines.push("- [[standards/_MOC|Coding Standards]]");
|
|
512
|
+
lines.push("");
|
|
513
|
+
lines.push("## Statistics");
|
|
514
|
+
lines.push("");
|
|
515
|
+
lines.push(`- **Total Documents**: ${allDocs.length}`);
|
|
516
|
+
lines.push(`- **Categories**: ${structure.size}`);
|
|
517
|
+
lines.push(`- **Generated**: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
518
|
+
lines.push("");
|
|
519
|
+
return lines.join("\n");
|
|
520
|
+
}
|
|
521
|
+
function generatePrimitives(allDocs) {
|
|
522
|
+
const lines = [];
|
|
523
|
+
lines.push("---");
|
|
524
|
+
lines.push('title: "Primitives"');
|
|
525
|
+
lines.push("type: primitive");
|
|
526
|
+
lines.push("status: active");
|
|
527
|
+
lines.push("tags:");
|
|
528
|
+
lines.push(" - primitives");
|
|
529
|
+
lines.push(" - foundation");
|
|
530
|
+
lines.push(" - knowledge-graph");
|
|
531
|
+
lines.push(`created: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`);
|
|
532
|
+
lines.push("---");
|
|
533
|
+
lines.push("");
|
|
534
|
+
lines.push("# Primitives");
|
|
535
|
+
lines.push("");
|
|
536
|
+
lines.push("Core building blocks and foundational technologies used in this project.");
|
|
537
|
+
lines.push("");
|
|
538
|
+
const byType = /* @__PURE__ */ new Map();
|
|
539
|
+
allDocs.forEach((doc) => {
|
|
540
|
+
if (!byType.has(doc.type)) {
|
|
541
|
+
byType.set(doc.type, []);
|
|
542
|
+
}
|
|
543
|
+
byType.get(doc.type).push(doc);
|
|
544
|
+
});
|
|
545
|
+
for (const [type, docs] of byType) {
|
|
546
|
+
lines.push(`## ${formatTitle(type)}`);
|
|
547
|
+
lines.push("");
|
|
548
|
+
docs.slice(0, 10).forEach((doc) => {
|
|
549
|
+
lines.push(`- [[${doc.title}]]`);
|
|
550
|
+
});
|
|
551
|
+
if (docs.length > 10) {
|
|
552
|
+
lines.push(`- *...and ${docs.length - 10} more*`);
|
|
553
|
+
}
|
|
554
|
+
lines.push("");
|
|
555
|
+
}
|
|
556
|
+
return lines.join("\n");
|
|
557
|
+
}
|
|
558
|
+
function formatFilename(title) {
|
|
559
|
+
return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 50);
|
|
560
|
+
}
|
|
561
|
+
function formatTitle(filename) {
|
|
562
|
+
return filename.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()).trim();
|
|
563
|
+
}
|
|
564
|
+
export {
|
|
565
|
+
analyzeDocs
|
|
566
|
+
};
|
|
567
|
+
//# sourceMappingURL=docs-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs-analyzer.js","sources":["../../src/generators/docs-analyzer.ts"],"sourcesContent":["/**\n * Docs Analyzer\n *\n * Advanced documentation analyzer that uses claude-flow to create\n * comprehensive knowledge graph documentation with proper structure,\n * wikilinks, frontmatter, and tags following Obsidian conventions.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { join, basename, dirname, relative, extname } from 'path';\nimport { execSync, spawn } from 'child_process';\nimport fg from 'fast-glob';\nimport matter from 'gray-matter';\nimport type { NodeType, NodeStatus, NodeFrontmatter } from '../core/types.js';\n\n/**\n * Analyzer options\n */\nexport interface AnalyzerOptions {\n /** Source directory with existing docs */\n sourceDir: string;\n /** Target directory (default: docs-nn) */\n targetDir?: string;\n /** Project root for path resolution */\n projectRoot: string;\n /** Use claude-flow for deep analysis */\n useClaudeFlow?: boolean;\n /** Create MOC (Map of Content) files */\n createMOC?: boolean;\n /** Link back to original docs */\n linkOriginal?: boolean;\n /** Maximum depth for analysis */\n maxDepth?: number;\n /** Dry run - show what would be done */\n dryRun?: boolean;\n /** Verbose output */\n verbose?: boolean;\n}\n\n/**\n * Analyzed document\n */\nexport interface AnalyzedDoc {\n /** Original file path */\n originalPath: string;\n /** New file path in docs-nn */\n newPath: string;\n /** Document title */\n title: string;\n /** Detected node type */\n type: NodeType;\n /** Extracted tags */\n tags: string[];\n /** Related documents (wikilinks) */\n related: string[];\n /** Key concepts extracted */\n concepts: string[];\n /** Areas needing research */\n researchNeeded: string[];\n /** TODOs found or generated */\n todos: string[];\n /** Summary/description */\n summary: string;\n /** Category path in structure */\n category: string;\n}\n\n/**\n * Analyzer result\n */\nexport interface AnalyzerResult {\n success: boolean;\n filesAnalyzed: number;\n filesCreated: number;\n mocFilesCreated: number;\n errors: string[];\n analyzed: AnalyzedDoc[];\n structure: Map<string, string[]>;\n}\n\n/**\n * Weave-NN category structure with descriptions\n */\nconst CATEGORY_STRUCTURE: Record<string, { type: NodeType; description: string; subcategories: string[] }> = {\n concepts: {\n type: 'concept',\n description: 'Abstract concepts, theories, and architectural principles',\n subcategories: ['architecture', 'patterns', 'principles', 'models'],\n },\n components: {\n type: 'technical',\n description: 'Reusable technical components and implementations',\n subcategories: ['ui', 'utilities', 'core', 'shared'],\n },\n services: {\n type: 'service',\n description: 'Backend services, APIs, and workers',\n subcategories: ['api', 'workers', 'handlers', 'middleware'],\n },\n features: {\n type: 'feature',\n description: 'Product features and capabilities',\n subcategories: ['core', 'advanced', 'experimental'],\n },\n integrations: {\n type: 'integration',\n description: 'External integrations and adapters',\n subcategories: ['databases', 'auth', 'storage', 'monitoring', 'third-party'],\n },\n standards: {\n type: 'standard',\n description: 'Coding standards, conventions, and best practices',\n subcategories: ['coding', 'documentation', 'testing', 'security'],\n },\n guides: {\n type: 'guide',\n description: 'How-to guides and tutorials',\n subcategories: ['getting-started', 'tutorials', 'troubleshooting', 'deployment'],\n },\n references: {\n type: 'technical',\n description: 'API references and technical documentation',\n subcategories: ['api', 'cli', 'config', 'schemas'],\n },\n};\n\n/**\n * Analyze and migrate documentation to weave-nn structure\n */\nexport async function analyzeDocs(options: AnalyzerOptions): Promise<AnalyzerResult> {\n const {\n sourceDir,\n targetDir = 'docs-nn',\n projectRoot,\n useClaudeFlow = false,\n createMOC = true,\n linkOriginal = true,\n maxDepth = 3,\n dryRun = false,\n verbose = false,\n } = options;\n\n const result: AnalyzerResult = {\n success: true,\n filesAnalyzed: 0,\n filesCreated: 0,\n mocFilesCreated: 0,\n errors: [],\n analyzed: [],\n structure: new Map(),\n };\n\n const sourcePath = join(projectRoot, sourceDir);\n const targetPath = join(projectRoot, targetDir);\n\n // Validate source exists\n if (!existsSync(sourcePath)) {\n result.success = false;\n result.errors.push(`Source directory not found: ${sourcePath}`);\n return result;\n }\n\n // Create target structure\n if (!dryRun) {\n createFullStructure(targetPath);\n }\n\n // Find all markdown files\n const files = await fg('**/*.md', {\n cwd: sourcePath,\n ignore: ['node_modules/**', '.git/**', '_templates/**', 'docs-nn/**'],\n });\n\n // First pass: Analyze all documents\n const analyzedDocs: AnalyzedDoc[] = [];\n\n for (const file of files) {\n result.filesAnalyzed++;\n const sourceFile = join(sourcePath, file);\n\n try {\n const analyzed = await analyzeDocument(sourceFile, file, sourcePath, {\n useClaudeFlow,\n linkOriginal,\n verbose,\n });\n analyzedDocs.push(analyzed);\n\n // Track structure\n const category = analyzed.category.split('/')[0];\n if (!result.structure.has(category)) {\n result.structure.set(category, []);\n }\n result.structure.get(category)!.push(analyzed.title);\n\n } catch (error) {\n result.errors.push(`Failed to analyze ${file}: ${error}`);\n }\n }\n\n // Build cross-references between documents\n buildCrossReferences(analyzedDocs);\n\n // Second pass: Create new documents\n for (const doc of analyzedDocs) {\n try {\n const targetFile = join(targetPath, doc.newPath);\n\n if (!dryRun) {\n mkdirSync(dirname(targetFile), { recursive: true });\n const content = generateKnowledgeDoc(doc, sourceDir, linkOriginal, analyzedDocs);\n writeFileSync(targetFile, content, 'utf-8');\n }\n\n result.filesCreated++;\n result.analyzed.push(doc);\n\n } catch (error) {\n result.errors.push(`Failed to create ${doc.newPath}: ${error}`);\n }\n }\n\n // Create MOC files for each category\n if (createMOC && !dryRun) {\n for (const [category, docs] of result.structure) {\n const mocPath = join(targetPath, category, '_MOC.md');\n const mocContent = generateMOC(category, docs, analyzedDocs);\n writeFileSync(mocPath, mocContent, 'utf-8');\n result.mocFilesCreated++;\n }\n\n // Create master MOC\n const masterMocPath = join(targetPath, 'MOC.md');\n const masterMocContent = generateMasterMOC(result.structure, analyzedDocs);\n writeFileSync(masterMocPath, masterMocContent, 'utf-8');\n result.mocFilesCreated++;\n\n // Create PRIMITIVES.md\n const primitivesPath = join(targetPath, 'PRIMITIVES.md');\n const primitivesContent = generatePrimitives(analyzedDocs);\n writeFileSync(primitivesPath, primitivesContent, 'utf-8');\n }\n\n result.success = result.errors.length === 0;\n return result;\n}\n\n/**\n * Analyze a single document\n */\nasync function analyzeDocument(\n filePath: string,\n relativePath: string,\n sourcePath: string,\n options: { useClaudeFlow?: boolean; linkOriginal?: boolean; verbose?: boolean }\n): Promise<AnalyzedDoc> {\n const content = readFileSync(filePath, 'utf-8');\n const { data: existingFrontmatter, content: body } = matter(content);\n\n const filename = basename(filePath, '.md');\n const title = existingFrontmatter.title as string || formatTitle(filename);\n\n // Detect node type and category\n const { type, category } = detectTypeAndCategory(relativePath, body, existingFrontmatter);\n\n // Extract tags\n const tags = extractAllTags(body, existingFrontmatter, relativePath);\n\n // Extract wikilinks and markdown links\n const related = extractLinks(body);\n\n // Extract key concepts\n const concepts = extractConcepts(body);\n\n // Find areas needing research\n const researchNeeded = findResearchAreas(body, filename);\n\n // Extract existing TODOs and generate new ones\n const todos = extractAndGenerateTodos(body, content, filename);\n\n // Generate summary\n const summary = generateSummary(body, existingFrontmatter);\n\n // Determine new path\n const newPath = join(category, formatFilename(filename) + '.md');\n\n return {\n originalPath: relativePath,\n newPath,\n title,\n type,\n tags,\n related,\n concepts,\n researchNeeded,\n todos,\n summary,\n category,\n };\n}\n\n/**\n * Create full target directory structure\n */\nfunction createFullStructure(targetPath: string): void {\n // Create all category directories and subcategories\n for (const [category, config] of Object.entries(CATEGORY_STRUCTURE)) {\n mkdirSync(join(targetPath, category), { recursive: true });\n for (const sub of config.subcategories) {\n mkdirSync(join(targetPath, category, sub), { recursive: true });\n }\n }\n\n // Create meta directories\n mkdirSync(join(targetPath, '_templates'), { recursive: true });\n mkdirSync(join(targetPath, '_attachments'), { recursive: true });\n mkdirSync(join(targetPath, '_archive'), { recursive: true });\n}\n\n/**\n * Detect node type and category from content\n */\nfunction detectTypeAndCategory(\n filePath: string,\n content: string,\n frontmatter: Record<string, unknown>\n): { type: NodeType; category: string } {\n // Check frontmatter first\n if (frontmatter.type && frontmatter.category) {\n return {\n type: frontmatter.type as NodeType,\n category: frontmatter.category as string,\n };\n }\n\n const lowerContent = content.toLowerCase();\n const lowerPath = filePath.toLowerCase();\n\n // Score each category\n const scores: Record<string, number> = {};\n\n for (const [category, config] of Object.entries(CATEGORY_STRUCTURE)) {\n scores[category] = 0;\n\n // Path matching\n if (lowerPath.includes(category)) scores[category] += 10;\n for (const sub of config.subcategories) {\n if (lowerPath.includes(sub)) scores[category] += 5;\n }\n\n // Content analysis based on type\n const keywords = getKeywordsForType(config.type);\n for (const keyword of keywords) {\n const regex = new RegExp(`\\\\b${keyword}\\\\b`, 'gi');\n const matches = content.match(regex);\n if (matches) scores[category] += matches.length;\n }\n }\n\n // Find best match\n let bestCategory = 'concepts';\n let bestScore = 0;\n\n for (const [category, score] of Object.entries(scores)) {\n if (score > bestScore) {\n bestScore = score;\n bestCategory = category;\n }\n }\n\n return {\n type: CATEGORY_STRUCTURE[bestCategory].type,\n category: bestCategory,\n };\n}\n\n/**\n * Get keywords for a node type\n */\nfunction getKeywordsForType(type: NodeType): string[] {\n const keywords: Record<NodeType, string[]> = {\n concept: ['concept', 'theory', 'principle', 'overview', 'introduction', 'architecture', 'design', 'pattern'],\n technical: ['component', 'implementation', 'class', 'function', 'module', 'utility', 'helper'],\n feature: ['feature', 'capability', 'functionality', 'user', 'requirement', 'use case'],\n primitive: ['library', 'framework', 'dependency', 'tool', 'sdk'],\n service: ['api', 'endpoint', 'service', 'server', 'backend', 'worker', 'handler'],\n guide: ['how to', 'tutorial', 'guide', 'step', 'walkthrough', 'getting started'],\n standard: ['standard', 'convention', 'best practice', 'rule', 'guideline', 'style'],\n integration: ['integration', 'connect', 'plugin', 'adapter', 'sync', 'import', 'export'],\n };\n\n return keywords[type] || [];\n}\n\n/**\n * Extract all tags from content and path\n */\nfunction extractAllTags(\n content: string,\n frontmatter: Record<string, unknown>,\n filePath: string\n): string[] {\n const tags = new Set<string>();\n\n // Add existing frontmatter tags\n if (Array.isArray(frontmatter.tags)) {\n frontmatter.tags.forEach(t => tags.add(String(t)));\n }\n\n // Extract #tags from content\n const hashTags = content.match(/#[\\w-]+/g);\n if (hashTags) {\n hashTags.forEach(t => tags.add(t.slice(1)));\n }\n\n // Generate tags from path\n const pathParts = filePath.split('/').filter(p => p && !p.endsWith('.md'));\n pathParts.forEach(p => {\n if (p.length > 2 && p.length < 20) {\n tags.add(p.replace(/[-_]/g, '-').toLowerCase());\n }\n });\n\n // Add status tags\n if (content.match(/\\b(wip|draft|todo)\\b/i)) tags.add('needs-work');\n if (content.match(/\\b(deprecated|legacy)\\b/i)) tags.add('deprecated');\n if (content.match(/\\b(experimental|beta)\\b/i)) tags.add('experimental');\n\n return [...tags].slice(0, 15);\n}\n\n/**\n * Extract wikilinks and markdown links\n */\nfunction extractLinks(content: string): string[] {\n const links = new Set<string>();\n\n // Wikilinks\n const wikilinks = content.match(/\\[\\[([^\\]|]+)(?:\\|[^\\]]+)?\\]\\]/g);\n if (wikilinks) {\n wikilinks.forEach(link => {\n const match = link.match(/\\[\\[([^\\]|]+)/);\n if (match) links.add(match[1].trim());\n });\n }\n\n // Markdown links (internal only)\n const mdLinks = content.match(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g);\n if (mdLinks) {\n mdLinks.forEach(link => {\n const match = link.match(/\\]\\(([^)]+)\\)/);\n if (match && !match[1].startsWith('http')) {\n links.add(match[1].replace(/\\.md$/, '').trim());\n }\n });\n }\n\n return [...links];\n}\n\n/**\n * Extract key concepts from content\n */\nfunction extractConcepts(content: string): string[] {\n const concepts: string[] = [];\n\n // Look for headers as concepts\n const headers = content.match(/^##\\s+(.+)$/gm);\n if (headers) {\n headers.slice(0, 5).forEach(h => {\n concepts.push(h.replace(/^##\\s+/, '').trim());\n });\n }\n\n // Look for bold terms as concepts\n const boldTerms = content.match(/\\*\\*([^*]+)\\*\\*/g);\n if (boldTerms) {\n boldTerms.slice(0, 5).forEach(term => {\n const clean = term.replace(/\\*\\*/g, '').trim();\n if (clean.length > 2 && clean.length < 50) {\n concepts.push(clean);\n }\n });\n }\n\n return [...new Set(concepts)].slice(0, 10);\n}\n\n/**\n * Find areas needing research\n */\nfunction findResearchAreas(content: string, filename: string): string[] {\n const areas: string[] = [];\n\n // Look for question marks indicating uncertainty\n const questions = content.match(/[^.!?]*\\?/g);\n if (questions) {\n questions.slice(0, 3).forEach(q => {\n if (q.length > 10 && q.length < 200) {\n areas.push(q.trim());\n }\n });\n }\n\n // Look for placeholders\n if (content.match(/\\bTBD\\b|\\bTODO\\b|\\bFIXME\\b/i)) {\n areas.push('Contains placeholders that need completion');\n }\n\n // Look for empty sections\n const emptyHeaders = content.match(/^##[^#\\n]+\\n\\n##/gm);\n if (emptyHeaders) {\n areas.push('Has empty sections that need content');\n }\n\n // Check for missing content indicators\n if (content.length < 500) {\n areas.push('Document is short - may need expansion');\n }\n\n return areas;\n}\n\n/**\n * Extract and generate TODOs\n */\nfunction extractAndGenerateTodos(body: string, fullContent: string, filename: string): string[] {\n const todos: string[] = [];\n\n // Extract existing TODOs\n const existingTodos = fullContent.match(/[-*]\\s*\\[[ x]\\]\\s*(.+)/g);\n if (existingTodos) {\n existingTodos.forEach(todo => {\n todos.push(todo.replace(/^[-*]\\s*\\[[ x]\\]\\s*/, '').trim());\n });\n }\n\n // Extract TODO comments\n const todoComments = fullContent.match(/(?:TODO|FIXME|XXX):\\s*(.+)/gi);\n if (todoComments) {\n todoComments.forEach(todo => {\n todos.push(todo.replace(/^(?:TODO|FIXME|XXX):\\s*/i, '').trim());\n });\n }\n\n // Generate suggested TODOs based on analysis\n if (!fullContent.match(/^---[\\s\\S]*?---/)) {\n todos.push('Add proper frontmatter');\n }\n\n if (!fullContent.match(/\\[\\[/)) {\n todos.push('Add wikilinks to related documents');\n }\n\n if (!fullContent.match(/^##\\s/m)) {\n todos.push('Add section structure with headers');\n }\n\n return [...new Set(todos)].slice(0, 10);\n}\n\n/**\n * Generate summary from content\n */\nfunction generateSummary(body: string, frontmatter: Record<string, unknown>): string {\n // Use existing description\n if (frontmatter.description) {\n return String(frontmatter.description);\n }\n\n // Extract first meaningful paragraph\n const lines = body.split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed && !trimmed.startsWith('#') && !trimmed.startsWith('```') && trimmed.length > 30) {\n return trimmed.length > 200 ? trimmed.slice(0, 197) + '...' : trimmed;\n }\n }\n\n return 'Documentation requiring summary.';\n}\n\n/**\n * Build cross-references between documents\n */\nfunction buildCrossReferences(docs: AnalyzedDoc[]): void {\n const titleMap = new Map<string, AnalyzedDoc>();\n\n // Build title lookup\n docs.forEach(doc => {\n titleMap.set(doc.title.toLowerCase(), doc);\n titleMap.set(formatFilename(doc.title), doc);\n });\n\n // Update related links\n docs.forEach(doc => {\n const newRelated: string[] = [];\n\n doc.related.forEach(link => {\n const linkedDoc = titleMap.get(link.toLowerCase()) || titleMap.get(formatFilename(link));\n if (linkedDoc) {\n newRelated.push(linkedDoc.title);\n } else {\n newRelated.push(link);\n }\n });\n\n // Find related docs by shared tags\n const sharedTagDocs = docs.filter(other =>\n other !== doc &&\n other.tags.some(t => doc.tags.includes(t))\n );\n\n sharedTagDocs.slice(0, 3).forEach(other => {\n if (!newRelated.includes(other.title)) {\n newRelated.push(other.title);\n }\n });\n\n doc.related = [...new Set(newRelated)].slice(0, 10);\n });\n}\n\n/**\n * Generate knowledge document content\n */\nfunction generateKnowledgeDoc(\n doc: AnalyzedDoc,\n sourceDir: string,\n linkOriginal: boolean,\n allDocs: AnalyzedDoc[]\n): string {\n const lines: string[] = [];\n\n // Frontmatter\n lines.push('---');\n lines.push(`title: \"${doc.title}\"`);\n lines.push(`type: ${doc.type}`);\n lines.push(`status: active`);\n if (doc.tags.length > 0) {\n lines.push('tags:');\n doc.tags.forEach(tag => lines.push(` - ${tag}`));\n }\n lines.push(`category: ${doc.category}`);\n lines.push(`description: \"${doc.summary.replace(/\"/g, '\\\\\"')}\"`);\n lines.push(`created: ${new Date().toISOString().split('T')[0]}`);\n lines.push(`updated: ${new Date().toISOString().split('T')[0]}`);\n if (linkOriginal) {\n lines.push(`original: \"${sourceDir}/${doc.originalPath}\"`);\n }\n if (doc.related.length > 0) {\n lines.push('related:');\n doc.related.slice(0, 5).forEach(r => lines.push(` - \"[[${r}]]\"`));\n }\n lines.push('---');\n lines.push('');\n\n // Title\n lines.push(`# ${doc.title}`);\n lines.push('');\n\n // Summary\n lines.push('## Overview');\n lines.push('');\n lines.push(doc.summary);\n lines.push('');\n\n // Original reference\n if (linkOriginal) {\n lines.push(`> [!info] Original Documentation`);\n lines.push(`> See [[${sourceDir}/${doc.originalPath}|original document]] for full details.`);\n lines.push('');\n }\n\n // Key concepts\n if (doc.concepts.length > 0) {\n lines.push('## Key Concepts');\n lines.push('');\n doc.concepts.forEach(concept => {\n lines.push(`- **${concept}**`);\n });\n lines.push('');\n }\n\n // Related documents\n if (doc.related.length > 0) {\n lines.push('## Related');\n lines.push('');\n doc.related.forEach(rel => {\n lines.push(`- [[${rel}]]`);\n });\n lines.push('');\n }\n\n // Research needed\n if (doc.researchNeeded.length > 0) {\n lines.push('## Research Needed');\n lines.push('');\n lines.push('> [!warning] Areas Requiring Further Research');\n doc.researchNeeded.forEach(area => {\n lines.push(`> - ${area}`);\n });\n lines.push('');\n }\n\n // TODOs\n if (doc.todos.length > 0) {\n lines.push('## TODOs');\n lines.push('');\n doc.todos.forEach(todo => {\n lines.push(`- [ ] ${todo}`);\n });\n lines.push('');\n }\n\n // Tags section\n lines.push('## Tags');\n lines.push('');\n lines.push(doc.tags.map(t => `#${t}`).join(' '));\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/**\n * Generate MOC (Map of Content) for a category\n */\nfunction generateMOC(category: string, docTitles: string[], allDocs: AnalyzedDoc[]): string {\n const config = CATEGORY_STRUCTURE[category];\n const categoryDocs = allDocs.filter(d => d.category.startsWith(category));\n\n const lines: string[] = [];\n\n lines.push('---');\n lines.push(`title: \"${formatTitle(category)} - Map of Content\"`);\n lines.push('type: concept');\n lines.push('status: active');\n lines.push('tags:');\n lines.push(' - moc');\n lines.push(` - ${category}`);\n lines.push(`created: ${new Date().toISOString().split('T')[0]}`);\n lines.push('---');\n lines.push('');\n lines.push(`# ${formatTitle(category)}`);\n lines.push('');\n lines.push(config?.description || `Documentation related to ${category}.`);\n lines.push('');\n\n // Group by subcategory\n const bySubcategory = new Map<string, AnalyzedDoc[]>();\n categoryDocs.forEach(doc => {\n const parts = doc.category.split('/');\n const sub = parts[1] || 'general';\n if (!bySubcategory.has(sub)) {\n bySubcategory.set(sub, []);\n }\n bySubcategory.get(sub)!.push(doc);\n });\n\n for (const [sub, docs] of bySubcategory) {\n lines.push(`## ${formatTitle(sub)}`);\n lines.push('');\n docs.forEach(doc => {\n lines.push(`- [[${doc.title}]] - ${doc.summary.slice(0, 60)}...`);\n });\n lines.push('');\n }\n\n lines.push('---');\n lines.push(`*${categoryDocs.length} documents in this category*`);\n\n return lines.join('\\n');\n}\n\n/**\n * Generate master MOC\n */\nfunction generateMasterMOC(structure: Map<string, string[]>, allDocs: AnalyzedDoc[]): string {\n const lines: string[] = [];\n\n lines.push('---');\n lines.push('title: \"Knowledge Graph - Master Index\"');\n lines.push('type: concept');\n lines.push('status: active');\n lines.push('tags:');\n lines.push(' - moc');\n lines.push(' - index');\n lines.push(' - knowledge-graph');\n lines.push(`created: ${new Date().toISOString().split('T')[0]}`);\n lines.push('---');\n lines.push('');\n lines.push('# Knowledge Graph');\n lines.push('');\n lines.push('Welcome to the knowledge graph. This is the master index of all documentation.');\n lines.push('');\n lines.push('## Categories');\n lines.push('');\n\n for (const [category, config] of Object.entries(CATEGORY_STRUCTURE)) {\n const count = structure.get(category)?.length || 0;\n lines.push(`### [[${category}/_MOC|${formatTitle(category)}]]`);\n lines.push('');\n lines.push(`${config.description}`);\n lines.push(`*${count} documents*`);\n lines.push('');\n }\n\n lines.push('## Quick Links');\n lines.push('');\n lines.push('- [[PRIMITIVES]] - Core building blocks and technologies');\n lines.push('- [[guides/_MOC|Getting Started]]');\n lines.push('- [[standards/_MOC|Coding Standards]]');\n lines.push('');\n\n lines.push('## Statistics');\n lines.push('');\n lines.push(`- **Total Documents**: ${allDocs.length}`);\n lines.push(`- **Categories**: ${structure.size}`);\n lines.push(`- **Generated**: ${new Date().toISOString()}`);\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/**\n * Generate PRIMITIVES.md\n */\nfunction generatePrimitives(allDocs: AnalyzedDoc[]): string {\n const lines: string[] = [];\n\n lines.push('---');\n lines.push('title: \"Primitives\"');\n lines.push('type: primitive');\n lines.push('status: active');\n lines.push('tags:');\n lines.push(' - primitives');\n lines.push(' - foundation');\n lines.push(' - knowledge-graph');\n lines.push(`created: ${new Date().toISOString().split('T')[0]}`);\n lines.push('---');\n lines.push('');\n lines.push('# Primitives');\n lines.push('');\n lines.push('Core building blocks and foundational technologies used in this project.');\n lines.push('');\n\n // Group docs by type\n const byType = new Map<NodeType, AnalyzedDoc[]>();\n allDocs.forEach(doc => {\n if (!byType.has(doc.type)) {\n byType.set(doc.type, []);\n }\n byType.get(doc.type)!.push(doc);\n });\n\n for (const [type, docs] of byType) {\n lines.push(`## ${formatTitle(type)}`);\n lines.push('');\n docs.slice(0, 10).forEach(doc => {\n lines.push(`- [[${doc.title}]]`);\n });\n if (docs.length > 10) {\n lines.push(`- *...and ${docs.length - 10} more*`);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Format filename from title\n */\nfunction formatFilename(title: string): string {\n return title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 50);\n}\n\n/**\n * Format title from filename\n */\nfunction formatTitle(filename: string): string {\n return filename\n .replace(/[-_]/g, ' ')\n .replace(/\\b\\w/g, c => c.toUpperCase())\n .trim();\n}\n"],"names":[],"mappings":"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"}
|