@weavelogic/knowledge-graph-agent 0.11.3 → 0.11.5
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/cultivation/deep-analyzer.d.ts +21 -0
- package/dist/cultivation/deep-analyzer.d.ts.map +1 -1
- package/dist/cultivation/deep-analyzer.js +210 -5
- package/dist/cultivation/deep-analyzer.js.map +1 -1
- package/dist/cultivation/migration-orchestrator.d.ts +31 -0
- package/dist/cultivation/migration-orchestrator.d.ts.map +1 -1
- package/dist/cultivation/migration-orchestrator.js +250 -10
- package/dist/cultivation/migration-orchestrator.js.map +1 -1
- 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
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @module cultivation/deep-analyzer
|
|
13
13
|
*/
|
|
14
|
+
import { ComplianceCheckResult, GapAnalysisResult } from '../sops/index.js';
|
|
14
15
|
/**
|
|
15
16
|
* Deep analyzer options
|
|
16
17
|
*/
|
|
@@ -59,6 +60,10 @@ export interface DeepAnalysisResult {
|
|
|
59
60
|
duration: number;
|
|
60
61
|
errors: string[];
|
|
61
62
|
mode: 'cli' | 'anthropic' | 'gemini' | 'static';
|
|
63
|
+
/** SOP compliance check result */
|
|
64
|
+
sopCompliance?: ComplianceCheckResult;
|
|
65
|
+
/** SOP gap analysis result */
|
|
66
|
+
sopGaps?: GapAnalysisResult;
|
|
62
67
|
}
|
|
63
68
|
/**
|
|
64
69
|
* DeepAnalyzer - Documentation cultivation with AI-powered analysis
|
|
@@ -161,6 +166,22 @@ export declare class DeepAnalyzer {
|
|
|
161
166
|
* Build context-aware prompt for documentation cultivation
|
|
162
167
|
*/
|
|
163
168
|
private buildPrompt;
|
|
169
|
+
/**
|
|
170
|
+
* Run SOP compliance check against the documentation
|
|
171
|
+
*/
|
|
172
|
+
private runSOPComplianceCheck;
|
|
173
|
+
/**
|
|
174
|
+
* Run SOP gap analysis on compliance results
|
|
175
|
+
*/
|
|
176
|
+
private runSOPGapAnalysis;
|
|
177
|
+
/**
|
|
178
|
+
* Write SOP gaps summary to analysis output
|
|
179
|
+
*/
|
|
180
|
+
private writeSOPGapsSummary;
|
|
181
|
+
/**
|
|
182
|
+
* Build SOP agent-specific instructions with gap context
|
|
183
|
+
*/
|
|
184
|
+
private buildSOPAgentInstructions;
|
|
164
185
|
/**
|
|
165
186
|
* Run analysis using Claude CLI
|
|
166
187
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deep-analyzer.d.ts","sourceRoot":"","sources":["../../src/cultivation/deep-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"deep-analyzer.d.ts","sourceRoot":"","sources":["../../src/cultivation/deep-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,EAGL,qBAAqB,EACrB,iBAAiB,EAIlB,MAAM,kBAAkB,CAAC;AAI1B;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mCAAmC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,KAAK,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAChD,kCAAkC;IAClC,aAAa,CAAC,EAAE,qBAAqB,CAAC;IACtC,8BAA8B;IAC9B,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;AA2DD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,iBAAiB,CAAyB;gBAEtC,OAAO,EAAE,mBAAmB;IAYxC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAI1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAI1B;;OAEG;IACH,OAAO,CAAC,eAAe;IASvB;;OAEG;IACH,OAAO,CAAC,eAAe;IASvB;;OAEG;IACH,OAAO,CAAC,cAAc;IAatB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAiD3B;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAKrC;;OAEG;IACG,qBAAqB,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAQ9E;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA6DzB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA+BxB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA0F9B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAe5B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA+B5B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAoJ5C;;OAEG;YACW,YAAY;IAwD1B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA4C5B;;OAEG;IACH,OAAO,CAAC,WAAW;IA+JnB;;OAEG;YACW,qBAAqB;IAyBnC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAwBzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA+C3B;;OAEG;IACH,OAAO,CAAC,yBAAyB;IA6FjC;;OAEG;YACW,UAAU;IA4BxB;;OAEG;YACW,gBAAgB;IA8B9B;;OAEG;YACW,aAAa;IA4B3B;;OAEG;IACH,OAAO,CAAC,eAAe;IAqBvB;;OAEG;IACH,OAAO,CAAC,YAAY;CA6BrB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAE7E;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,CAAC,CAG7B"}
|
|
@@ -2,6 +2,11 @@ import { execFileSync, execSync } from "child_process";
|
|
|
2
2
|
import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, statSync } from "fs";
|
|
3
3
|
import { resolve, join, extname, relative, basename } from "path";
|
|
4
4
|
import { createLogger } from "../utils/logger.js";
|
|
5
|
+
import { SOPPriority } from "../sops/types.js";
|
|
6
|
+
import "../sops/registry.js";
|
|
7
|
+
import { checkCompliance } from "../sops/compliance-checker.js";
|
|
8
|
+
import { analyzeGaps } from "../sops/gap-analyzer.js";
|
|
9
|
+
import "../sops/overlay-manager.js";
|
|
5
10
|
const logger = createLogger("deep-analyzer");
|
|
6
11
|
class DeepAnalyzer {
|
|
7
12
|
projectRoot;
|
|
@@ -359,6 +364,8 @@ class DeepAnalyzer {
|
|
|
359
364
|
needsWork: dirCoverage.filter((d) => d.needsDocumentation).length,
|
|
360
365
|
iteration
|
|
361
366
|
});
|
|
367
|
+
const sopCompliance = await this.runSOPComplianceCheck();
|
|
368
|
+
const sopGaps = sopCompliance ? this.runSOPGapAnalysis(sopCompliance) : void 0;
|
|
362
369
|
const agents = [
|
|
363
370
|
{
|
|
364
371
|
name: "Vision Synthesizer",
|
|
@@ -389,9 +396,20 @@ class DeepAnalyzer {
|
|
|
389
396
|
type: "connections",
|
|
390
397
|
task: "Identify relationships between concepts and suggest knowledge graph connections",
|
|
391
398
|
outputFile: "knowledge-connections.md"
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
name: "SOP Compliance Analyst",
|
|
402
|
+
type: "sop",
|
|
403
|
+
task: "Analyze AI-SDLC SOP compliance gaps and recommend documentation to address them",
|
|
404
|
+
outputFile: "sop-compliance-gaps.md"
|
|
392
405
|
}
|
|
393
406
|
];
|
|
394
|
-
logger.info("Executing cultivation agents", {
|
|
407
|
+
logger.info("Executing cultivation agents", {
|
|
408
|
+
agents: agents.length,
|
|
409
|
+
mode: "sequential",
|
|
410
|
+
iteration,
|
|
411
|
+
sopGapsCount: sopGaps?.totalGaps || 0
|
|
412
|
+
});
|
|
395
413
|
for (const agent of agents) {
|
|
396
414
|
const agentResult = await this.executeAgent(
|
|
397
415
|
agent,
|
|
@@ -399,10 +417,13 @@ class DeepAnalyzer {
|
|
|
399
417
|
documents,
|
|
400
418
|
keyDocs,
|
|
401
419
|
dirCoverage,
|
|
402
|
-
previousAnalysis
|
|
420
|
+
previousAnalysis,
|
|
421
|
+
sopGaps
|
|
403
422
|
);
|
|
404
423
|
result.results.push(agentResult);
|
|
405
424
|
}
|
|
425
|
+
result.sopCompliance = sopCompliance;
|
|
426
|
+
result.sopGaps = sopGaps;
|
|
406
427
|
this.saveAnalysisMetadata(result, dirCoverage);
|
|
407
428
|
result.agentsSpawned = result.results.length;
|
|
408
429
|
result.insightsCount = result.results.reduce((sum, r) => sum + r.insights.length, 0);
|
|
@@ -425,7 +446,7 @@ class DeepAnalyzer {
|
|
|
425
446
|
/**
|
|
426
447
|
* Execute a single agent
|
|
427
448
|
*/
|
|
428
|
-
async executeAgent(agent, mode, documents, keyDocs, dirCoverage, previousAnalysis) {
|
|
449
|
+
async executeAgent(agent, mode, documents, keyDocs, dirCoverage, previousAnalysis, sopGaps) {
|
|
429
450
|
const startTime = Date.now();
|
|
430
451
|
const outputPath = join(this.outputDir, agent.outputFile);
|
|
431
452
|
const result = {
|
|
@@ -438,7 +459,7 @@ class DeepAnalyzer {
|
|
|
438
459
|
};
|
|
439
460
|
try {
|
|
440
461
|
logger.info(`Executing agent: ${agent.name}`, { type: agent.type, mode });
|
|
441
|
-
const prompt = this.buildPrompt(agent, documents, keyDocs, dirCoverage, previousAnalysis);
|
|
462
|
+
const prompt = this.buildPrompt(agent, documents, keyDocs, dirCoverage, previousAnalysis, sopGaps);
|
|
442
463
|
let output;
|
|
443
464
|
if (mode === "cli") {
|
|
444
465
|
output = await this.runWithCli(prompt);
|
|
@@ -502,7 +523,7 @@ class DeepAnalyzer {
|
|
|
502
523
|
/**
|
|
503
524
|
* Build context-aware prompt for documentation cultivation
|
|
504
525
|
*/
|
|
505
|
-
buildPrompt(agent, documents, keyDocs, dirCoverage, previousAnalysis) {
|
|
526
|
+
buildPrompt(agent, documents, keyDocs, dirCoverage, previousAnalysis, sopGaps) {
|
|
506
527
|
const inventory = documents.map((d) => `- ${d.path} (${d.type}): ${d.title}`).join("\n");
|
|
507
528
|
const keyContent = Array.from(keyDocs.entries()).map(([name, content]) => `### ${name}
|
|
508
529
|
|
|
@@ -604,6 +625,9 @@ Suggest knowledge graph nodes and edges in this format:
|
|
|
604
625
|
|
|
605
626
|
Also identify concepts that should be linked but aren't currently.`;
|
|
606
627
|
break;
|
|
628
|
+
case "sop":
|
|
629
|
+
specificInstructions = this.buildSOPAgentInstructions(sopGaps);
|
|
630
|
+
break;
|
|
607
631
|
}
|
|
608
632
|
return `You are a documentation analyst helping to cultivate a knowledge graph.
|
|
609
633
|
${iterationContext}
|
|
@@ -634,6 +658,187 @@ Reference specific documents using [[document-name]] wiki-link format where rele
|
|
|
634
658
|
Be specific and actionable in your analysis.
|
|
635
659
|
${previousAnalysis ? "\nFocus on NEW items not identified in previous iterations." : ""}`;
|
|
636
660
|
}
|
|
661
|
+
/**
|
|
662
|
+
* Run SOP compliance check against the documentation
|
|
663
|
+
*/
|
|
664
|
+
async runSOPComplianceCheck() {
|
|
665
|
+
try {
|
|
666
|
+
logger.info("Running SOP compliance check", { projectRoot: this.projectRoot });
|
|
667
|
+
const result = await checkCompliance({
|
|
668
|
+
projectRoot: this.projectRoot,
|
|
669
|
+
docsPath: this.docsPath,
|
|
670
|
+
deepAnalysis: false,
|
|
671
|
+
assessor: "deep-analyzer"
|
|
672
|
+
});
|
|
673
|
+
logger.info("SOP compliance check complete", {
|
|
674
|
+
score: result.overallScore,
|
|
675
|
+
compliant: result.assessments.filter((a) => a.score >= 70).length,
|
|
676
|
+
nonCompliant: result.assessments.filter((a) => a.score < 70).length
|
|
677
|
+
});
|
|
678
|
+
return result;
|
|
679
|
+
} catch (error) {
|
|
680
|
+
logger.warn("SOP compliance check failed", { error: error instanceof Error ? error.message : String(error) });
|
|
681
|
+
return void 0;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Run SOP gap analysis on compliance results
|
|
686
|
+
*/
|
|
687
|
+
runSOPGapAnalysis(compliance) {
|
|
688
|
+
try {
|
|
689
|
+
const result = analyzeGaps(compliance, {
|
|
690
|
+
complianceThreshold: 70,
|
|
691
|
+
includePartial: true,
|
|
692
|
+
generateRemediation: true
|
|
693
|
+
});
|
|
694
|
+
logger.info("SOP gap analysis complete", {
|
|
695
|
+
totalGaps: result.totalGaps,
|
|
696
|
+
criticalGaps: result.criticalGaps.length,
|
|
697
|
+
compliancePercentage: result.summary.compliancePercentage
|
|
698
|
+
});
|
|
699
|
+
this.writeSOPGapsSummary(result);
|
|
700
|
+
return result;
|
|
701
|
+
} catch (error) {
|
|
702
|
+
logger.warn("SOP gap analysis failed", { error: error instanceof Error ? error.message : String(error) });
|
|
703
|
+
return void 0;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Write SOP gaps summary to analysis output
|
|
708
|
+
*/
|
|
709
|
+
writeSOPGapsSummary(gaps) {
|
|
710
|
+
const summaryPath = join(this.outputDir, "sop-gaps-summary.json");
|
|
711
|
+
try {
|
|
712
|
+
const summary = {
|
|
713
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
714
|
+
totalGaps: gaps.totalGaps,
|
|
715
|
+
criticalGaps: gaps.criticalGaps.length,
|
|
716
|
+
summary: gaps.summary,
|
|
717
|
+
byPriority: {
|
|
718
|
+
critical: gaps.byPriority[SOPPriority.CRITICAL].length,
|
|
719
|
+
high: gaps.byPriority[SOPPriority.HIGH].length,
|
|
720
|
+
medium: gaps.byPriority[SOPPriority.MEDIUM].length,
|
|
721
|
+
low: gaps.byPriority[SOPPriority.LOW].length
|
|
722
|
+
},
|
|
723
|
+
byCategory: Object.entries(gaps.byCategory).reduce((acc, [key, value]) => {
|
|
724
|
+
acc[key] = value.length;
|
|
725
|
+
return acc;
|
|
726
|
+
}, {}),
|
|
727
|
+
gaps: gaps.gaps.map((g) => ({
|
|
728
|
+
id: g.id,
|
|
729
|
+
sopId: g.sopId,
|
|
730
|
+
requirementId: g.requirementId,
|
|
731
|
+
description: g.description,
|
|
732
|
+
priority: g.priority,
|
|
733
|
+
effort: g.effort,
|
|
734
|
+
remediation: g.remediation
|
|
735
|
+
})),
|
|
736
|
+
roadmap: gaps.roadmap ? {
|
|
737
|
+
phases: gaps.roadmap.phases.map((p) => ({
|
|
738
|
+
phase: p.phase,
|
|
739
|
+
name: p.name,
|
|
740
|
+
focus: p.focus,
|
|
741
|
+
effort: p.effort,
|
|
742
|
+
gapCount: p.gaps.length
|
|
743
|
+
})),
|
|
744
|
+
quickWinsCount: gaps.roadmap.quickWins.length
|
|
745
|
+
} : void 0
|
|
746
|
+
};
|
|
747
|
+
writeFileSync(summaryPath, JSON.stringify(summary, null, 2));
|
|
748
|
+
logger.debug("Wrote SOP gaps summary", { path: summaryPath });
|
|
749
|
+
} catch (error) {
|
|
750
|
+
logger.warn("Failed to write SOP gaps summary", { error: error instanceof Error ? error.message : String(error) });
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Build SOP agent-specific instructions with gap context
|
|
755
|
+
*/
|
|
756
|
+
buildSOPAgentInstructions(sopGaps) {
|
|
757
|
+
let instructions = `
|
|
758
|
+
Analyze AI-SDLC SOP (Standard Operating Procedures) compliance gaps and recommend documentation:
|
|
759
|
+
|
|
760
|
+
1. **Gap Prioritization**: Review the compliance gaps and prioritize by impact
|
|
761
|
+
2. **Documentation Recommendations**: For each gap, suggest what documentation should be created
|
|
762
|
+
3. **Remediation Steps**: Provide actionable steps to address each gap
|
|
763
|
+
4. **Quick Wins**: Identify low-effort, high-impact gaps that can be addressed quickly
|
|
764
|
+
5. **Documentation Templates**: Suggest document templates for common gap types
|
|
765
|
+
|
|
766
|
+
For each gap, recommend:
|
|
767
|
+
- Document type (guide, standard, process, reference)
|
|
768
|
+
- Suggested file path (using project conventions)
|
|
769
|
+
- Key sections to include
|
|
770
|
+
- Related documents to link to ([[wiki-links]])
|
|
771
|
+
- Priority level (high/medium/low)
|
|
772
|
+
`;
|
|
773
|
+
if (sopGaps && sopGaps.totalGaps > 0) {
|
|
774
|
+
instructions += `
|
|
775
|
+
## Current SOP Compliance Gaps
|
|
776
|
+
|
|
777
|
+
**Summary:**
|
|
778
|
+
- Total Gaps: ${sopGaps.totalGaps}
|
|
779
|
+
- Critical Gaps: ${sopGaps.criticalGaps.length}
|
|
780
|
+
- Compliance Score: ${sopGaps.summary.compliancePercentage}%
|
|
781
|
+
|
|
782
|
+
### Gaps by Priority:
|
|
783
|
+
- Critical: ${sopGaps.byPriority[SOPPriority.CRITICAL].length}
|
|
784
|
+
- High: ${sopGaps.byPriority[SOPPriority.HIGH].length}
|
|
785
|
+
- Medium: ${sopGaps.byPriority[SOPPriority.MEDIUM].length}
|
|
786
|
+
- Low: ${sopGaps.byPriority[SOPPriority.LOW].length}
|
|
787
|
+
|
|
788
|
+
### Detailed Gaps:
|
|
789
|
+
`;
|
|
790
|
+
const priorityGaps = [
|
|
791
|
+
...sopGaps.byPriority[SOPPriority.CRITICAL],
|
|
792
|
+
...sopGaps.byPriority[SOPPriority.HIGH]
|
|
793
|
+
].slice(0, 15);
|
|
794
|
+
for (const gap of priorityGaps) {
|
|
795
|
+
instructions += `
|
|
796
|
+
#### ${gap.priority.toUpperCase()}: ${gap.description}
|
|
797
|
+
- SOP: ${gap.sopId}
|
|
798
|
+
- Requirement: ${gap.requirementId}
|
|
799
|
+
- Effort: ${gap.effort}
|
|
800
|
+
- Remediation: ${gap.remediation}
|
|
801
|
+
- Impact: ${gap.impact}
|
|
802
|
+
`;
|
|
803
|
+
}
|
|
804
|
+
if (sopGaps.roadmap) {
|
|
805
|
+
instructions += `
|
|
806
|
+
### Remediation Roadmap:
|
|
807
|
+
`;
|
|
808
|
+
for (const phase of sopGaps.roadmap.phases) {
|
|
809
|
+
instructions += `
|
|
810
|
+
**Phase ${phase.phase}: ${phase.name}**
|
|
811
|
+
- Focus: ${phase.focus}
|
|
812
|
+
- Effort: ${phase.effort}
|
|
813
|
+
- Gaps to address: ${phase.gaps.length}
|
|
814
|
+
`;
|
|
815
|
+
}
|
|
816
|
+
if (sopGaps.roadmap.quickWins.length > 0) {
|
|
817
|
+
instructions += `
|
|
818
|
+
### Quick Wins (High Impact, Low Effort):
|
|
819
|
+
`;
|
|
820
|
+
for (const win of sopGaps.roadmap.quickWins.slice(0, 5)) {
|
|
821
|
+
instructions += `- ${win.description} (${win.effort} effort)
|
|
822
|
+
`;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
} else {
|
|
827
|
+
instructions += `
|
|
828
|
+
## No SOP Gaps Data Available
|
|
829
|
+
|
|
830
|
+
Perform a general AI-SDLC compliance analysis based on the documentation structure.
|
|
831
|
+
Review for common compliance areas:
|
|
832
|
+
- Requirements documentation
|
|
833
|
+
- Architecture documentation
|
|
834
|
+
- Testing documentation
|
|
835
|
+
- Security documentation
|
|
836
|
+
- Deployment documentation
|
|
837
|
+
- Operational procedures
|
|
838
|
+
`;
|
|
839
|
+
}
|
|
840
|
+
return instructions;
|
|
841
|
+
}
|
|
637
842
|
/**
|
|
638
843
|
* Run analysis using Claude CLI
|
|
639
844
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deep-analyzer.js","sources":["../../src/cultivation/deep-analyzer.ts"],"sourcesContent":["/**\n * DeepAnalyzer - Documentation Cultivation & Knowledge Graph Enhancement\n *\n * Analyzes existing documentation to:\n * - Understand the vision and requirements described\n * - Identify documentation gaps and unclear areas\n * - Guide the documentation process with research questions\n * - Build knowledge graph connections\n *\n * This is NOT for code analysis - use analyze-codebase for that.\n *\n * @module cultivation/deep-analyzer\n */\n\nimport { execFileSync, execSync } from 'child_process';\nimport { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, statSync } from 'fs';\nimport { join, resolve, relative, basename, extname } from 'path';\nimport { createLogger } from '../utils/index.js';\n\nconst logger = createLogger('deep-analyzer');\n\n/**\n * Deep analyzer options\n */\nexport interface DeepAnalyzerOptions {\n /** Project root directory */\n projectRoot: string;\n /** Documentation path (relative to project root) */\n docsPath?: string;\n /** Output directory for analysis results */\n outputDir?: string;\n /** Enable verbose logging */\n verbose?: boolean;\n /** Maximum documents to analyze */\n maxDocuments?: number;\n /** Timeout for each analysis (ms) */\n agentTimeout?: number;\n /** Force use of API key even if CLI is available */\n forceApiKey?: boolean;\n /** Preferred provider when multiple are available */\n preferredProvider?: 'anthropic' | 'gemini';\n}\n\n/**\n * Analysis result from an agent\n */\nexport interface AgentResult {\n name: string;\n type: string;\n success: boolean;\n insights: string[];\n documents: Array<{ path: string; title: string }>;\n duration: number;\n error?: string;\n}\n\n/**\n * Deep analysis result\n */\nexport interface DeepAnalysisResult {\n success: boolean;\n agentsSpawned: number;\n insightsCount: number;\n documentsCreated: number;\n results: AgentResult[];\n duration: number;\n errors: string[];\n mode: 'cli' | 'anthropic' | 'gemini' | 'static';\n}\n\n/**\n * Agent configuration\n */\ninterface AgentConfig {\n name: string;\n type: string;\n task: string;\n outputFile: string;\n}\n\n/**\n * Execution mode detection result\n */\ninterface ExecutionMode {\n mode: 'cli' | 'anthropic' | 'gemini' | 'unavailable';\n reason: string;\n}\n\n/**\n * Document metadata for analysis\n */\ninterface DocMetadata {\n path: string;\n title: string;\n type: string;\n size: number;\n preview: string;\n}\n\n/**\n * Directory coverage information\n */\ninterface DirectoryCoverage {\n path: string;\n name: string;\n hasMOC: boolean;\n mocStatus: 'complete' | 'stub' | 'empty' | 'missing';\n documentCount: number;\n subdirectories: string[];\n documents: string[];\n needsDocumentation: boolean;\n reason?: string;\n}\n\n/**\n * Previous analysis metadata for iteration tracking\n */\ninterface PreviousAnalysis {\n timestamp: string;\n iteration: number;\n gapsIdentified: number;\n gapsFilled: number;\n questionsRaised: number;\n questionsAnswered: number;\n coverageScore: number;\n}\n\n/**\n * DeepAnalyzer - Documentation cultivation with AI-powered analysis\n *\n * Reads existing markdown documentation and provides:\n * - Vision synthesis from requirements\n * - Gap analysis identifying missing documentation\n * - Research questions for unclear areas\n * - Knowledge graph connection suggestions\n *\n * @example\n * ```typescript\n * const analyzer = new DeepAnalyzer({\n * projectRoot: '/my/project',\n * docsPath: 'docs',\n * });\n *\n * const result = await analyzer.analyze();\n * console.log(`Generated ${result.insightsCount} insights`);\n * ```\n */\nexport class DeepAnalyzer {\n private projectRoot: string;\n private docsPath: string;\n private outputDir: string;\n private verbose: boolean;\n private maxDocuments: number;\n private agentTimeout: number;\n private forceApiKey: boolean;\n private preferredProvider: 'anthropic' | 'gemini';\n\n constructor(options: DeepAnalyzerOptions) {\n this.projectRoot = resolve(options.projectRoot);\n this.docsPath = options.docsPath || 'docs';\n this.outputDir = options.outputDir || join(this.projectRoot, this.docsPath, 'analysis');\n this.verbose = options.verbose || false;\n this.maxDocuments = options.maxDocuments || 50;\n // Default timeout of 2 minutes (120 seconds)\n this.agentTimeout = options.agentTimeout || 120000;\n this.forceApiKey = options.forceApiKey || false;\n this.preferredProvider = options.preferredProvider || 'anthropic';\n }\n\n /**\n * Check if running inside a Claude Code session\n */\n private isInsideClaudeCode(): boolean {\n return process.env.CLAUDECODE === '1' || process.env.CLAUDE_CODE === '1';\n }\n\n /**\n * Check if Anthropic API key is available\n */\n private hasAnthropicApiKey(): boolean {\n return !!process.env.ANTHROPIC_API_KEY;\n }\n\n /**\n * Check if Google AI / Gemini API key is available\n */\n private hasGeminiApiKey(): boolean {\n return !!(\n process.env.GOOGLE_AI_API_KEY ||\n process.env.GOOGLE_GEMINI_API_KEY ||\n process.env.GEMINI_API_KEY ||\n process.env.GOOGLE_API_KEY\n );\n }\n\n /**\n * Get the Gemini API key from available env vars\n */\n private getGeminiApiKey(): string | undefined {\n return (\n process.env.GOOGLE_AI_API_KEY ||\n process.env.GOOGLE_GEMINI_API_KEY ||\n process.env.GEMINI_API_KEY ||\n process.env.GOOGLE_API_KEY\n );\n }\n\n /**\n * Check if Claude CLI is available\n */\n private isCliAvailable(): boolean {\n try {\n execFileSync('claude', ['--version'], {\n stdio: 'pipe',\n timeout: 5000,\n windowsHide: true,\n });\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Determine the best execution mode\n */\n private detectExecutionMode(): ExecutionMode {\n const insideClaudeCode = this.isInsideClaudeCode();\n const hasAnthropicKey = this.hasAnthropicApiKey();\n const hasGeminiKey = this.hasGeminiApiKey();\n const cliAvailable = this.isCliAvailable();\n\n // If forced to use API key\n if (this.forceApiKey) {\n if (this.preferredProvider === 'gemini' && hasGeminiKey) {\n return { mode: 'gemini', reason: 'Using Gemini API (forced, preferred)' };\n }\n if (hasAnthropicKey) {\n return { mode: 'anthropic', reason: 'Using Anthropic API (forced)' };\n }\n if (hasGeminiKey) {\n return { mode: 'gemini', reason: 'Using Gemini API (forced, fallback)' };\n }\n return { mode: 'unavailable', reason: 'No API key found. Set ANTHROPIC_API_KEY or GOOGLE_AI_API_KEY.' };\n }\n\n // Prefer API keys for reliability\n if (this.preferredProvider === 'gemini' && hasGeminiKey) {\n return { mode: 'gemini', reason: 'Using Gemini API (preferred)' };\n }\n if (hasAnthropicKey) {\n return { mode: 'anthropic', reason: 'Using Anthropic API' };\n }\n if (hasGeminiKey) {\n return { mode: 'gemini', reason: 'Using Gemini API' };\n }\n\n // No API keys - try CLI as last resort\n if (insideClaudeCode) {\n return {\n mode: 'unavailable',\n reason: 'Cannot run inside Claude Code without an API key. Set ANTHROPIC_API_KEY or GOOGLE_AI_API_KEY.',\n };\n }\n\n if (cliAvailable) {\n return { mode: 'cli', reason: 'Using Claude CLI (no API key found)' };\n }\n\n return {\n mode: 'unavailable',\n reason: 'No execution method available. Set ANTHROPIC_API_KEY or GOOGLE_AI_API_KEY.',\n };\n }\n\n /**\n * Check if analysis is available\n */\n async isAvailable(): Promise<boolean> {\n const mode = this.detectExecutionMode();\n return mode.mode !== 'unavailable';\n }\n\n /**\n * Get availability status with reason\n */\n async getAvailabilityStatus(): Promise<{ available: boolean; reason: string }> {\n const mode = this.detectExecutionMode();\n return {\n available: mode.mode !== 'unavailable',\n reason: mode.reason,\n };\n }\n\n /**\n * Scan documentation directory for markdown files\n */\n private scanDocumentation(): DocMetadata[] {\n const docsDir = join(this.projectRoot, this.docsPath);\n if (!existsSync(docsDir)) {\n return [];\n }\n\n const documents: DocMetadata[] = [];\n const scan = (dir: string) => {\n const entries = readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name.startsWith('.') || entry.name === 'node_modules' || entry.name === 'analysis') {\n continue;\n }\n\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n scan(fullPath);\n } else if (entry.isFile() && extname(entry.name) === '.md') {\n try {\n const content = readFileSync(fullPath, 'utf-8');\n const stats = statSync(fullPath);\n const relPath = relative(docsDir, fullPath);\n\n // Extract title from first heading or filename\n const titleMatch = content.match(/^#\\s+(.+)$/m);\n const title = titleMatch ? titleMatch[1] : basename(entry.name, '.md');\n\n // Determine document type from path or frontmatter\n let type = 'general';\n if (relPath.includes('concepts/')) type = 'concept';\n else if (relPath.includes('components/')) type = 'component';\n else if (relPath.includes('services/')) type = 'service';\n else if (relPath.includes('features/')) type = 'feature';\n else if (relPath.includes('guides/')) type = 'guide';\n else if (relPath.includes('standards/')) type = 'standard';\n else if (relPath.includes('references/')) type = 'reference';\n else if (relPath.includes('integrations/')) type = 'integration';\n else if (entry.name.includes('requirement')) type = 'requirement';\n else if (entry.name.includes('spec')) type = 'specification';\n\n // Get preview (first 500 chars after title)\n const preview = content.slice(0, 2000).replace(/^#.+\\n/, '').trim().slice(0, 500);\n\n documents.push({\n path: relPath,\n title,\n type,\n size: stats.size,\n preview,\n });\n } catch {\n // Skip files that can't be read\n }\n }\n }\n };\n\n scan(docsDir);\n return documents.slice(0, this.maxDocuments);\n }\n\n /**\n * Read full content of key documents\n */\n private readKeyDocuments(): Map<string, string> {\n const docsDir = join(this.projectRoot, this.docsPath);\n const keyDocs = new Map<string, string>();\n\n // Priority documents to read in full\n const priorityFiles = [\n 'README.md',\n 'MOC.md',\n 'PRIMITIVES.md',\n 'original_specs.md',\n 'business_requirements_document.md',\n 'technical_requirements.md',\n 'test_strategy.md',\n ];\n\n for (const file of priorityFiles) {\n const filePath = join(docsDir, file);\n if (existsSync(filePath)) {\n try {\n const content = readFileSync(filePath, 'utf-8');\n // Limit to 15KB per document to fit in context\n keyDocs.set(file, content.slice(0, 15000));\n } catch {\n // Skip\n }\n }\n }\n\n return keyDocs;\n }\n\n /**\n * Scan directory structure for MOC files and coverage\n */\n private scanDirectoryStructure(): DirectoryCoverage[] {\n const docsDir = join(this.projectRoot, this.docsPath);\n if (!existsSync(docsDir)) {\n return [];\n }\n\n const directories: DirectoryCoverage[] = [];\n const ignoredDirs = new Set(['.', '..', 'analysis', 'node_modules', '.git', '.obsidian']);\n\n const scanDir = (dir: string, depth: number = 0): void => {\n if (depth > 5) return; // Max depth to prevent infinite loops\n\n const relPath = relative(docsDir, dir) || '.';\n const entries = readdirSync(dir, { withFileTypes: true });\n\n const subdirs: string[] = [];\n const docs: string[] = [];\n let mocFile: string | null = null;\n let mocContent = '';\n\n for (const entry of entries) {\n if (ignoredDirs.has(entry.name) || entry.name.startsWith('.')) continue;\n\n if (entry.isDirectory()) {\n subdirs.push(entry.name);\n scanDir(join(dir, entry.name), depth + 1);\n } else if (entry.isFile() && entry.name.endsWith('.md')) {\n docs.push(entry.name);\n if (entry.name === '_MOC.md' || entry.name === 'MOC.md' || entry.name === 'index.md') {\n mocFile = entry.name;\n try {\n mocContent = readFileSync(join(dir, entry.name), 'utf-8');\n } catch {\n mocContent = '';\n }\n }\n }\n }\n\n // Determine MOC status\n let mocStatus: DirectoryCoverage['mocStatus'] = 'missing';\n if (mocFile) {\n if (mocContent.length < 100) {\n mocStatus = 'empty';\n } else if (\n mocContent.toLowerCase().includes('stub') ||\n mocContent.includes('TODO') ||\n mocContent.includes('TBD') ||\n !mocContent.includes('[[')\n ) {\n mocStatus = 'stub';\n } else {\n mocStatus = 'complete';\n }\n }\n\n // Determine if documentation is needed\n let needsDocumentation = false;\n let reason = '';\n\n if (subdirs.length > 0 || docs.length > 1) {\n if (mocStatus === 'missing') {\n needsDocumentation = true;\n reason = 'Directory has content but no MOC file';\n } else if (mocStatus === 'empty' || mocStatus === 'stub') {\n needsDocumentation = true;\n reason = `MOC file is ${mocStatus} - needs content`;\n }\n }\n\n // Only track directories that have content or subdirectories\n if (subdirs.length > 0 || docs.length > 0 || relPath === '.') {\n directories.push({\n path: relPath,\n name: basename(dir),\n hasMOC: mocFile !== null,\n mocStatus,\n documentCount: docs.length,\n subdirectories: subdirs,\n documents: docs,\n needsDocumentation,\n reason,\n });\n }\n };\n\n scanDir(docsDir);\n return directories;\n }\n\n /**\n * Load previous analysis results for iteration tracking\n */\n private loadPreviousAnalysis(): PreviousAnalysis | null {\n const metadataFile = join(this.outputDir, '.analysis-metadata.json');\n\n if (!existsSync(metadataFile)) {\n return null;\n }\n\n try {\n const content = readFileSync(metadataFile, 'utf-8');\n return JSON.parse(content) as PreviousAnalysis;\n } catch {\n return null;\n }\n }\n\n /**\n * Save analysis metadata for iteration tracking\n */\n private saveAnalysisMetadata(result: DeepAnalysisResult, dirCoverage: DirectoryCoverage[]): void {\n const metadataFile = join(this.outputDir, '.analysis-metadata.json');\n const previous = this.loadPreviousAnalysis();\n\n // Count coverage metrics\n const totalDirs = dirCoverage.length;\n const coveredDirs = dirCoverage.filter(d => d.mocStatus === 'complete').length;\n const coverageScore = totalDirs > 0 ? (coveredDirs / totalDirs) * 100 : 0;\n\n // Count gaps and questions from results\n const gapsResult = result.results.find(r => r.type === 'gaps');\n const questionsResult = result.results.find(r => r.type === 'research');\n const coverageResult = result.results.find(r => r.type === 'coverage');\n\n const metadata: PreviousAnalysis = {\n timestamp: new Date().toISOString(),\n iteration: (previous?.iteration || 0) + 1,\n gapsIdentified: (gapsResult?.insights.length || 0) + (coverageResult?.insights.length || 0),\n gapsFilled: 0, // Updated by migrate command\n questionsRaised: questionsResult?.insights.length || 0,\n questionsAnswered: 0, // Updated by migrate command\n coverageScore,\n };\n\n try {\n writeFileSync(metadataFile, JSON.stringify(metadata, null, 2));\n } catch {\n // Non-critical, continue\n }\n }\n\n /**\n * Run deep analysis\n */\n async analyze(): Promise<DeepAnalysisResult> {\n const startTime = Date.now();\n const executionMode = this.detectExecutionMode();\n\n const result: DeepAnalysisResult = {\n success: false,\n agentsSpawned: 0,\n insightsCount: 0,\n documentsCreated: 0,\n results: [],\n duration: 0,\n errors: [],\n mode: executionMode.mode === 'unavailable' ? 'static' : executionMode.mode,\n };\n\n // Check availability\n if (executionMode.mode === 'unavailable') {\n result.errors.push(executionMode.reason);\n result.duration = Date.now() - startTime;\n logger.error('Deep analysis unavailable', new Error(executionMode.reason));\n return result;\n }\n\n logger.info(`Starting documentation cultivation`, { mode: executionMode.mode, reason: executionMode.reason });\n\n // Ensure output directory exists\n if (!existsSync(this.outputDir)) {\n mkdirSync(this.outputDir, { recursive: true });\n }\n\n // Scan existing documentation\n const documents = this.scanDocumentation();\n const keyDocs = this.readKeyDocuments();\n const dirCoverage = this.scanDirectoryStructure();\n const previousAnalysis = this.loadPreviousAnalysis();\n\n if (documents.length === 0) {\n result.errors.push('No markdown documents found in docs directory');\n result.duration = Date.now() - startTime;\n return result;\n }\n\n // Log iteration info\n const iteration = (previousAnalysis?.iteration || 0) + 1;\n logger.info('Found documentation', {\n documents: documents.length,\n keyDocs: keyDocs.size,\n directories: dirCoverage.length,\n needsWork: dirCoverage.filter(d => d.needsDocumentation).length,\n iteration,\n });\n\n // Define documentation cultivation agents - including Directory Coverage\n const agents: AgentConfig[] = [\n {\n name: 'Vision Synthesizer',\n type: 'vision',\n task: 'Synthesize the project vision, goals, and core value proposition from the documentation',\n outputFile: 'vision-synthesis.md',\n },\n {\n name: 'Directory Coverage Analyst',\n type: 'coverage',\n task: 'Analyze directory structure, MOC files, and identify areas needing documentation',\n outputFile: 'directory-coverage.md',\n },\n {\n name: 'Gap Analyst',\n type: 'gaps',\n task: 'Identify documentation gaps, missing sections, and areas that need more detail',\n outputFile: 'documentation-gaps.md',\n },\n {\n name: 'Research Guide',\n type: 'research',\n task: 'Generate research questions and areas that need further investigation or clarification',\n outputFile: 'research-questions.md',\n },\n {\n name: 'Connection Mapper',\n type: 'connections',\n task: 'Identify relationships between concepts and suggest knowledge graph connections',\n outputFile: 'knowledge-connections.md',\n },\n ];\n\n logger.info('Executing cultivation agents', { agents: agents.length, mode: 'sequential', iteration });\n\n // Execute agents sequentially\n for (const agent of agents) {\n const agentResult = await this.executeAgent(\n agent,\n executionMode.mode as 'cli' | 'anthropic' | 'gemini',\n documents,\n keyDocs,\n dirCoverage,\n previousAnalysis\n );\n result.results.push(agentResult);\n }\n\n // Save metadata for iteration tracking\n this.saveAnalysisMetadata(result, dirCoverage);\n\n // Calculate totals\n result.agentsSpawned = result.results.length;\n result.insightsCount = result.results.reduce((sum, r) => sum + r.insights.length, 0);\n result.documentsCreated = result.results.reduce((sum, r) => sum + r.documents.length, 0);\n result.success = result.results.some(r => r.success);\n result.duration = Date.now() - startTime;\n\n // Collect errors\n for (const agentResult of result.results) {\n if (agentResult.error) {\n result.errors.push(`${agentResult.name}: ${agentResult.error}`);\n }\n }\n\n logger.info('Documentation cultivation complete', {\n success: result.success,\n insights: result.insightsCount,\n documents: result.documentsCreated,\n duration: result.duration,\n });\n\n return result;\n }\n\n /**\n * Execute a single agent\n */\n private async executeAgent(\n agent: AgentConfig,\n mode: 'cli' | 'anthropic' | 'gemini',\n documents: DocMetadata[],\n keyDocs: Map<string, string>,\n dirCoverage: DirectoryCoverage[],\n previousAnalysis: PreviousAnalysis | null\n ): Promise<AgentResult> {\n const startTime = Date.now();\n const outputPath = join(this.outputDir, agent.outputFile);\n\n const result: AgentResult = {\n name: agent.name,\n type: agent.type,\n success: false,\n insights: [],\n documents: [],\n duration: 0,\n };\n\n try {\n logger.info(`Executing agent: ${agent.name}`, { type: agent.type, mode });\n\n const prompt = this.buildPrompt(agent, documents, keyDocs, dirCoverage, previousAnalysis);\n let output: string;\n\n if (mode === 'cli') {\n output = await this.runWithCli(prompt);\n } else if (mode === 'anthropic') {\n output = await this.runWithAnthropic(prompt);\n } else {\n output = await this.runWithGemini(prompt);\n }\n\n // Parse output for insights\n result.insights = this.extractInsights(output);\n\n // Write output to file\n writeFileSync(outputPath, this.formatOutput(agent, output, mode));\n result.documents.push({ path: outputPath, title: agent.name });\n\n result.success = true;\n\n if (this.verbose) {\n logger.debug(`Agent completed: ${agent.name}`, { insights: result.insights.length });\n }\n } catch (error) {\n result.error = error instanceof Error ? error.message : String(error);\n logger.error(`Agent failed: ${agent.name}`, error instanceof Error ? error : new Error(String(error)));\n }\n\n result.duration = Date.now() - startTime;\n return result;\n }\n\n /**\n * Build directory coverage summary for prompts\n */\n private buildCoverageSummary(dirCoverage: DirectoryCoverage[]): string {\n const lines: string[] = [];\n\n // Summary stats\n const total = dirCoverage.length;\n const complete = dirCoverage.filter(d => d.mocStatus === 'complete').length;\n const stub = dirCoverage.filter(d => d.mocStatus === 'stub').length;\n const empty = dirCoverage.filter(d => d.mocStatus === 'empty').length;\n const missing = dirCoverage.filter(d => d.mocStatus === 'missing').length;\n\n lines.push(`### Summary`);\n lines.push(`- Total Directories: ${total}`);\n lines.push(`- Complete MOCs: ${complete} (${((complete / total) * 100).toFixed(1)}%)`);\n lines.push(`- Stub MOCs: ${stub}`);\n lines.push(`- Empty MOCs: ${empty}`);\n lines.push(`- Missing MOCs: ${missing}`);\n lines.push(`- Coverage Score: ${((complete / total) * 100).toFixed(1)}%`);\n lines.push('');\n\n // Directories needing work\n const needsWork = dirCoverage.filter(d => d.needsDocumentation);\n if (needsWork.length > 0) {\n lines.push('### Directories Needing Documentation');\n for (const dir of needsWork) {\n lines.push(`- **${dir.path}/** (${dir.mocStatus})`);\n lines.push(` - Documents: ${dir.documents.join(', ') || 'none'}`);\n lines.push(` - Subdirectories: ${dir.subdirectories.join(', ') || 'none'}`);\n lines.push(` - Reason: ${dir.reason}`);\n }\n lines.push('');\n }\n\n // Complete directories\n const completeDirs = dirCoverage.filter(d => d.mocStatus === 'complete');\n if (completeDirs.length > 0) {\n lines.push('### Directories with Complete MOCs');\n for (const dir of completeDirs) {\n lines.push(`- ${dir.path}/ (${dir.documentCount} docs)`);\n }\n }\n\n return lines.join('\\n');\n }\n\n /**\n * Build context-aware prompt for documentation cultivation\n */\n private buildPrompt(\n agent: AgentConfig,\n documents: DocMetadata[],\n keyDocs: Map<string, string>,\n dirCoverage: DirectoryCoverage[],\n previousAnalysis: PreviousAnalysis | null\n ): string {\n // Build document inventory\n const inventory = documents.map(d => `- ${d.path} (${d.type}): ${d.title}`).join('\\n');\n\n // Build key document content\n const keyContent = Array.from(keyDocs.entries())\n .map(([name, content]) => `### ${name}\\n\\n${content}`)\n .join('\\n\\n---\\n\\n');\n\n // Build directory coverage summary\n const coverageSummary = this.buildCoverageSummary(dirCoverage);\n\n // Build iteration context\n const iterationContext = previousAnalysis\n ? `\\n## Previous Analysis (Iteration ${previousAnalysis.iteration})\n- Timestamp: ${previousAnalysis.timestamp}\n- Gaps Identified: ${previousAnalysis.gapsIdentified}\n- Gaps Filled: ${previousAnalysis.gapsFilled}\n- Questions Raised: ${previousAnalysis.questionsRaised}\n- Questions Answered: ${previousAnalysis.questionsAnswered}\n- Coverage Score: ${previousAnalysis.coverageScore.toFixed(1)}%\n\nFocus on NEW gaps and questions not addressed in previous iterations.\n`\n : '';\n\n // Agent-specific instructions\n let specificInstructions = '';\n switch (agent.type) {\n case 'coverage':\n specificInstructions = `\nFocus on directory structure and MOC (Map of Content) files:\n\n1. **Directory Analysis**: Review each directory and its MOC file status\n2. **Empty/Stub MOCs**: Identify MOC files that are empty or just stubs\n3. **Missing MOCs**: Identify directories that need MOC files\n4. **Documentation Needs**: For each directory, determine what documentation is needed\n5. **Not Needed**: If a directory genuinely doesn't need documentation, explain why\n\nFor each directory needing work:\n- State the directory path\n- Current MOC status (missing/empty/stub/complete)\n- What documentation should be added\n- Priority (high/medium/low)\n- Suggested content or links to include\n\nThe goal is 100% documentation coverage - every directory should either:\n1. Have a complete MOC with links to contents\n2. Have documentation explaining why it doesn't need more docs\n3. Be marked for future documentation\n\n## Directory Coverage Status\n${coverageSummary}`;\n break;\n\n case 'vision':\n specificInstructions = `\nFocus on:\n1. What is the core purpose/goal of this project?\n2. What problem does it solve?\n3. What is the target audience/user?\n4. What are the key success metrics?\n5. What is the overall architecture vision?\n\nProvide a clear, concise synthesis of the project vision with references to specific documentation.`;\n break;\n\n case 'gaps':\n specificInstructions = `\nIdentify:\n1. Missing documentation (what topics are mentioned but not explained?)\n2. Incomplete sections (what areas need more detail?)\n3. Outdated information (anything that seems inconsistent?)\n4. Missing examples or use cases\n5. Unclear terminology or concepts that need definitions\n6. Empty or stub MOC files that need content (see Directory Coverage below)\n\nFor each gap, specify:\n- What is missing\n- Where it should be documented (specific file path)\n- Why it's important\n- Priority (high/medium/low)\n\n## Directory Coverage Status\n${coverageSummary}`;\n break;\n\n case 'research':\n specificInstructions = `\nGenerate research questions in these categories:\n1. Technical questions (how should X be implemented?)\n2. Design decisions (why this approach vs alternatives?)\n3. Integration questions (how does X connect to Y?)\n4. Validation questions (how do we verify X works?)\n5. Scalability questions (will this work at scale?)\n\nFor each question:\n- State the question clearly\n- Explain why answering it is important\n- Suggest where to look for answers`;\n break;\n\n case 'connections':\n specificInstructions = `\nIdentify relationships between documented concepts:\n1. Dependencies (X requires Y)\n2. Extensions (X extends Y)\n3. Alternatives (X is an alternative to Y)\n4. Compositions (X is made up of Y and Z)\n5. References (X references Y for details)\n\nSuggest knowledge graph nodes and edges in this format:\n- [Node A] --relationship--> [Node B]: description\n\nAlso identify concepts that should be linked but aren't currently.`;\n break;\n }\n\n return `You are a documentation analyst helping to cultivate a knowledge graph.\n${iterationContext}\n## Your Task\n${agent.task}\n\n## Documentation Inventory\nThe following markdown documents exist in this project:\n${inventory}\n\n## Key Document Contents\n\n${keyContent}\n\n## Instructions\n${specificInstructions}\n\n## Output Format\nProvide your analysis in markdown format with:\n1. Clear section headings\n2. Specific observations (prefix with \"Observation:\")\n3. Specific recommendations (prefix with \"Recommendation:\")\n4. Key findings (prefix with \"Finding:\")\n5. Research questions where applicable (prefix with \"Question:\")\n6. Priority levels (high/medium/low) for actionable items\n\nReference specific documents using [[document-name]] wiki-link format where relevant.\nBe specific and actionable in your analysis.\n${previousAnalysis ? '\\nFocus on NEW items not identified in previous iterations.' : ''}`;\n }\n\n /**\n * Run analysis using Claude CLI\n */\n private async runWithCli(prompt: string): Promise<string> {\n const sanitizedPrompt = prompt\n .replace(/\"/g, '\\\\\"')\n .replace(/[`$]/g, '');\n\n try {\n const result = execSync(`claude -p \"${sanitizedPrompt}\"`, {\n cwd: this.projectRoot,\n encoding: 'utf8',\n timeout: this.agentTimeout,\n maxBuffer: 10 * 1024 * 1024,\n });\n return result;\n } catch (error) {\n if (error instanceof Error) {\n const execError = error as { stderr?: string; stdout?: string; killed?: boolean };\n if (execError.killed) {\n if (execError.stdout && execError.stdout.length > 100) {\n return execError.stdout;\n }\n throw new Error(`Claude CLI timed out after ${this.agentTimeout / 1000}s`);\n }\n throw new Error(execError.stderr || error.message);\n }\n throw error;\n }\n }\n\n /**\n * Run analysis using Anthropic API directly\n */\n private async runWithAnthropic(prompt: string): Promise<string> {\n const apiKey = process.env.ANTHROPIC_API_KEY;\n if (!apiKey) {\n throw new Error('ANTHROPIC_API_KEY not set');\n }\n\n try {\n const { default: Anthropic } = await import('@anthropic-ai/sdk');\n const client = new Anthropic({ apiKey });\n\n const response = await client.messages.create({\n model: 'claude-sonnet-4-20250514',\n max_tokens: 4096,\n messages: [{ role: 'user', content: prompt }],\n });\n\n const textBlock = response.content.find(block => block.type === 'text');\n if (textBlock && textBlock.type === 'text') {\n return textBlock.text;\n }\n\n throw new Error('No text content in API response');\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Anthropic API call failed: ${error.message}`);\n }\n throw error;\n }\n }\n\n /**\n * Run analysis using Google Gemini API\n */\n private async runWithGemini(prompt: string): Promise<string> {\n const apiKey = this.getGeminiApiKey();\n if (!apiKey) {\n throw new Error('GOOGLE_AI_API_KEY not set');\n }\n\n try {\n const { GoogleGenerativeAI } = await import('@google/generative-ai');\n const genAI = new GoogleGenerativeAI(apiKey);\n const model = genAI.getGenerativeModel({ model: 'gemini-2.5-flash' });\n\n const result = await model.generateContent(prompt);\n const response = result.response;\n const text = response.text();\n\n if (!text) {\n throw new Error('No text content in Gemini response');\n }\n\n return text;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Gemini API call failed: ${error.message}`);\n }\n throw error;\n }\n }\n\n /**\n * Extract insights from agent output\n */\n private extractInsights(output: string): string[] {\n const insights: string[] = [];\n\n const patterns = [\n /[-*]?\\s*(?:insight|finding|observation|recommendation|question):\\s*(.+)/gi,\n /##\\s*(?:insight|finding|observation|recommendation|question):\\s*(.+)/gi,\n /(?:key\\s+)?(?:insight|finding|observation|recommendation|question):\\s*(.+)/gi,\n ];\n\n for (const pattern of patterns) {\n const matches = output.matchAll(pattern);\n for (const match of matches) {\n if (match[1]) {\n insights.push(match[1].trim());\n }\n }\n }\n\n return [...new Set(insights)];\n }\n\n /**\n * Format output for documentation\n */\n private formatOutput(agent: AgentConfig, output: string, mode: string): string {\n const timestamp = new Date().toISOString();\n\n return `---\ntitle: \"${agent.name}\"\ntype: cultivation-analysis\ngenerator: deep-analyzer\nagent: ${agent.type}\nprovider: ${mode}\ncreated: ${timestamp}\n---\n\n# ${agent.name}\n\n> Generated by DeepAnalyzer for documentation cultivation\n\n## Purpose\n\n${agent.task}\n\n## Analysis\n\n${output}\n\n---\n\n*Generated on ${new Date().toLocaleString()}*\n`;\n }\n}\n\n/**\n * Create a deep analyzer instance\n */\nexport function createDeepAnalyzer(options: DeepAnalyzerOptions): DeepAnalyzer {\n return new DeepAnalyzer(options);\n}\n\n/**\n * Run deep analysis on a project\n */\nexport async function analyzeDeep(\n projectRoot: string,\n docsPath?: string\n): Promise<DeepAnalysisResult> {\n const analyzer = new DeepAnalyzer({ projectRoot, docsPath });\n return analyzer.analyze();\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"deep-analyzer.js","sources":["../../src/cultivation/deep-analyzer.ts"],"sourcesContent":["/**\n * DeepAnalyzer - Documentation Cultivation & Knowledge Graph Enhancement\n *\n * Analyzes existing documentation to:\n * - Understand the vision and requirements described\n * - Identify documentation gaps and unclear areas\n * - Guide the documentation process with research questions\n * - Build knowledge graph connections\n *\n * This is NOT for code analysis - use analyze-codebase for that.\n *\n * @module cultivation/deep-analyzer\n */\n\nimport { execFileSync, execSync } from 'child_process';\nimport { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, statSync } from 'fs';\nimport { join, resolve, relative, basename, extname } from 'path';\nimport { createLogger } from '../utils/index.js';\nimport {\n checkCompliance,\n analyzeGaps,\n ComplianceCheckResult,\n GapAnalysisResult,\n ComplianceGap,\n SOPPriority,\n SOPCategory,\n} from '../sops/index.js';\n\nconst logger = createLogger('deep-analyzer');\n\n/**\n * Deep analyzer options\n */\nexport interface DeepAnalyzerOptions {\n /** Project root directory */\n projectRoot: string;\n /** Documentation path (relative to project root) */\n docsPath?: string;\n /** Output directory for analysis results */\n outputDir?: string;\n /** Enable verbose logging */\n verbose?: boolean;\n /** Maximum documents to analyze */\n maxDocuments?: number;\n /** Timeout for each analysis (ms) */\n agentTimeout?: number;\n /** Force use of API key even if CLI is available */\n forceApiKey?: boolean;\n /** Preferred provider when multiple are available */\n preferredProvider?: 'anthropic' | 'gemini';\n}\n\n/**\n * Analysis result from an agent\n */\nexport interface AgentResult {\n name: string;\n type: string;\n success: boolean;\n insights: string[];\n documents: Array<{ path: string; title: string }>;\n duration: number;\n error?: string;\n}\n\n/**\n * Deep analysis result\n */\nexport interface DeepAnalysisResult {\n success: boolean;\n agentsSpawned: number;\n insightsCount: number;\n documentsCreated: number;\n results: AgentResult[];\n duration: number;\n errors: string[];\n mode: 'cli' | 'anthropic' | 'gemini' | 'static';\n /** SOP compliance check result */\n sopCompliance?: ComplianceCheckResult;\n /** SOP gap analysis result */\n sopGaps?: GapAnalysisResult;\n}\n\n/**\n * Agent configuration\n */\ninterface AgentConfig {\n name: string;\n type: string;\n task: string;\n outputFile: string;\n}\n\n/**\n * Execution mode detection result\n */\ninterface ExecutionMode {\n mode: 'cli' | 'anthropic' | 'gemini' | 'unavailable';\n reason: string;\n}\n\n/**\n * Document metadata for analysis\n */\ninterface DocMetadata {\n path: string;\n title: string;\n type: string;\n size: number;\n preview: string;\n}\n\n/**\n * Directory coverage information\n */\ninterface DirectoryCoverage {\n path: string;\n name: string;\n hasMOC: boolean;\n mocStatus: 'complete' | 'stub' | 'empty' | 'missing';\n documentCount: number;\n subdirectories: string[];\n documents: string[];\n needsDocumentation: boolean;\n reason?: string;\n}\n\n/**\n * Previous analysis metadata for iteration tracking\n */\ninterface PreviousAnalysis {\n timestamp: string;\n iteration: number;\n gapsIdentified: number;\n gapsFilled: number;\n questionsRaised: number;\n questionsAnswered: number;\n coverageScore: number;\n}\n\n/**\n * DeepAnalyzer - Documentation cultivation with AI-powered analysis\n *\n * Reads existing markdown documentation and provides:\n * - Vision synthesis from requirements\n * - Gap analysis identifying missing documentation\n * - Research questions for unclear areas\n * - Knowledge graph connection suggestions\n *\n * @example\n * ```typescript\n * const analyzer = new DeepAnalyzer({\n * projectRoot: '/my/project',\n * docsPath: 'docs',\n * });\n *\n * const result = await analyzer.analyze();\n * console.log(`Generated ${result.insightsCount} insights`);\n * ```\n */\nexport class DeepAnalyzer {\n private projectRoot: string;\n private docsPath: string;\n private outputDir: string;\n private verbose: boolean;\n private maxDocuments: number;\n private agentTimeout: number;\n private forceApiKey: boolean;\n private preferredProvider: 'anthropic' | 'gemini';\n\n constructor(options: DeepAnalyzerOptions) {\n this.projectRoot = resolve(options.projectRoot);\n this.docsPath = options.docsPath || 'docs';\n this.outputDir = options.outputDir || join(this.projectRoot, this.docsPath, 'analysis');\n this.verbose = options.verbose || false;\n this.maxDocuments = options.maxDocuments || 50;\n // Default timeout of 2 minutes (120 seconds)\n this.agentTimeout = options.agentTimeout || 120000;\n this.forceApiKey = options.forceApiKey || false;\n this.preferredProvider = options.preferredProvider || 'anthropic';\n }\n\n /**\n * Check if running inside a Claude Code session\n */\n private isInsideClaudeCode(): boolean {\n return process.env.CLAUDECODE === '1' || process.env.CLAUDE_CODE === '1';\n }\n\n /**\n * Check if Anthropic API key is available\n */\n private hasAnthropicApiKey(): boolean {\n return !!process.env.ANTHROPIC_API_KEY;\n }\n\n /**\n * Check if Google AI / Gemini API key is available\n */\n private hasGeminiApiKey(): boolean {\n return !!(\n process.env.GOOGLE_AI_API_KEY ||\n process.env.GOOGLE_GEMINI_API_KEY ||\n process.env.GEMINI_API_KEY ||\n process.env.GOOGLE_API_KEY\n );\n }\n\n /**\n * Get the Gemini API key from available env vars\n */\n private getGeminiApiKey(): string | undefined {\n return (\n process.env.GOOGLE_AI_API_KEY ||\n process.env.GOOGLE_GEMINI_API_KEY ||\n process.env.GEMINI_API_KEY ||\n process.env.GOOGLE_API_KEY\n );\n }\n\n /**\n * Check if Claude CLI is available\n */\n private isCliAvailable(): boolean {\n try {\n execFileSync('claude', ['--version'], {\n stdio: 'pipe',\n timeout: 5000,\n windowsHide: true,\n });\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Determine the best execution mode\n */\n private detectExecutionMode(): ExecutionMode {\n const insideClaudeCode = this.isInsideClaudeCode();\n const hasAnthropicKey = this.hasAnthropicApiKey();\n const hasGeminiKey = this.hasGeminiApiKey();\n const cliAvailable = this.isCliAvailable();\n\n // If forced to use API key\n if (this.forceApiKey) {\n if (this.preferredProvider === 'gemini' && hasGeminiKey) {\n return { mode: 'gemini', reason: 'Using Gemini API (forced, preferred)' };\n }\n if (hasAnthropicKey) {\n return { mode: 'anthropic', reason: 'Using Anthropic API (forced)' };\n }\n if (hasGeminiKey) {\n return { mode: 'gemini', reason: 'Using Gemini API (forced, fallback)' };\n }\n return { mode: 'unavailable', reason: 'No API key found. Set ANTHROPIC_API_KEY or GOOGLE_AI_API_KEY.' };\n }\n\n // Prefer API keys for reliability\n if (this.preferredProvider === 'gemini' && hasGeminiKey) {\n return { mode: 'gemini', reason: 'Using Gemini API (preferred)' };\n }\n if (hasAnthropicKey) {\n return { mode: 'anthropic', reason: 'Using Anthropic API' };\n }\n if (hasGeminiKey) {\n return { mode: 'gemini', reason: 'Using Gemini API' };\n }\n\n // No API keys - try CLI as last resort\n if (insideClaudeCode) {\n return {\n mode: 'unavailable',\n reason: 'Cannot run inside Claude Code without an API key. Set ANTHROPIC_API_KEY or GOOGLE_AI_API_KEY.',\n };\n }\n\n if (cliAvailable) {\n return { mode: 'cli', reason: 'Using Claude CLI (no API key found)' };\n }\n\n return {\n mode: 'unavailable',\n reason: 'No execution method available. Set ANTHROPIC_API_KEY or GOOGLE_AI_API_KEY.',\n };\n }\n\n /**\n * Check if analysis is available\n */\n async isAvailable(): Promise<boolean> {\n const mode = this.detectExecutionMode();\n return mode.mode !== 'unavailable';\n }\n\n /**\n * Get availability status with reason\n */\n async getAvailabilityStatus(): Promise<{ available: boolean; reason: string }> {\n const mode = this.detectExecutionMode();\n return {\n available: mode.mode !== 'unavailable',\n reason: mode.reason,\n };\n }\n\n /**\n * Scan documentation directory for markdown files\n */\n private scanDocumentation(): DocMetadata[] {\n const docsDir = join(this.projectRoot, this.docsPath);\n if (!existsSync(docsDir)) {\n return [];\n }\n\n const documents: DocMetadata[] = [];\n const scan = (dir: string) => {\n const entries = readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name.startsWith('.') || entry.name === 'node_modules' || entry.name === 'analysis') {\n continue;\n }\n\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n scan(fullPath);\n } else if (entry.isFile() && extname(entry.name) === '.md') {\n try {\n const content = readFileSync(fullPath, 'utf-8');\n const stats = statSync(fullPath);\n const relPath = relative(docsDir, fullPath);\n\n // Extract title from first heading or filename\n const titleMatch = content.match(/^#\\s+(.+)$/m);\n const title = titleMatch ? titleMatch[1] : basename(entry.name, '.md');\n\n // Determine document type from path or frontmatter\n let type = 'general';\n if (relPath.includes('concepts/')) type = 'concept';\n else if (relPath.includes('components/')) type = 'component';\n else if (relPath.includes('services/')) type = 'service';\n else if (relPath.includes('features/')) type = 'feature';\n else if (relPath.includes('guides/')) type = 'guide';\n else if (relPath.includes('standards/')) type = 'standard';\n else if (relPath.includes('references/')) type = 'reference';\n else if (relPath.includes('integrations/')) type = 'integration';\n else if (entry.name.includes('requirement')) type = 'requirement';\n else if (entry.name.includes('spec')) type = 'specification';\n\n // Get preview (first 500 chars after title)\n const preview = content.slice(0, 2000).replace(/^#.+\\n/, '').trim().slice(0, 500);\n\n documents.push({\n path: relPath,\n title,\n type,\n size: stats.size,\n preview,\n });\n } catch {\n // Skip files that can't be read\n }\n }\n }\n };\n\n scan(docsDir);\n return documents.slice(0, this.maxDocuments);\n }\n\n /**\n * Read full content of key documents\n */\n private readKeyDocuments(): Map<string, string> {\n const docsDir = join(this.projectRoot, this.docsPath);\n const keyDocs = new Map<string, string>();\n\n // Priority documents to read in full\n const priorityFiles = [\n 'README.md',\n 'MOC.md',\n 'PRIMITIVES.md',\n 'original_specs.md',\n 'business_requirements_document.md',\n 'technical_requirements.md',\n 'test_strategy.md',\n ];\n\n for (const file of priorityFiles) {\n const filePath = join(docsDir, file);\n if (existsSync(filePath)) {\n try {\n const content = readFileSync(filePath, 'utf-8');\n // Limit to 15KB per document to fit in context\n keyDocs.set(file, content.slice(0, 15000));\n } catch {\n // Skip\n }\n }\n }\n\n return keyDocs;\n }\n\n /**\n * Scan directory structure for MOC files and coverage\n */\n private scanDirectoryStructure(): DirectoryCoverage[] {\n const docsDir = join(this.projectRoot, this.docsPath);\n if (!existsSync(docsDir)) {\n return [];\n }\n\n const directories: DirectoryCoverage[] = [];\n const ignoredDirs = new Set(['.', '..', 'analysis', 'node_modules', '.git', '.obsidian']);\n\n const scanDir = (dir: string, depth: number = 0): void => {\n if (depth > 5) return; // Max depth to prevent infinite loops\n\n const relPath = relative(docsDir, dir) || '.';\n const entries = readdirSync(dir, { withFileTypes: true });\n\n const subdirs: string[] = [];\n const docs: string[] = [];\n let mocFile: string | null = null;\n let mocContent = '';\n\n for (const entry of entries) {\n if (ignoredDirs.has(entry.name) || entry.name.startsWith('.')) continue;\n\n if (entry.isDirectory()) {\n subdirs.push(entry.name);\n scanDir(join(dir, entry.name), depth + 1);\n } else if (entry.isFile() && entry.name.endsWith('.md')) {\n docs.push(entry.name);\n if (entry.name === '_MOC.md' || entry.name === 'MOC.md' || entry.name === 'index.md') {\n mocFile = entry.name;\n try {\n mocContent = readFileSync(join(dir, entry.name), 'utf-8');\n } catch {\n mocContent = '';\n }\n }\n }\n }\n\n // Determine MOC status\n let mocStatus: DirectoryCoverage['mocStatus'] = 'missing';\n if (mocFile) {\n if (mocContent.length < 100) {\n mocStatus = 'empty';\n } else if (\n mocContent.toLowerCase().includes('stub') ||\n mocContent.includes('TODO') ||\n mocContent.includes('TBD') ||\n !mocContent.includes('[[')\n ) {\n mocStatus = 'stub';\n } else {\n mocStatus = 'complete';\n }\n }\n\n // Determine if documentation is needed\n let needsDocumentation = false;\n let reason = '';\n\n if (subdirs.length > 0 || docs.length > 1) {\n if (mocStatus === 'missing') {\n needsDocumentation = true;\n reason = 'Directory has content but no MOC file';\n } else if (mocStatus === 'empty' || mocStatus === 'stub') {\n needsDocumentation = true;\n reason = `MOC file is ${mocStatus} - needs content`;\n }\n }\n\n // Only track directories that have content or subdirectories\n if (subdirs.length > 0 || docs.length > 0 || relPath === '.') {\n directories.push({\n path: relPath,\n name: basename(dir),\n hasMOC: mocFile !== null,\n mocStatus,\n documentCount: docs.length,\n subdirectories: subdirs,\n documents: docs,\n needsDocumentation,\n reason,\n });\n }\n };\n\n scanDir(docsDir);\n return directories;\n }\n\n /**\n * Load previous analysis results for iteration tracking\n */\n private loadPreviousAnalysis(): PreviousAnalysis | null {\n const metadataFile = join(this.outputDir, '.analysis-metadata.json');\n\n if (!existsSync(metadataFile)) {\n return null;\n }\n\n try {\n const content = readFileSync(metadataFile, 'utf-8');\n return JSON.parse(content) as PreviousAnalysis;\n } catch {\n return null;\n }\n }\n\n /**\n * Save analysis metadata for iteration tracking\n */\n private saveAnalysisMetadata(result: DeepAnalysisResult, dirCoverage: DirectoryCoverage[]): void {\n const metadataFile = join(this.outputDir, '.analysis-metadata.json');\n const previous = this.loadPreviousAnalysis();\n\n // Count coverage metrics\n const totalDirs = dirCoverage.length;\n const coveredDirs = dirCoverage.filter(d => d.mocStatus === 'complete').length;\n const coverageScore = totalDirs > 0 ? (coveredDirs / totalDirs) * 100 : 0;\n\n // Count gaps and questions from results\n const gapsResult = result.results.find(r => r.type === 'gaps');\n const questionsResult = result.results.find(r => r.type === 'research');\n const coverageResult = result.results.find(r => r.type === 'coverage');\n\n const metadata: PreviousAnalysis = {\n timestamp: new Date().toISOString(),\n iteration: (previous?.iteration || 0) + 1,\n gapsIdentified: (gapsResult?.insights.length || 0) + (coverageResult?.insights.length || 0),\n gapsFilled: 0, // Updated by migrate command\n questionsRaised: questionsResult?.insights.length || 0,\n questionsAnswered: 0, // Updated by migrate command\n coverageScore,\n };\n\n try {\n writeFileSync(metadataFile, JSON.stringify(metadata, null, 2));\n } catch {\n // Non-critical, continue\n }\n }\n\n /**\n * Run deep analysis\n */\n async analyze(): Promise<DeepAnalysisResult> {\n const startTime = Date.now();\n const executionMode = this.detectExecutionMode();\n\n const result: DeepAnalysisResult = {\n success: false,\n agentsSpawned: 0,\n insightsCount: 0,\n documentsCreated: 0,\n results: [],\n duration: 0,\n errors: [],\n mode: executionMode.mode === 'unavailable' ? 'static' : executionMode.mode,\n };\n\n // Check availability\n if (executionMode.mode === 'unavailable') {\n result.errors.push(executionMode.reason);\n result.duration = Date.now() - startTime;\n logger.error('Deep analysis unavailable', new Error(executionMode.reason));\n return result;\n }\n\n logger.info(`Starting documentation cultivation`, { mode: executionMode.mode, reason: executionMode.reason });\n\n // Ensure output directory exists\n if (!existsSync(this.outputDir)) {\n mkdirSync(this.outputDir, { recursive: true });\n }\n\n // Scan existing documentation\n const documents = this.scanDocumentation();\n const keyDocs = this.readKeyDocuments();\n const dirCoverage = this.scanDirectoryStructure();\n const previousAnalysis = this.loadPreviousAnalysis();\n\n if (documents.length === 0) {\n result.errors.push('No markdown documents found in docs directory');\n result.duration = Date.now() - startTime;\n return result;\n }\n\n // Log iteration info\n const iteration = (previousAnalysis?.iteration || 0) + 1;\n logger.info('Found documentation', {\n documents: documents.length,\n keyDocs: keyDocs.size,\n directories: dirCoverage.length,\n needsWork: dirCoverage.filter(d => d.needsDocumentation).length,\n iteration,\n });\n\n // Run SOP compliance check before agents\n const sopCompliance = await this.runSOPComplianceCheck();\n const sopGaps = sopCompliance ? this.runSOPGapAnalysis(sopCompliance) : undefined;\n\n // Define documentation cultivation agents - including Directory Coverage and SOP Compliance\n const agents: AgentConfig[] = [\n {\n name: 'Vision Synthesizer',\n type: 'vision',\n task: 'Synthesize the project vision, goals, and core value proposition from the documentation',\n outputFile: 'vision-synthesis.md',\n },\n {\n name: 'Directory Coverage Analyst',\n type: 'coverage',\n task: 'Analyze directory structure, MOC files, and identify areas needing documentation',\n outputFile: 'directory-coverage.md',\n },\n {\n name: 'Gap Analyst',\n type: 'gaps',\n task: 'Identify documentation gaps, missing sections, and areas that need more detail',\n outputFile: 'documentation-gaps.md',\n },\n {\n name: 'Research Guide',\n type: 'research',\n task: 'Generate research questions and areas that need further investigation or clarification',\n outputFile: 'research-questions.md',\n },\n {\n name: 'Connection Mapper',\n type: 'connections',\n task: 'Identify relationships between concepts and suggest knowledge graph connections',\n outputFile: 'knowledge-connections.md',\n },\n {\n name: 'SOP Compliance Analyst',\n type: 'sop',\n task: 'Analyze AI-SDLC SOP compliance gaps and recommend documentation to address them',\n outputFile: 'sop-compliance-gaps.md',\n },\n ];\n\n logger.info('Executing cultivation agents', {\n agents: agents.length,\n mode: 'sequential',\n iteration,\n sopGapsCount: sopGaps?.totalGaps || 0,\n });\n\n // Execute agents sequentially\n for (const agent of agents) {\n const agentResult = await this.executeAgent(\n agent,\n executionMode.mode as 'cli' | 'anthropic' | 'gemini',\n documents,\n keyDocs,\n dirCoverage,\n previousAnalysis,\n sopGaps\n );\n result.results.push(agentResult);\n }\n\n // Store SOP results\n result.sopCompliance = sopCompliance;\n result.sopGaps = sopGaps;\n\n // Save metadata for iteration tracking\n this.saveAnalysisMetadata(result, dirCoverage);\n\n // Calculate totals\n result.agentsSpawned = result.results.length;\n result.insightsCount = result.results.reduce((sum, r) => sum + r.insights.length, 0);\n result.documentsCreated = result.results.reduce((sum, r) => sum + r.documents.length, 0);\n result.success = result.results.some(r => r.success);\n result.duration = Date.now() - startTime;\n\n // Collect errors\n for (const agentResult of result.results) {\n if (agentResult.error) {\n result.errors.push(`${agentResult.name}: ${agentResult.error}`);\n }\n }\n\n logger.info('Documentation cultivation complete', {\n success: result.success,\n insights: result.insightsCount,\n documents: result.documentsCreated,\n duration: result.duration,\n });\n\n return result;\n }\n\n /**\n * Execute a single agent\n */\n private async executeAgent(\n agent: AgentConfig,\n mode: 'cli' | 'anthropic' | 'gemini',\n documents: DocMetadata[],\n keyDocs: Map<string, string>,\n dirCoverage: DirectoryCoverage[],\n previousAnalysis: PreviousAnalysis | null,\n sopGaps?: GapAnalysisResult\n ): Promise<AgentResult> {\n const startTime = Date.now();\n const outputPath = join(this.outputDir, agent.outputFile);\n\n const result: AgentResult = {\n name: agent.name,\n type: agent.type,\n success: false,\n insights: [],\n documents: [],\n duration: 0,\n };\n\n try {\n logger.info(`Executing agent: ${agent.name}`, { type: agent.type, mode });\n\n const prompt = this.buildPrompt(agent, documents, keyDocs, dirCoverage, previousAnalysis, sopGaps);\n let output: string;\n\n if (mode === 'cli') {\n output = await this.runWithCli(prompt);\n } else if (mode === 'anthropic') {\n output = await this.runWithAnthropic(prompt);\n } else {\n output = await this.runWithGemini(prompt);\n }\n\n // Parse output for insights\n result.insights = this.extractInsights(output);\n\n // Write output to file\n writeFileSync(outputPath, this.formatOutput(agent, output, mode));\n result.documents.push({ path: outputPath, title: agent.name });\n\n result.success = true;\n\n if (this.verbose) {\n logger.debug(`Agent completed: ${agent.name}`, { insights: result.insights.length });\n }\n } catch (error) {\n result.error = error instanceof Error ? error.message : String(error);\n logger.error(`Agent failed: ${agent.name}`, error instanceof Error ? error : new Error(String(error)));\n }\n\n result.duration = Date.now() - startTime;\n return result;\n }\n\n /**\n * Build directory coverage summary for prompts\n */\n private buildCoverageSummary(dirCoverage: DirectoryCoverage[]): string {\n const lines: string[] = [];\n\n // Summary stats\n const total = dirCoverage.length;\n const complete = dirCoverage.filter(d => d.mocStatus === 'complete').length;\n const stub = dirCoverage.filter(d => d.mocStatus === 'stub').length;\n const empty = dirCoverage.filter(d => d.mocStatus === 'empty').length;\n const missing = dirCoverage.filter(d => d.mocStatus === 'missing').length;\n\n lines.push(`### Summary`);\n lines.push(`- Total Directories: ${total}`);\n lines.push(`- Complete MOCs: ${complete} (${((complete / total) * 100).toFixed(1)}%)`);\n lines.push(`- Stub MOCs: ${stub}`);\n lines.push(`- Empty MOCs: ${empty}`);\n lines.push(`- Missing MOCs: ${missing}`);\n lines.push(`- Coverage Score: ${((complete / total) * 100).toFixed(1)}%`);\n lines.push('');\n\n // Directories needing work\n const needsWork = dirCoverage.filter(d => d.needsDocumentation);\n if (needsWork.length > 0) {\n lines.push('### Directories Needing Documentation');\n for (const dir of needsWork) {\n lines.push(`- **${dir.path}/** (${dir.mocStatus})`);\n lines.push(` - Documents: ${dir.documents.join(', ') || 'none'}`);\n lines.push(` - Subdirectories: ${dir.subdirectories.join(', ') || 'none'}`);\n lines.push(` - Reason: ${dir.reason}`);\n }\n lines.push('');\n }\n\n // Complete directories\n const completeDirs = dirCoverage.filter(d => d.mocStatus === 'complete');\n if (completeDirs.length > 0) {\n lines.push('### Directories with Complete MOCs');\n for (const dir of completeDirs) {\n lines.push(`- ${dir.path}/ (${dir.documentCount} docs)`);\n }\n }\n\n return lines.join('\\n');\n }\n\n /**\n * Build context-aware prompt for documentation cultivation\n */\n private buildPrompt(\n agent: AgentConfig,\n documents: DocMetadata[],\n keyDocs: Map<string, string>,\n dirCoverage: DirectoryCoverage[],\n previousAnalysis: PreviousAnalysis | null,\n sopGaps?: GapAnalysisResult\n ): string {\n // Build document inventory\n const inventory = documents.map(d => `- ${d.path} (${d.type}): ${d.title}`).join('\\n');\n\n // Build key document content\n const keyContent = Array.from(keyDocs.entries())\n .map(([name, content]) => `### ${name}\\n\\n${content}`)\n .join('\\n\\n---\\n\\n');\n\n // Build directory coverage summary\n const coverageSummary = this.buildCoverageSummary(dirCoverage);\n\n // Build iteration context\n const iterationContext = previousAnalysis\n ? `\\n## Previous Analysis (Iteration ${previousAnalysis.iteration})\n- Timestamp: ${previousAnalysis.timestamp}\n- Gaps Identified: ${previousAnalysis.gapsIdentified}\n- Gaps Filled: ${previousAnalysis.gapsFilled}\n- Questions Raised: ${previousAnalysis.questionsRaised}\n- Questions Answered: ${previousAnalysis.questionsAnswered}\n- Coverage Score: ${previousAnalysis.coverageScore.toFixed(1)}%\n\nFocus on NEW gaps and questions not addressed in previous iterations.\n`\n : '';\n\n // Agent-specific instructions\n let specificInstructions = '';\n switch (agent.type) {\n case 'coverage':\n specificInstructions = `\nFocus on directory structure and MOC (Map of Content) files:\n\n1. **Directory Analysis**: Review each directory and its MOC file status\n2. **Empty/Stub MOCs**: Identify MOC files that are empty or just stubs\n3. **Missing MOCs**: Identify directories that need MOC files\n4. **Documentation Needs**: For each directory, determine what documentation is needed\n5. **Not Needed**: If a directory genuinely doesn't need documentation, explain why\n\nFor each directory needing work:\n- State the directory path\n- Current MOC status (missing/empty/stub/complete)\n- What documentation should be added\n- Priority (high/medium/low)\n- Suggested content or links to include\n\nThe goal is 100% documentation coverage - every directory should either:\n1. Have a complete MOC with links to contents\n2. Have documentation explaining why it doesn't need more docs\n3. Be marked for future documentation\n\n## Directory Coverage Status\n${coverageSummary}`;\n break;\n\n case 'vision':\n specificInstructions = `\nFocus on:\n1. What is the core purpose/goal of this project?\n2. What problem does it solve?\n3. What is the target audience/user?\n4. What are the key success metrics?\n5. What is the overall architecture vision?\n\nProvide a clear, concise synthesis of the project vision with references to specific documentation.`;\n break;\n\n case 'gaps':\n specificInstructions = `\nIdentify:\n1. Missing documentation (what topics are mentioned but not explained?)\n2. Incomplete sections (what areas need more detail?)\n3. Outdated information (anything that seems inconsistent?)\n4. Missing examples or use cases\n5. Unclear terminology or concepts that need definitions\n6. Empty or stub MOC files that need content (see Directory Coverage below)\n\nFor each gap, specify:\n- What is missing\n- Where it should be documented (specific file path)\n- Why it's important\n- Priority (high/medium/low)\n\n## Directory Coverage Status\n${coverageSummary}`;\n break;\n\n case 'research':\n specificInstructions = `\nGenerate research questions in these categories:\n1. Technical questions (how should X be implemented?)\n2. Design decisions (why this approach vs alternatives?)\n3. Integration questions (how does X connect to Y?)\n4. Validation questions (how do we verify X works?)\n5. Scalability questions (will this work at scale?)\n\nFor each question:\n- State the question clearly\n- Explain why answering it is important\n- Suggest where to look for answers`;\n break;\n\n case 'connections':\n specificInstructions = `\nIdentify relationships between documented concepts:\n1. Dependencies (X requires Y)\n2. Extensions (X extends Y)\n3. Alternatives (X is an alternative to Y)\n4. Compositions (X is made up of Y and Z)\n5. References (X references Y for details)\n\nSuggest knowledge graph nodes and edges in this format:\n- [Node A] --relationship--> [Node B]: description\n\nAlso identify concepts that should be linked but aren't currently.`;\n break;\n\n case 'sop':\n specificInstructions = this.buildSOPAgentInstructions(sopGaps);\n break;\n }\n\n return `You are a documentation analyst helping to cultivate a knowledge graph.\n${iterationContext}\n## Your Task\n${agent.task}\n\n## Documentation Inventory\nThe following markdown documents exist in this project:\n${inventory}\n\n## Key Document Contents\n\n${keyContent}\n\n## Instructions\n${specificInstructions}\n\n## Output Format\nProvide your analysis in markdown format with:\n1. Clear section headings\n2. Specific observations (prefix with \"Observation:\")\n3. Specific recommendations (prefix with \"Recommendation:\")\n4. Key findings (prefix with \"Finding:\")\n5. Research questions where applicable (prefix with \"Question:\")\n6. Priority levels (high/medium/low) for actionable items\n\nReference specific documents using [[document-name]] wiki-link format where relevant.\nBe specific and actionable in your analysis.\n${previousAnalysis ? '\\nFocus on NEW items not identified in previous iterations.' : ''}`;\n }\n\n /**\n * Run SOP compliance check against the documentation\n */\n private async runSOPComplianceCheck(): Promise<ComplianceCheckResult | undefined> {\n try {\n logger.info('Running SOP compliance check', { projectRoot: this.projectRoot });\n\n // Run compliance check with project settings\n const result = await checkCompliance({\n projectRoot: this.projectRoot,\n docsPath: this.docsPath,\n deepAnalysis: false,\n assessor: 'deep-analyzer',\n });\n\n logger.info('SOP compliance check complete', {\n score: result.overallScore,\n compliant: result.assessments.filter(a => a.score >= 70).length,\n nonCompliant: result.assessments.filter(a => a.score < 70).length,\n });\n\n return result;\n } catch (error) {\n logger.warn('SOP compliance check failed', { error: error instanceof Error ? error.message : String(error) });\n return undefined;\n }\n }\n\n /**\n * Run SOP gap analysis on compliance results\n */\n private runSOPGapAnalysis(compliance: ComplianceCheckResult): GapAnalysisResult | undefined {\n try {\n const result = analyzeGaps(compliance, {\n complianceThreshold: 70,\n includePartial: true,\n generateRemediation: true,\n });\n\n logger.info('SOP gap analysis complete', {\n totalGaps: result.totalGaps,\n criticalGaps: result.criticalGaps.length,\n compliancePercentage: result.summary.compliancePercentage,\n });\n\n // Write gap analysis summary to output\n this.writeSOPGapsSummary(result);\n\n return result;\n } catch (error) {\n logger.warn('SOP gap analysis failed', { error: error instanceof Error ? error.message : String(error) });\n return undefined;\n }\n }\n\n /**\n * Write SOP gaps summary to analysis output\n */\n private writeSOPGapsSummary(gaps: GapAnalysisResult): void {\n const summaryPath = join(this.outputDir, 'sop-gaps-summary.json');\n\n try {\n const summary = {\n timestamp: new Date().toISOString(),\n totalGaps: gaps.totalGaps,\n criticalGaps: gaps.criticalGaps.length,\n summary: gaps.summary,\n byPriority: {\n critical: gaps.byPriority[SOPPriority.CRITICAL].length,\n high: gaps.byPriority[SOPPriority.HIGH].length,\n medium: gaps.byPriority[SOPPriority.MEDIUM].length,\n low: gaps.byPriority[SOPPriority.LOW].length,\n },\n byCategory: Object.entries(gaps.byCategory).reduce((acc, [key, value]) => {\n acc[key] = value.length;\n return acc;\n }, {} as Record<string, number>),\n gaps: gaps.gaps.map(g => ({\n id: g.id,\n sopId: g.sopId,\n requirementId: g.requirementId,\n description: g.description,\n priority: g.priority,\n effort: g.effort,\n remediation: g.remediation,\n })),\n roadmap: gaps.roadmap ? {\n phases: gaps.roadmap.phases.map(p => ({\n phase: p.phase,\n name: p.name,\n focus: p.focus,\n effort: p.effort,\n gapCount: p.gaps.length,\n })),\n quickWinsCount: gaps.roadmap.quickWins.length,\n } : undefined,\n };\n\n writeFileSync(summaryPath, JSON.stringify(summary, null, 2));\n logger.debug('Wrote SOP gaps summary', { path: summaryPath });\n } catch (error) {\n logger.warn('Failed to write SOP gaps summary', { error: error instanceof Error ? error.message : String(error) });\n }\n }\n\n /**\n * Build SOP agent-specific instructions with gap context\n */\n private buildSOPAgentInstructions(sopGaps?: GapAnalysisResult): string {\n let instructions = `\nAnalyze AI-SDLC SOP (Standard Operating Procedures) compliance gaps and recommend documentation:\n\n1. **Gap Prioritization**: Review the compliance gaps and prioritize by impact\n2. **Documentation Recommendations**: For each gap, suggest what documentation should be created\n3. **Remediation Steps**: Provide actionable steps to address each gap\n4. **Quick Wins**: Identify low-effort, high-impact gaps that can be addressed quickly\n5. **Documentation Templates**: Suggest document templates for common gap types\n\nFor each gap, recommend:\n- Document type (guide, standard, process, reference)\n- Suggested file path (using project conventions)\n- Key sections to include\n- Related documents to link to ([[wiki-links]])\n- Priority level (high/medium/low)\n`;\n\n if (sopGaps && sopGaps.totalGaps > 0) {\n instructions += `\n## Current SOP Compliance Gaps\n\n**Summary:**\n- Total Gaps: ${sopGaps.totalGaps}\n- Critical Gaps: ${sopGaps.criticalGaps.length}\n- Compliance Score: ${sopGaps.summary.compliancePercentage}%\n\n### Gaps by Priority:\n- Critical: ${sopGaps.byPriority[SOPPriority.CRITICAL].length}\n- High: ${sopGaps.byPriority[SOPPriority.HIGH].length}\n- Medium: ${sopGaps.byPriority[SOPPriority.MEDIUM].length}\n- Low: ${sopGaps.byPriority[SOPPriority.LOW].length}\n\n### Detailed Gaps:\n`;\n\n // Add critical and high priority gaps in detail\n const priorityGaps = [\n ...sopGaps.byPriority[SOPPriority.CRITICAL],\n ...sopGaps.byPriority[SOPPriority.HIGH],\n ].slice(0, 15); // Limit to top 15 to fit in context\n\n for (const gap of priorityGaps) {\n instructions += `\n#### ${gap.priority.toUpperCase()}: ${gap.description}\n- SOP: ${gap.sopId}\n- Requirement: ${gap.requirementId}\n- Effort: ${gap.effort}\n- Remediation: ${gap.remediation}\n- Impact: ${gap.impact}\n`;\n }\n\n if (sopGaps.roadmap) {\n instructions += `\n### Remediation Roadmap:\n`;\n for (const phase of sopGaps.roadmap.phases) {\n instructions += `\n**Phase ${phase.phase}: ${phase.name}**\n- Focus: ${phase.focus}\n- Effort: ${phase.effort}\n- Gaps to address: ${phase.gaps.length}\n`;\n }\n\n if (sopGaps.roadmap.quickWins.length > 0) {\n instructions += `\n### Quick Wins (High Impact, Low Effort):\n`;\n for (const win of sopGaps.roadmap.quickWins.slice(0, 5)) {\n instructions += `- ${win.description} (${win.effort} effort)\\n`;\n }\n }\n }\n } else {\n instructions += `\n## No SOP Gaps Data Available\n\nPerform a general AI-SDLC compliance analysis based on the documentation structure.\nReview for common compliance areas:\n- Requirements documentation\n- Architecture documentation\n- Testing documentation\n- Security documentation\n- Deployment documentation\n- Operational procedures\n`;\n }\n\n return instructions;\n }\n\n /**\n * Run analysis using Claude CLI\n */\n private async runWithCli(prompt: string): Promise<string> {\n const sanitizedPrompt = prompt\n .replace(/\"/g, '\\\\\"')\n .replace(/[`$]/g, '');\n\n try {\n const result = execSync(`claude -p \"${sanitizedPrompt}\"`, {\n cwd: this.projectRoot,\n encoding: 'utf8',\n timeout: this.agentTimeout,\n maxBuffer: 10 * 1024 * 1024,\n });\n return result;\n } catch (error) {\n if (error instanceof Error) {\n const execError = error as { stderr?: string; stdout?: string; killed?: boolean };\n if (execError.killed) {\n if (execError.stdout && execError.stdout.length > 100) {\n return execError.stdout;\n }\n throw new Error(`Claude CLI timed out after ${this.agentTimeout / 1000}s`);\n }\n throw new Error(execError.stderr || error.message);\n }\n throw error;\n }\n }\n\n /**\n * Run analysis using Anthropic API directly\n */\n private async runWithAnthropic(prompt: string): Promise<string> {\n const apiKey = process.env.ANTHROPIC_API_KEY;\n if (!apiKey) {\n throw new Error('ANTHROPIC_API_KEY not set');\n }\n\n try {\n const { default: Anthropic } = await import('@anthropic-ai/sdk');\n const client = new Anthropic({ apiKey });\n\n const response = await client.messages.create({\n model: 'claude-sonnet-4-20250514',\n max_tokens: 4096,\n messages: [{ role: 'user', content: prompt }],\n });\n\n const textBlock = response.content.find(block => block.type === 'text');\n if (textBlock && textBlock.type === 'text') {\n return textBlock.text;\n }\n\n throw new Error('No text content in API response');\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Anthropic API call failed: ${error.message}`);\n }\n throw error;\n }\n }\n\n /**\n * Run analysis using Google Gemini API\n */\n private async runWithGemini(prompt: string): Promise<string> {\n const apiKey = this.getGeminiApiKey();\n if (!apiKey) {\n throw new Error('GOOGLE_AI_API_KEY not set');\n }\n\n try {\n const { GoogleGenerativeAI } = await import('@google/generative-ai');\n const genAI = new GoogleGenerativeAI(apiKey);\n const model = genAI.getGenerativeModel({ model: 'gemini-2.5-flash' });\n\n const result = await model.generateContent(prompt);\n const response = result.response;\n const text = response.text();\n\n if (!text) {\n throw new Error('No text content in Gemini response');\n }\n\n return text;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Gemini API call failed: ${error.message}`);\n }\n throw error;\n }\n }\n\n /**\n * Extract insights from agent output\n */\n private extractInsights(output: string): string[] {\n const insights: string[] = [];\n\n const patterns = [\n /[-*]?\\s*(?:insight|finding|observation|recommendation|question):\\s*(.+)/gi,\n /##\\s*(?:insight|finding|observation|recommendation|question):\\s*(.+)/gi,\n /(?:key\\s+)?(?:insight|finding|observation|recommendation|question):\\s*(.+)/gi,\n ];\n\n for (const pattern of patterns) {\n const matches = output.matchAll(pattern);\n for (const match of matches) {\n if (match[1]) {\n insights.push(match[1].trim());\n }\n }\n }\n\n return [...new Set(insights)];\n }\n\n /**\n * Format output for documentation\n */\n private formatOutput(agent: AgentConfig, output: string, mode: string): string {\n const timestamp = new Date().toISOString();\n\n return `---\ntitle: \"${agent.name}\"\ntype: cultivation-analysis\ngenerator: deep-analyzer\nagent: ${agent.type}\nprovider: ${mode}\ncreated: ${timestamp}\n---\n\n# ${agent.name}\n\n> Generated by DeepAnalyzer for documentation cultivation\n\n## Purpose\n\n${agent.task}\n\n## Analysis\n\n${output}\n\n---\n\n*Generated on ${new Date().toLocaleString()}*\n`;\n }\n}\n\n/**\n * Create a deep analyzer instance\n */\nexport function createDeepAnalyzer(options: DeepAnalyzerOptions): DeepAnalyzer {\n return new DeepAnalyzer(options);\n}\n\n/**\n * Run deep analysis on a project\n */\nexport async function analyzeDeep(\n projectRoot: string,\n docsPath?: string\n): Promise<DeepAnalysisResult> {\n const analyzer = new DeepAnalyzer({ projectRoot, docsPath });\n return analyzer.analyze();\n}\n"],"names":[],"mappings":"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"}
|