@weavelogic/knowledge-graph-agent 0.8.8 → 0.9.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/dist/cli/commands/docs.d.ts.map +1 -1
- package/dist/cli/commands/docs.js +106 -0
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/generators/doc-cultivator.d.ts +117 -0
- package/dist/generators/doc-cultivator.d.ts.map +1 -0
- package/dist/generators/doc-cultivator.js +1020 -0
- package/dist/generators/doc-cultivator.js.map +1 -0
- package/dist/node_modules/@typescript-eslint/project-service/dist/index.js +1 -1
- package/dist/node_modules/tinyglobby/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,1020 @@
|
|
|
1
|
+
import { existsSync, statSync, readdirSync, mkdirSync, writeFileSync, readFileSync } from "fs";
|
|
2
|
+
import { join, dirname, basename } from "path";
|
|
3
|
+
import fg from "fast-glob";
|
|
4
|
+
import { exec, spawn } from "child_process";
|
|
5
|
+
import { promisify } from "util";
|
|
6
|
+
promisify(exec);
|
|
7
|
+
async function cultivateDocs(projectRoot, docsPath, options = {}) {
|
|
8
|
+
const result = {
|
|
9
|
+
success: true,
|
|
10
|
+
projectRoot,
|
|
11
|
+
docsPath,
|
|
12
|
+
startTime: /* @__PURE__ */ new Date(),
|
|
13
|
+
services: [],
|
|
14
|
+
documentsGenerated: [],
|
|
15
|
+
documentsUpdated: [],
|
|
16
|
+
errors: [],
|
|
17
|
+
logs: []
|
|
18
|
+
};
|
|
19
|
+
const log = (msg) => {
|
|
20
|
+
result.logs.push(`[${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}`);
|
|
21
|
+
if (options.verbose) {
|
|
22
|
+
console.log(msg);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
try {
|
|
26
|
+
log("Starting documentation cultivation...");
|
|
27
|
+
log("Phase 1: Analyzing project structure...");
|
|
28
|
+
result.services = await analyzeProjectServices(projectRoot, options);
|
|
29
|
+
log(` Found ${result.services.length} services: ${result.services.map((s) => s.name).join(", ")}`);
|
|
30
|
+
log("Phase 2: Scanning existing documentation...");
|
|
31
|
+
const existingDocs = await scanAllDocs(projectRoot, docsPath);
|
|
32
|
+
log(` Found ${existingDocs.length} existing documentation files`);
|
|
33
|
+
log("Phase 3: Building cultivation tasks...");
|
|
34
|
+
const tasks = await buildCultivationTasks(result.services, existingDocs, docsPath, options);
|
|
35
|
+
log(` Created ${tasks.length} cultivation tasks`);
|
|
36
|
+
if (options.dryRun) {
|
|
37
|
+
log("\n[Dry Run] Would execute the following tasks:");
|
|
38
|
+
for (const task of tasks) {
|
|
39
|
+
log(` - [${task.type}] ${task.description} (${task.agentType} agent)`);
|
|
40
|
+
if (task.outputPath) {
|
|
41
|
+
log(` → ${task.outputPath}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
result.endTime = /* @__PURE__ */ new Date();
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
log("Phase 4: Executing cultivation with claude-flow swarm...");
|
|
48
|
+
const taskResults = await executeCultivationSwarm(tasks, result, options);
|
|
49
|
+
if (options.generateDevPlan !== false) {
|
|
50
|
+
log("Phase 5: Generating development plan...");
|
|
51
|
+
const devPlan = await generateDevelopmentPlan(result.services, docsPath, options);
|
|
52
|
+
result.developmentPlan = devPlan;
|
|
53
|
+
log(` Generated ${devPlan.phases.length} development phases`);
|
|
54
|
+
}
|
|
55
|
+
if (options.generateInfraPlan !== false) {
|
|
56
|
+
log("Phase 6: Generating infrastructure plan...");
|
|
57
|
+
const infraPlan = await generateInfrastructurePlan(result.services, docsPath, options);
|
|
58
|
+
result.infrastructurePlan = infraPlan;
|
|
59
|
+
log(` Generated infrastructure plan for ${infraPlan.environments.length} environments`);
|
|
60
|
+
}
|
|
61
|
+
if (options.includeSops) {
|
|
62
|
+
log("Phase 7: Analyzing SOP compliance...");
|
|
63
|
+
const sopCompliance = await analyzeSopCompliance(projectRoot, docsPath, result.services);
|
|
64
|
+
result.sopCompliance = sopCompliance;
|
|
65
|
+
log(` SOP compliance score: ${sopCompliance.score}%`);
|
|
66
|
+
}
|
|
67
|
+
result.success = result.errors.length === 0;
|
|
68
|
+
result.endTime = /* @__PURE__ */ new Date();
|
|
69
|
+
log(`
|
|
70
|
+
Cultivation complete!`);
|
|
71
|
+
log(` Documents generated: ${result.documentsGenerated.length}`);
|
|
72
|
+
log(` Documents updated: ${result.documentsUpdated.length}`);
|
|
73
|
+
log(` Errors: ${result.errors.length}`);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
result.success = false;
|
|
76
|
+
result.errors.push(`Cultivation failed: ${error}`);
|
|
77
|
+
result.endTime = /* @__PURE__ */ new Date();
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
async function analyzeProjectServices(projectRoot, options) {
|
|
82
|
+
const services = [];
|
|
83
|
+
const serviceDirs = options.services || ["api", "backend", "frontend", "admin", "shared", "common", "lib"];
|
|
84
|
+
const searchPaths = [
|
|
85
|
+
join(projectRoot, "src"),
|
|
86
|
+
projectRoot
|
|
87
|
+
];
|
|
88
|
+
for (const searchPath of searchPaths) {
|
|
89
|
+
if (!existsSync(searchPath)) continue;
|
|
90
|
+
for (const serviceName of serviceDirs) {
|
|
91
|
+
const servicePath = join(searchPath, serviceName);
|
|
92
|
+
if (!existsSync(servicePath)) continue;
|
|
93
|
+
try {
|
|
94
|
+
if (!statSync(servicePath).isDirectory()) continue;
|
|
95
|
+
} catch {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const analysis = await analyzeService(servicePath, serviceName);
|
|
99
|
+
if (analysis) {
|
|
100
|
+
services.push(analysis);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const srcDir = join(projectRoot, "src");
|
|
105
|
+
if (existsSync(srcDir)) {
|
|
106
|
+
try {
|
|
107
|
+
const entries = readdirSync(srcDir, { withFileTypes: true });
|
|
108
|
+
for (const entry of entries) {
|
|
109
|
+
if (!entry.isDirectory()) continue;
|
|
110
|
+
if (services.some((s) => s.name === entry.name)) continue;
|
|
111
|
+
const servicePath = join(srcDir, entry.name);
|
|
112
|
+
const docsDir = join(servicePath, "docs");
|
|
113
|
+
if (existsSync(docsDir)) {
|
|
114
|
+
const analysis = await analyzeService(servicePath, entry.name);
|
|
115
|
+
if (analysis) {
|
|
116
|
+
services.push(analysis);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
} catch {
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return services;
|
|
124
|
+
}
|
|
125
|
+
async function analyzeService(servicePath, serviceName) {
|
|
126
|
+
try {
|
|
127
|
+
const analysis = {
|
|
128
|
+
name: serviceName,
|
|
129
|
+
path: servicePath,
|
|
130
|
+
type: guessServiceType(serviceName),
|
|
131
|
+
languages: [],
|
|
132
|
+
frameworks: [],
|
|
133
|
+
existingDocs: [],
|
|
134
|
+
sourceFiles: [],
|
|
135
|
+
dependencies: [],
|
|
136
|
+
description: ""
|
|
137
|
+
};
|
|
138
|
+
const sourcePatterns = ["**/*.{ts,tsx,js,jsx,py,go,rs}"];
|
|
139
|
+
const sourceFiles = await fg(sourcePatterns, {
|
|
140
|
+
cwd: servicePath,
|
|
141
|
+
ignore: ["node_modules/**", ".git/**", "dist/**", "build/**", "__pycache__/**"]
|
|
142
|
+
});
|
|
143
|
+
analysis.sourceFiles = sourceFiles;
|
|
144
|
+
if (sourceFiles.some((f) => f.endsWith(".ts") || f.endsWith(".tsx"))) {
|
|
145
|
+
analysis.languages.push("TypeScript");
|
|
146
|
+
}
|
|
147
|
+
if (sourceFiles.some((f) => f.endsWith(".js") || f.endsWith(".jsx"))) {
|
|
148
|
+
analysis.languages.push("JavaScript");
|
|
149
|
+
}
|
|
150
|
+
if (sourceFiles.some((f) => f.endsWith(".py"))) {
|
|
151
|
+
analysis.languages.push("Python");
|
|
152
|
+
}
|
|
153
|
+
if (sourceFiles.some((f) => f.endsWith(".go"))) {
|
|
154
|
+
analysis.languages.push("Go");
|
|
155
|
+
}
|
|
156
|
+
if (sourceFiles.some((f) => f.endsWith(".rs"))) {
|
|
157
|
+
analysis.languages.push("Rust");
|
|
158
|
+
}
|
|
159
|
+
const docsDir = join(servicePath, "docs");
|
|
160
|
+
if (existsSync(docsDir)) {
|
|
161
|
+
const docFiles = await fg("**/*.md", { cwd: docsDir });
|
|
162
|
+
analysis.existingDocs = docFiles;
|
|
163
|
+
}
|
|
164
|
+
const pkgPath = join(servicePath, "package.json");
|
|
165
|
+
if (existsSync(pkgPath)) {
|
|
166
|
+
try {
|
|
167
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
168
|
+
analysis.description = pkg.description || "";
|
|
169
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
170
|
+
analysis.dependencies = Object.keys(deps);
|
|
171
|
+
if (deps.react) analysis.frameworks.push("React");
|
|
172
|
+
if (deps.next) analysis.frameworks.push("Next.js");
|
|
173
|
+
if (deps.vue) analysis.frameworks.push("Vue");
|
|
174
|
+
if (deps.express) analysis.frameworks.push("Express");
|
|
175
|
+
if (deps.fastify) analysis.frameworks.push("Fastify");
|
|
176
|
+
if (deps["@nestjs/core"]) analysis.frameworks.push("NestJS");
|
|
177
|
+
} catch {
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const reqPath = join(servicePath, "requirements.txt");
|
|
181
|
+
if (existsSync(reqPath)) {
|
|
182
|
+
try {
|
|
183
|
+
const reqContent = readFileSync(reqPath, "utf-8").toLowerCase();
|
|
184
|
+
if (reqContent.includes("fastapi")) analysis.frameworks.push("FastAPI");
|
|
185
|
+
if (reqContent.includes("flask")) analysis.frameworks.push("Flask");
|
|
186
|
+
if (reqContent.includes("django")) analysis.frameworks.push("Django");
|
|
187
|
+
if (reqContent.includes("sqlalchemy")) analysis.frameworks.push("SQLAlchemy");
|
|
188
|
+
} catch {
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return analysis;
|
|
192
|
+
} catch {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function guessServiceType(name) {
|
|
197
|
+
const nameLower = name.toLowerCase();
|
|
198
|
+
if (nameLower.includes("frontend") || nameLower.includes("client") || nameLower.includes("web") || nameLower.includes("ui")) {
|
|
199
|
+
return "frontend";
|
|
200
|
+
}
|
|
201
|
+
if (nameLower.includes("backend") || nameLower.includes("server")) {
|
|
202
|
+
return "backend";
|
|
203
|
+
}
|
|
204
|
+
if (nameLower.includes("api") || nameLower.includes("gateway")) {
|
|
205
|
+
return "api";
|
|
206
|
+
}
|
|
207
|
+
if (nameLower.includes("admin") || nameLower.includes("dashboard")) {
|
|
208
|
+
return "admin";
|
|
209
|
+
}
|
|
210
|
+
if (nameLower.includes("shared") || nameLower.includes("common") || nameLower.includes("lib")) {
|
|
211
|
+
return "shared";
|
|
212
|
+
}
|
|
213
|
+
return "unknown";
|
|
214
|
+
}
|
|
215
|
+
async function scanAllDocs(projectRoot, docsPath) {
|
|
216
|
+
const allDocs = [];
|
|
217
|
+
if (existsSync(docsPath)) {
|
|
218
|
+
const mainDocs = await fg("**/*.md", {
|
|
219
|
+
cwd: docsPath,
|
|
220
|
+
ignore: ["node_modules/**", ".git/**"]
|
|
221
|
+
});
|
|
222
|
+
allDocs.push(...mainDocs.map((d) => join(docsPath, d)));
|
|
223
|
+
}
|
|
224
|
+
const srcDir = join(projectRoot, "src");
|
|
225
|
+
if (existsSync(srcDir)) {
|
|
226
|
+
const serviceDocs = await fg("*/docs/**/*.md", {
|
|
227
|
+
cwd: srcDir,
|
|
228
|
+
ignore: ["node_modules/**", ".git/**"]
|
|
229
|
+
});
|
|
230
|
+
allDocs.push(...serviceDocs.map((d) => join(srcDir, d)));
|
|
231
|
+
}
|
|
232
|
+
const rootDocs = await fg("*.md", {
|
|
233
|
+
cwd: projectRoot,
|
|
234
|
+
ignore: ["node_modules/**", ".git/**"]
|
|
235
|
+
});
|
|
236
|
+
allDocs.push(...rootDocs.map((d) => join(projectRoot, d)));
|
|
237
|
+
return allDocs;
|
|
238
|
+
}
|
|
239
|
+
async function buildCultivationTasks(services, existingDocs, docsPath, options) {
|
|
240
|
+
const tasks = [];
|
|
241
|
+
let taskId = 0;
|
|
242
|
+
tasks.push({
|
|
243
|
+
id: `task-${++taskId}`,
|
|
244
|
+
type: "research",
|
|
245
|
+
agentType: "researcher",
|
|
246
|
+
description: "Research and document project overview",
|
|
247
|
+
prompt: buildProjectOverviewPrompt(services, existingDocs),
|
|
248
|
+
outputPath: join(docsPath, "README.md")
|
|
249
|
+
});
|
|
250
|
+
tasks.push({
|
|
251
|
+
id: `task-${++taskId}`,
|
|
252
|
+
type: "document",
|
|
253
|
+
agentType: "architect",
|
|
254
|
+
description: "Document system architecture",
|
|
255
|
+
prompt: buildArchitectureDocPrompt(services),
|
|
256
|
+
outputPath: join(docsPath, "concepts", "architecture", "system-overview.md")
|
|
257
|
+
});
|
|
258
|
+
for (const service of services) {
|
|
259
|
+
tasks.push({
|
|
260
|
+
id: `task-${++taskId}`,
|
|
261
|
+
type: "document",
|
|
262
|
+
agentType: "coder",
|
|
263
|
+
description: `Document ${service.name} service overview`,
|
|
264
|
+
prompt: buildServiceDocPrompt(service),
|
|
265
|
+
outputPath: join(docsPath, "services", service.name, "README.md")
|
|
266
|
+
});
|
|
267
|
+
if (service.type === "api" || service.type === "backend") {
|
|
268
|
+
tasks.push({
|
|
269
|
+
id: `task-${++taskId}`,
|
|
270
|
+
type: "document",
|
|
271
|
+
agentType: "coder",
|
|
272
|
+
description: `Document ${service.name} API endpoints`,
|
|
273
|
+
prompt: buildApiDocPrompt(service),
|
|
274
|
+
outputPath: join(docsPath, "services", service.name, "api-reference.md")
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
if (service.type === "backend" || service.type === "api") {
|
|
278
|
+
tasks.push({
|
|
279
|
+
id: `task-${++taskId}`,
|
|
280
|
+
type: "document",
|
|
281
|
+
agentType: "analyst",
|
|
282
|
+
description: `Document ${service.name} data models`,
|
|
283
|
+
prompt: buildDataModelPrompt(service),
|
|
284
|
+
outputPath: join(docsPath, "services", service.name, "data-models.md")
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
if (service.type === "frontend" || service.type === "admin") {
|
|
288
|
+
tasks.push({
|
|
289
|
+
id: `task-${++taskId}`,
|
|
290
|
+
type: "document",
|
|
291
|
+
agentType: "coder",
|
|
292
|
+
description: `Document ${service.name} components`,
|
|
293
|
+
prompt: buildComponentDocPrompt(service),
|
|
294
|
+
outputPath: join(docsPath, "services", service.name, "components.md")
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (services.length > 1) {
|
|
299
|
+
tasks.push({
|
|
300
|
+
id: `task-${++taskId}`,
|
|
301
|
+
type: "document",
|
|
302
|
+
agentType: "architect",
|
|
303
|
+
description: "Document service integrations",
|
|
304
|
+
prompt: buildIntegrationDocPrompt(services),
|
|
305
|
+
outputPath: join(docsPath, "integrations", "service-integration.md")
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
if (options.includeSops) {
|
|
309
|
+
tasks.push({
|
|
310
|
+
id: `task-${++taskId}`,
|
|
311
|
+
type: "sop",
|
|
312
|
+
agentType: "analyst",
|
|
313
|
+
description: "Analyze and integrate SOP compliance",
|
|
314
|
+
prompt: buildSopAnalysisPrompt(services),
|
|
315
|
+
outputPath: join(docsPath, "standards", "sop-compliance.md")
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
return tasks;
|
|
319
|
+
}
|
|
320
|
+
async function executeCultivationSwarm(tasks, result, options) {
|
|
321
|
+
const maxAgents = options.maxAgents || 4;
|
|
322
|
+
const independentTasks = tasks.filter((t) => !t.dependencies || t.dependencies.length === 0);
|
|
323
|
+
const dependentTasks = tasks.filter((t) => t.dependencies && t.dependencies.length > 0);
|
|
324
|
+
for (let i = 0; i < independentTasks.length; i += maxAgents) {
|
|
325
|
+
const batch = independentTasks.slice(i, i + maxAgents);
|
|
326
|
+
const batchResults = await Promise.allSettled(
|
|
327
|
+
batch.map((task) => executeSwarmTask(task))
|
|
328
|
+
);
|
|
329
|
+
for (let j = 0; j < batchResults.length; j++) {
|
|
330
|
+
const task = batch[j];
|
|
331
|
+
const taskResult = batchResults[j];
|
|
332
|
+
if (taskResult.status === "fulfilled" && taskResult.value.success) {
|
|
333
|
+
if (task.outputPath) {
|
|
334
|
+
result.documentsGenerated.push(task.outputPath);
|
|
335
|
+
}
|
|
336
|
+
} else {
|
|
337
|
+
const error = taskResult.status === "rejected" ? taskResult.reason : taskResult.value.error;
|
|
338
|
+
result.errors.push(`Task ${task.id} failed: ${error}`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
for (const task of dependentTasks) {
|
|
343
|
+
try {
|
|
344
|
+
const taskResult = await executeSwarmTask(task, options);
|
|
345
|
+
if (taskResult.success && task.outputPath) {
|
|
346
|
+
result.documentsGenerated.push(task.outputPath);
|
|
347
|
+
} else {
|
|
348
|
+
result.errors.push(`Task ${task.id} failed: ${taskResult.error}`);
|
|
349
|
+
}
|
|
350
|
+
} catch (error) {
|
|
351
|
+
result.errors.push(`Task ${task.id} failed: ${error}`);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
async function executeSwarmTask(task, options) {
|
|
356
|
+
return new Promise((resolve) => {
|
|
357
|
+
const agentProcess = spawn("npx", [
|
|
358
|
+
"claude-flow@alpha",
|
|
359
|
+
"agent",
|
|
360
|
+
"spawn",
|
|
361
|
+
"--type",
|
|
362
|
+
task.agentType,
|
|
363
|
+
"--task",
|
|
364
|
+
task.prompt.slice(0, 1e3)
|
|
365
|
+
// Truncate for CLI
|
|
366
|
+
], {
|
|
367
|
+
shell: true,
|
|
368
|
+
timeout: 12e4
|
|
369
|
+
});
|
|
370
|
+
let output = "";
|
|
371
|
+
let errorOutput = "";
|
|
372
|
+
agentProcess.stdout?.on("data", (data) => {
|
|
373
|
+
output += data.toString();
|
|
374
|
+
});
|
|
375
|
+
agentProcess.stderr?.on("data", (data) => {
|
|
376
|
+
errorOutput += data.toString();
|
|
377
|
+
});
|
|
378
|
+
agentProcess.on("close", (code) => {
|
|
379
|
+
if (code === 0 || output.length > 0) {
|
|
380
|
+
if (task.outputPath && output.length > 0) {
|
|
381
|
+
try {
|
|
382
|
+
const dir = dirname(task.outputPath);
|
|
383
|
+
if (!existsSync(dir)) {
|
|
384
|
+
mkdirSync(dir, { recursive: true });
|
|
385
|
+
}
|
|
386
|
+
writeFileSync(task.outputPath, output);
|
|
387
|
+
} catch (e) {
|
|
388
|
+
writeTemplateDoc(task);
|
|
389
|
+
}
|
|
390
|
+
} else {
|
|
391
|
+
writeTemplateDoc(task);
|
|
392
|
+
}
|
|
393
|
+
resolve({ success: true, output });
|
|
394
|
+
} else {
|
|
395
|
+
writeTemplateDoc(task);
|
|
396
|
+
resolve({ success: true, output: "Generated from template" });
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
agentProcess.on("error", () => {
|
|
400
|
+
writeTemplateDoc(task);
|
|
401
|
+
resolve({ success: true, output: "Generated from template (fallback)" });
|
|
402
|
+
});
|
|
403
|
+
setTimeout(() => {
|
|
404
|
+
agentProcess.kill();
|
|
405
|
+
writeTemplateDoc(task);
|
|
406
|
+
resolve({ success: true, output: "Generated from template (timeout)" });
|
|
407
|
+
}, 6e4);
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
function writeTemplateDoc(task) {
|
|
411
|
+
if (!task.outputPath) return;
|
|
412
|
+
const dir = dirname(task.outputPath);
|
|
413
|
+
if (!existsSync(dir)) {
|
|
414
|
+
mkdirSync(dir, { recursive: true });
|
|
415
|
+
}
|
|
416
|
+
const title = basename(task.outputPath, ".md").split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
417
|
+
const content = `---
|
|
418
|
+
title: ${title}
|
|
419
|
+
type: ${task.type}
|
|
420
|
+
status: draft
|
|
421
|
+
created: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
422
|
+
tags: [auto-generated, needs-review]
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
# ${title}
|
|
426
|
+
|
|
427
|
+
${task.description}
|
|
428
|
+
|
|
429
|
+
## Overview
|
|
430
|
+
|
|
431
|
+
*This document was auto-generated and needs to be completed.*
|
|
432
|
+
|
|
433
|
+
${task.prompt.split("\n").slice(0, 10).join("\n")}
|
|
434
|
+
|
|
435
|
+
## Next Steps
|
|
436
|
+
|
|
437
|
+
- [ ] Review and expand this document
|
|
438
|
+
- [ ] Add specific implementation details
|
|
439
|
+
- [ ] Link related documentation
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
> Auto-generated by kg-agent cultivate
|
|
443
|
+
`;
|
|
444
|
+
writeFileSync(task.outputPath, content);
|
|
445
|
+
}
|
|
446
|
+
function buildProjectOverviewPrompt(services, existingDocs) {
|
|
447
|
+
return `Analyze this project and create a comprehensive README.md.
|
|
448
|
+
|
|
449
|
+
Services found: ${services.map((s) => `${s.name} (${s.type})`).join(", ")}
|
|
450
|
+
Existing docs: ${existingDocs.length} files
|
|
451
|
+
|
|
452
|
+
Create a project overview including:
|
|
453
|
+
- Project purpose and goals
|
|
454
|
+
- Architecture summary
|
|
455
|
+
- Services overview
|
|
456
|
+
- Getting started guide
|
|
457
|
+
- Development setup
|
|
458
|
+
`;
|
|
459
|
+
}
|
|
460
|
+
function buildArchitectureDocPrompt(services) {
|
|
461
|
+
const serviceInfo = services.map(
|
|
462
|
+
(s) => `- ${s.name}: ${s.type} service using ${s.languages.join(", ")} with ${s.frameworks.join(", ") || "no specific framework"}`
|
|
463
|
+
).join("\n");
|
|
464
|
+
return `Document the system architecture for this multi-service application.
|
|
465
|
+
|
|
466
|
+
Services:
|
|
467
|
+
${serviceInfo}
|
|
468
|
+
|
|
469
|
+
Include:
|
|
470
|
+
- High-level architecture diagram (mermaid)
|
|
471
|
+
- Service responsibilities
|
|
472
|
+
- Data flow between services
|
|
473
|
+
- Technology stack
|
|
474
|
+
- Scalability considerations
|
|
475
|
+
`;
|
|
476
|
+
}
|
|
477
|
+
function buildServiceDocPrompt(service) {
|
|
478
|
+
return `Document the ${service.name} service.
|
|
479
|
+
|
|
480
|
+
Type: ${service.type}
|
|
481
|
+
Languages: ${service.languages.join(", ")}
|
|
482
|
+
Frameworks: ${service.frameworks.join(", ") || "None detected"}
|
|
483
|
+
Source files: ${service.sourceFiles.length}
|
|
484
|
+
Existing docs: ${service.existingDocs.length}
|
|
485
|
+
|
|
486
|
+
Create documentation including:
|
|
487
|
+
- Service purpose and responsibilities
|
|
488
|
+
- Key components/modules
|
|
489
|
+
- Configuration options
|
|
490
|
+
- Dependencies
|
|
491
|
+
- Usage examples
|
|
492
|
+
`;
|
|
493
|
+
}
|
|
494
|
+
function buildApiDocPrompt(service) {
|
|
495
|
+
return `Document the API endpoints for ${service.name}.
|
|
496
|
+
|
|
497
|
+
Analyze the source files and document:
|
|
498
|
+
- Available endpoints (REST/GraphQL)
|
|
499
|
+
- Request/response formats
|
|
500
|
+
- Authentication requirements
|
|
501
|
+
- Error handling
|
|
502
|
+
- Rate limiting (if applicable)
|
|
503
|
+
- Example requests/responses
|
|
504
|
+
`;
|
|
505
|
+
}
|
|
506
|
+
function buildDataModelPrompt(service) {
|
|
507
|
+
return `Document the data models for ${service.name}.
|
|
508
|
+
|
|
509
|
+
Analyze the source files and document:
|
|
510
|
+
- Database schemas
|
|
511
|
+
- Entity relationships (ERD if applicable)
|
|
512
|
+
- Data validation rules
|
|
513
|
+
- Migrations strategy
|
|
514
|
+
- Data access patterns
|
|
515
|
+
`;
|
|
516
|
+
}
|
|
517
|
+
function buildComponentDocPrompt(service) {
|
|
518
|
+
return `Document the UI components for ${service.name}.
|
|
519
|
+
|
|
520
|
+
Frameworks: ${service.frameworks.join(", ")}
|
|
521
|
+
|
|
522
|
+
Document:
|
|
523
|
+
- Component hierarchy
|
|
524
|
+
- Reusable components
|
|
525
|
+
- State management
|
|
526
|
+
- Styling approach
|
|
527
|
+
- Component props/interfaces
|
|
528
|
+
`;
|
|
529
|
+
}
|
|
530
|
+
function buildIntegrationDocPrompt(services) {
|
|
531
|
+
return `Document how the services integrate with each other.
|
|
532
|
+
|
|
533
|
+
Services: ${services.map((s) => s.name).join(", ")}
|
|
534
|
+
|
|
535
|
+
Document:
|
|
536
|
+
- Service communication patterns
|
|
537
|
+
- API contracts between services
|
|
538
|
+
- Shared data models
|
|
539
|
+
- Authentication flow across services
|
|
540
|
+
- Error handling across services
|
|
541
|
+
`;
|
|
542
|
+
}
|
|
543
|
+
function buildSopAnalysisPrompt(services) {
|
|
544
|
+
return `Analyze project for SOP (Standard Operating Procedure) compliance.
|
|
545
|
+
|
|
546
|
+
Services: ${services.map((s) => s.name).join(", ")}
|
|
547
|
+
|
|
548
|
+
Check compliance with:
|
|
549
|
+
- AI-SDLC SOPs for development practices
|
|
550
|
+
- Documentation requirements
|
|
551
|
+
- Testing requirements
|
|
552
|
+
- Security requirements
|
|
553
|
+
- Deployment requirements
|
|
554
|
+
|
|
555
|
+
Generate:
|
|
556
|
+
- Compliance score per category
|
|
557
|
+
- Gap analysis
|
|
558
|
+
- Recommendations for improvement
|
|
559
|
+
- Priority remediation items
|
|
560
|
+
`;
|
|
561
|
+
}
|
|
562
|
+
async function generateDevelopmentPlan(services, docsPath, options) {
|
|
563
|
+
const phases = [
|
|
564
|
+
{
|
|
565
|
+
id: "phase-1",
|
|
566
|
+
name: "Foundation",
|
|
567
|
+
description: "Set up infrastructure, authentication, and core services",
|
|
568
|
+
priority: "critical",
|
|
569
|
+
estimatedEffort: "2-3 weeks",
|
|
570
|
+
dependencies: [],
|
|
571
|
+
services: services.map((s) => s.name),
|
|
572
|
+
tasks: [
|
|
573
|
+
{
|
|
574
|
+
id: "task-1-1",
|
|
575
|
+
title: "Infrastructure Setup",
|
|
576
|
+
description: "Set up development, staging, and production environments",
|
|
577
|
+
service: "all",
|
|
578
|
+
type: "infrastructure",
|
|
579
|
+
priority: "critical",
|
|
580
|
+
estimatedEffort: "3-5 days",
|
|
581
|
+
dependencies: [],
|
|
582
|
+
acceptance: ["Environments accessible", "CI/CD pipeline working"]
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
id: "task-1-2",
|
|
586
|
+
title: "Authentication System",
|
|
587
|
+
description: "Implement authentication and authorization",
|
|
588
|
+
service: services.find((s) => s.type === "backend" || s.type === "api")?.name || "backend",
|
|
589
|
+
type: "feature",
|
|
590
|
+
priority: "critical",
|
|
591
|
+
estimatedEffort: "3-5 days",
|
|
592
|
+
dependencies: ["task-1-1"],
|
|
593
|
+
acceptance: ["User login/logout working", "Role-based access control"]
|
|
594
|
+
}
|
|
595
|
+
],
|
|
596
|
+
deliverables: ["Working development environment", "Authentication system", "CI/CD pipeline"]
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
id: "phase-2",
|
|
600
|
+
name: "Core Features",
|
|
601
|
+
description: "Implement core functionality for each service",
|
|
602
|
+
priority: "high",
|
|
603
|
+
estimatedEffort: "4-6 weeks",
|
|
604
|
+
dependencies: ["phase-1"],
|
|
605
|
+
services: services.map((s) => s.name),
|
|
606
|
+
tasks: services.map((s, i) => ({
|
|
607
|
+
id: `task-2-${i + 1}`,
|
|
608
|
+
title: `${s.name} Core Features`,
|
|
609
|
+
description: `Implement core functionality for ${s.name} service`,
|
|
610
|
+
service: s.name,
|
|
611
|
+
type: "feature",
|
|
612
|
+
priority: "high",
|
|
613
|
+
estimatedEffort: "1-2 weeks",
|
|
614
|
+
dependencies: ["phase-1"],
|
|
615
|
+
acceptance: ["Core features working", "Unit tests passing"]
|
|
616
|
+
})),
|
|
617
|
+
deliverables: services.map((s) => `${s.name} core features complete`)
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
id: "phase-3",
|
|
621
|
+
name: "Integration",
|
|
622
|
+
description: "Connect services and implement data flow",
|
|
623
|
+
priority: "high",
|
|
624
|
+
estimatedEffort: "2-3 weeks",
|
|
625
|
+
dependencies: ["phase-2"],
|
|
626
|
+
services: services.map((s) => s.name),
|
|
627
|
+
tasks: [
|
|
628
|
+
{
|
|
629
|
+
id: "task-3-1",
|
|
630
|
+
title: "Service Integration",
|
|
631
|
+
description: "Connect all services and implement API contracts",
|
|
632
|
+
service: "all",
|
|
633
|
+
type: "feature",
|
|
634
|
+
priority: "high",
|
|
635
|
+
estimatedEffort: "1-2 weeks",
|
|
636
|
+
dependencies: ["phase-2"],
|
|
637
|
+
acceptance: ["Services communicating", "Data flow working"]
|
|
638
|
+
}
|
|
639
|
+
],
|
|
640
|
+
deliverables: ["Integrated system", "End-to-end tests passing"]
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
id: "phase-4",
|
|
644
|
+
name: "Polish",
|
|
645
|
+
description: "UI/UX improvements, performance optimization, comprehensive testing",
|
|
646
|
+
priority: "medium",
|
|
647
|
+
estimatedEffort: "2-3 weeks",
|
|
648
|
+
dependencies: ["phase-3"],
|
|
649
|
+
services: services.filter((s) => s.type === "frontend" || s.type === "admin").map((s) => s.name),
|
|
650
|
+
tasks: [
|
|
651
|
+
{
|
|
652
|
+
id: "task-4-1",
|
|
653
|
+
title: "UI/UX Polish",
|
|
654
|
+
description: "Improve user interface and experience",
|
|
655
|
+
service: services.find((s) => s.type === "frontend")?.name || "frontend",
|
|
656
|
+
type: "feature",
|
|
657
|
+
priority: "medium",
|
|
658
|
+
estimatedEffort: "1 week",
|
|
659
|
+
dependencies: ["phase-3"],
|
|
660
|
+
acceptance: ["UI responsive", "Accessibility standards met"]
|
|
661
|
+
},
|
|
662
|
+
{
|
|
663
|
+
id: "task-4-2",
|
|
664
|
+
title: "Performance Optimization",
|
|
665
|
+
description: "Optimize application performance",
|
|
666
|
+
service: "all",
|
|
667
|
+
type: "feature",
|
|
668
|
+
priority: "medium",
|
|
669
|
+
estimatedEffort: "1 week",
|
|
670
|
+
dependencies: ["phase-3"],
|
|
671
|
+
acceptance: ["Load times < 3s", "Performance benchmarks met"]
|
|
672
|
+
}
|
|
673
|
+
],
|
|
674
|
+
deliverables: ["Polished UI", "Performance optimized", "Comprehensive test coverage"]
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
id: "phase-5",
|
|
678
|
+
name: "Deployment",
|
|
679
|
+
description: "Deploy to staging and production",
|
|
680
|
+
priority: "high",
|
|
681
|
+
estimatedEffort: "1-2 weeks",
|
|
682
|
+
dependencies: ["phase-4"],
|
|
683
|
+
services: services.map((s) => s.name),
|
|
684
|
+
tasks: [
|
|
685
|
+
{
|
|
686
|
+
id: "task-5-1",
|
|
687
|
+
title: "Staging Deployment",
|
|
688
|
+
description: "Deploy to staging environment",
|
|
689
|
+
service: "all",
|
|
690
|
+
type: "deployment",
|
|
691
|
+
priority: "high",
|
|
692
|
+
estimatedEffort: "2-3 days",
|
|
693
|
+
dependencies: ["phase-4"],
|
|
694
|
+
acceptance: ["Staging environment working", "QA sign-off"]
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
id: "task-5-2",
|
|
698
|
+
title: "Production Deployment",
|
|
699
|
+
description: "Deploy to production environment",
|
|
700
|
+
service: "all",
|
|
701
|
+
type: "deployment",
|
|
702
|
+
priority: "high",
|
|
703
|
+
estimatedEffort: "2-3 days",
|
|
704
|
+
dependencies: ["task-5-1"],
|
|
705
|
+
acceptance: ["Production live", "Monitoring active"]
|
|
706
|
+
}
|
|
707
|
+
],
|
|
708
|
+
deliverables: ["Staging deployed", "Production deployed", "Monitoring configured"]
|
|
709
|
+
}
|
|
710
|
+
];
|
|
711
|
+
const planPath = join(docsPath, "planning", "development-plan.md");
|
|
712
|
+
const planDir = dirname(planPath);
|
|
713
|
+
if (!existsSync(planDir)) {
|
|
714
|
+
mkdirSync(planDir, { recursive: true });
|
|
715
|
+
}
|
|
716
|
+
const planContent = generateDevPlanMarkdown(phases, services);
|
|
717
|
+
writeFileSync(planPath, planContent);
|
|
718
|
+
return {
|
|
719
|
+
phases,
|
|
720
|
+
totalEstimate: "12-18 weeks",
|
|
721
|
+
criticalPath: ["phase-1", "phase-2", "phase-3", "phase-5"]
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
function generateDevPlanMarkdown(phases, services) {
|
|
725
|
+
let md = `---
|
|
726
|
+
title: Development Plan
|
|
727
|
+
type: planning
|
|
728
|
+
status: active
|
|
729
|
+
created: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
730
|
+
tags: [planning, development, phases]
|
|
731
|
+
---
|
|
732
|
+
|
|
733
|
+
# Development Plan
|
|
734
|
+
|
|
735
|
+
## Overview
|
|
736
|
+
|
|
737
|
+
This document outlines the phased development approach for building out the project.
|
|
738
|
+
|
|
739
|
+
### Services
|
|
740
|
+
|
|
741
|
+
${services.map((s) => `- **${s.name}** (${s.type}): ${s.languages.join(", ")}`).join("\n")}
|
|
742
|
+
|
|
743
|
+
### Timeline
|
|
744
|
+
|
|
745
|
+
| Phase | Name | Duration | Priority |
|
|
746
|
+
|-------|------|----------|----------|
|
|
747
|
+
${phases.map((p) => `| ${p.id} | ${p.name} | ${p.estimatedEffort} | ${p.priority} |`).join("\n")}
|
|
748
|
+
|
|
749
|
+
---
|
|
750
|
+
|
|
751
|
+
`;
|
|
752
|
+
for (const phase of phases) {
|
|
753
|
+
md += `## ${phase.name}
|
|
754
|
+
|
|
755
|
+
**Priority:** ${phase.priority}
|
|
756
|
+
**Estimated Effort:** ${phase.estimatedEffort}
|
|
757
|
+
**Dependencies:** ${phase.dependencies.length > 0 ? phase.dependencies.join(", ") : "None"}
|
|
758
|
+
|
|
759
|
+
${phase.description}
|
|
760
|
+
|
|
761
|
+
### Tasks
|
|
762
|
+
|
|
763
|
+
${phase.tasks.map((t) => `
|
|
764
|
+
#### ${t.title}
|
|
765
|
+
|
|
766
|
+
- **Service:** ${t.service}
|
|
767
|
+
- **Type:** ${t.type}
|
|
768
|
+
- **Priority:** ${t.priority}
|
|
769
|
+
- **Effort:** ${t.estimatedEffort}
|
|
770
|
+
- **Dependencies:** ${t.dependencies.length > 0 ? t.dependencies.join(", ") : "None"}
|
|
771
|
+
|
|
772
|
+
${t.description}
|
|
773
|
+
|
|
774
|
+
**Acceptance Criteria:**
|
|
775
|
+
${t.acceptance.map((a) => `- [ ] ${a}`).join("\n")}
|
|
776
|
+
`).join("\n")}
|
|
777
|
+
|
|
778
|
+
### Deliverables
|
|
779
|
+
|
|
780
|
+
${phase.deliverables.map((d) => `- [ ] ${d}`).join("\n")}
|
|
781
|
+
|
|
782
|
+
---
|
|
783
|
+
|
|
784
|
+
`;
|
|
785
|
+
}
|
|
786
|
+
md += `
|
|
787
|
+
## Critical Path
|
|
788
|
+
|
|
789
|
+
The critical path for this project includes:
|
|
790
|
+
${phases.filter((p) => p.priority === "critical" || p.priority === "high").map((p) => `1. **${p.name}** - ${p.description}`).join("\n")}
|
|
791
|
+
|
|
792
|
+
---
|
|
793
|
+
> Auto-generated by kg-agent cultivate
|
|
794
|
+
`;
|
|
795
|
+
return md;
|
|
796
|
+
}
|
|
797
|
+
async function generateInfrastructurePlan(services, docsPath, options) {
|
|
798
|
+
const plan = {
|
|
799
|
+
environments: ["development", "staging", "production"],
|
|
800
|
+
services: {},
|
|
801
|
+
deployment: "containerized"
|
|
802
|
+
};
|
|
803
|
+
for (const service of services) {
|
|
804
|
+
plan.services[service.name] = service.type;
|
|
805
|
+
}
|
|
806
|
+
const planPath = join(docsPath, "planning", "infrastructure-plan.md");
|
|
807
|
+
const planDir = dirname(planPath);
|
|
808
|
+
if (!existsSync(planDir)) {
|
|
809
|
+
mkdirSync(planDir, { recursive: true });
|
|
810
|
+
}
|
|
811
|
+
const planContent = generateInfraPlanMarkdown(plan, services);
|
|
812
|
+
writeFileSync(planPath, planContent);
|
|
813
|
+
return plan;
|
|
814
|
+
}
|
|
815
|
+
function generateInfraPlanMarkdown(plan, services) {
|
|
816
|
+
return `---
|
|
817
|
+
title: Infrastructure Plan
|
|
818
|
+
type: planning
|
|
819
|
+
status: active
|
|
820
|
+
created: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
821
|
+
tags: [infrastructure, deployment, devops]
|
|
822
|
+
---
|
|
823
|
+
|
|
824
|
+
# Infrastructure Plan
|
|
825
|
+
|
|
826
|
+
## Overview
|
|
827
|
+
|
|
828
|
+
This document outlines the infrastructure and deployment strategy for all environments.
|
|
829
|
+
|
|
830
|
+
## Environments
|
|
831
|
+
|
|
832
|
+
### Development Environment
|
|
833
|
+
|
|
834
|
+
**Purpose:** Local development and testing
|
|
835
|
+
|
|
836
|
+
**Components:**
|
|
837
|
+
- Docker Compose for local services
|
|
838
|
+
- Local database instances
|
|
839
|
+
- Mock external services
|
|
840
|
+
|
|
841
|
+
**Setup:**
|
|
842
|
+
\`\`\`bash
|
|
843
|
+
# Clone repository
|
|
844
|
+
git clone <repo-url>
|
|
845
|
+
cd <project>
|
|
846
|
+
|
|
847
|
+
# Start development environment
|
|
848
|
+
docker-compose up -d
|
|
849
|
+
|
|
850
|
+
# Install dependencies
|
|
851
|
+
npm install # or appropriate package manager
|
|
852
|
+
\`\`\`
|
|
853
|
+
|
|
854
|
+
### Staging Environment
|
|
855
|
+
|
|
856
|
+
**Purpose:** Pre-production testing and QA
|
|
857
|
+
|
|
858
|
+
**Infrastructure:**
|
|
859
|
+
- Cloud provider: AWS/GCP/Azure (TBD)
|
|
860
|
+
- Container orchestration: Kubernetes/ECS
|
|
861
|
+
- Database: Managed database service
|
|
862
|
+
|
|
863
|
+
**Services:**
|
|
864
|
+
${services.map((s) => `- **${s.name}**: ${s.type} service`).join("\n")}
|
|
865
|
+
|
|
866
|
+
**CI/CD Pipeline:**
|
|
867
|
+
1. Push to staging branch
|
|
868
|
+
2. Run automated tests
|
|
869
|
+
3. Build container images
|
|
870
|
+
4. Deploy to staging cluster
|
|
871
|
+
5. Run integration tests
|
|
872
|
+
|
|
873
|
+
### Production Environment
|
|
874
|
+
|
|
875
|
+
**Purpose:** Live production system
|
|
876
|
+
|
|
877
|
+
**Infrastructure:**
|
|
878
|
+
- High-availability configuration
|
|
879
|
+
- Auto-scaling enabled
|
|
880
|
+
- CDN for static assets
|
|
881
|
+
- Managed database with read replicas
|
|
882
|
+
|
|
883
|
+
**Monitoring:**
|
|
884
|
+
- Application performance monitoring
|
|
885
|
+
- Log aggregation
|
|
886
|
+
- Alerting and on-call rotation
|
|
887
|
+
|
|
888
|
+
## Service Architecture
|
|
889
|
+
|
|
890
|
+
\`\`\`mermaid
|
|
891
|
+
graph TB
|
|
892
|
+
subgraph Frontend
|
|
893
|
+
${services.filter((s) => s.type === "frontend" || s.type === "admin").map((s) => `${s.name}[${s.name}]`).join("\n ")}
|
|
894
|
+
end
|
|
895
|
+
|
|
896
|
+
subgraph Backend
|
|
897
|
+
${services.filter((s) => s.type === "backend" || s.type === "api").map((s) => `${s.name}[${s.name}]`).join("\n ")}
|
|
898
|
+
end
|
|
899
|
+
|
|
900
|
+
subgraph Data
|
|
901
|
+
DB[(Database)]
|
|
902
|
+
Cache[(Cache)]
|
|
903
|
+
end
|
|
904
|
+
|
|
905
|
+
Frontend --> Backend
|
|
906
|
+
Backend --> Data
|
|
907
|
+
\`\`\`
|
|
908
|
+
|
|
909
|
+
## Deployment Strategy
|
|
910
|
+
|
|
911
|
+
### Development
|
|
912
|
+
- Local Docker Compose
|
|
913
|
+
- Hot reloading enabled
|
|
914
|
+
- Debug logging
|
|
915
|
+
|
|
916
|
+
### Staging
|
|
917
|
+
- Kubernetes deployment
|
|
918
|
+
- Automated from CI/CD
|
|
919
|
+
- Mirrors production configuration
|
|
920
|
+
|
|
921
|
+
### Production
|
|
922
|
+
- Blue-green deployment
|
|
923
|
+
- Automated rollback on failures
|
|
924
|
+
- Canary releases for major changes
|
|
925
|
+
|
|
926
|
+
## Security Considerations
|
|
927
|
+
|
|
928
|
+
- [ ] SSL/TLS certificates
|
|
929
|
+
- [ ] API authentication
|
|
930
|
+
- [ ] Secret management (Vault/AWS Secrets Manager)
|
|
931
|
+
- [ ] Network security groups
|
|
932
|
+
- [ ] WAF configuration
|
|
933
|
+
|
|
934
|
+
## Backup and Disaster Recovery
|
|
935
|
+
|
|
936
|
+
- Database backups: Daily automated backups
|
|
937
|
+
- Retention: 30 days
|
|
938
|
+
- RTO: 4 hours
|
|
939
|
+
- RPO: 1 hour
|
|
940
|
+
|
|
941
|
+
---
|
|
942
|
+
> Auto-generated by kg-agent cultivate
|
|
943
|
+
`;
|
|
944
|
+
}
|
|
945
|
+
async function analyzeSopCompliance(projectRoot, docsPath, services) {
|
|
946
|
+
const compliance = {
|
|
947
|
+
score: 0,
|
|
948
|
+
gaps: [],
|
|
949
|
+
recommendations: []
|
|
950
|
+
};
|
|
951
|
+
let totalChecks = 0;
|
|
952
|
+
let passedChecks = 0;
|
|
953
|
+
const requiredDocs = [
|
|
954
|
+
"README.md",
|
|
955
|
+
"concepts/architecture",
|
|
956
|
+
"guides/getting-started",
|
|
957
|
+
"standards"
|
|
958
|
+
];
|
|
959
|
+
for (const doc of requiredDocs) {
|
|
960
|
+
totalChecks++;
|
|
961
|
+
if (existsSync(join(docsPath, doc))) {
|
|
962
|
+
passedChecks++;
|
|
963
|
+
} else {
|
|
964
|
+
compliance.gaps.push(`Missing documentation: ${doc}`);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
for (const service of services) {
|
|
968
|
+
totalChecks++;
|
|
969
|
+
const serviceDoc = join(docsPath, "services", service.name, "README.md");
|
|
970
|
+
if (existsSync(serviceDoc)) {
|
|
971
|
+
passedChecks++;
|
|
972
|
+
} else {
|
|
973
|
+
compliance.gaps.push(`Missing service documentation: ${service.name}`);
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
compliance.score = totalChecks > 0 ? Math.round(passedChecks / totalChecks * 100) : 0;
|
|
977
|
+
if (compliance.gaps.length > 0) {
|
|
978
|
+
compliance.recommendations.push("Complete missing documentation items");
|
|
979
|
+
}
|
|
980
|
+
if (!existsSync(join(docsPath, "standards"))) {
|
|
981
|
+
compliance.recommendations.push("Add coding standards documentation");
|
|
982
|
+
}
|
|
983
|
+
if (!existsSync(join(docsPath, "guides", "getting-started"))) {
|
|
984
|
+
compliance.recommendations.push("Add getting started guide for new developers");
|
|
985
|
+
}
|
|
986
|
+
const reportPath = join(docsPath, "standards", "sop-compliance.md");
|
|
987
|
+
const reportDir = dirname(reportPath);
|
|
988
|
+
if (!existsSync(reportDir)) {
|
|
989
|
+
mkdirSync(reportDir, { recursive: true });
|
|
990
|
+
}
|
|
991
|
+
const reportContent = `---
|
|
992
|
+
title: SOP Compliance Report
|
|
993
|
+
type: standard
|
|
994
|
+
status: active
|
|
995
|
+
created: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
996
|
+
tags: [sop, compliance, standards]
|
|
997
|
+
---
|
|
998
|
+
|
|
999
|
+
# SOP Compliance Report
|
|
1000
|
+
|
|
1001
|
+
## Score: ${compliance.score}%
|
|
1002
|
+
|
|
1003
|
+
## Gaps
|
|
1004
|
+
|
|
1005
|
+
${compliance.gaps.length > 0 ? compliance.gaps.map((g) => `- ${g}`).join("\n") : "No gaps identified."}
|
|
1006
|
+
|
|
1007
|
+
## Recommendations
|
|
1008
|
+
|
|
1009
|
+
${compliance.recommendations.length > 0 ? compliance.recommendations.map((r) => `- ${r}`).join("\n") : "No recommendations at this time."}
|
|
1010
|
+
|
|
1011
|
+
---
|
|
1012
|
+
> Auto-generated by kg-agent cultivate
|
|
1013
|
+
`;
|
|
1014
|
+
writeFileSync(reportPath, reportContent);
|
|
1015
|
+
return compliance;
|
|
1016
|
+
}
|
|
1017
|
+
export {
|
|
1018
|
+
cultivateDocs
|
|
1019
|
+
};
|
|
1020
|
+
//# sourceMappingURL=doc-cultivator.js.map
|