@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.
@@ -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