specweave 0.32.0 → 0.32.2
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/CLAUDE.md +176 -2
- package/README.md +22 -0
- package/bin/specweave.js +18 -1
- package/dist/src/cli/commands/cache.d.ts +17 -0
- package/dist/src/cli/commands/cache.d.ts.map +1 -0
- package/dist/src/cli/commands/cache.js +126 -0
- package/dist/src/cli/commands/cache.js.map +1 -0
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/plan/increment-detector.js +2 -2
- package/dist/src/cli/commands/plan/increment-detector.js.map +1 -1
- package/dist/src/cli/commands/sync-spec-commits.js +1 -1
- package/dist/src/cli/commands/sync-spec-commits.js.map +1 -1
- package/dist/src/cli/commands/sync-specs.js +2 -2
- package/dist/src/cli/commands/sync-specs.js.map +1 -1
- package/dist/src/cli/helpers/github/increment-profile-selector.js +1 -1
- package/dist/src/cli/helpers/github/increment-profile-selector.js.map +1 -1
- package/dist/src/cli/workers/living-docs-worker.js +66 -1
- package/dist/src/cli/workers/living-docs-worker.js.map +1 -1
- package/dist/src/config/types.d.ts +203 -1208
- package/dist/src/config/types.d.ts.map +1 -1
- package/dist/src/core/discrepancy/increment-generator.d.ts.map +1 -1
- package/dist/src/core/discrepancy/increment-generator.js +5 -2
- package/dist/src/core/discrepancy/increment-generator.js.map +1 -1
- package/dist/src/core/increment/duplicate-detector.js +2 -2
- package/dist/src/core/increment/duplicate-detector.js.map +1 -1
- package/dist/src/core/increment/increment-archiver.d.ts +24 -0
- package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
- package/dist/src/core/increment/increment-archiver.js +59 -2
- package/dist/src/core/increment/increment-archiver.js.map +1 -1
- package/dist/src/core/increment/increment-status.js +2 -2
- package/dist/src/core/increment/increment-status.js.map +1 -1
- package/dist/src/core/increment/increment-utils.d.ts +85 -0
- package/dist/src/core/increment/increment-utils.d.ts.map +1 -1
- package/dist/src/core/increment/increment-utils.js +102 -4
- package/dist/src/core/increment/increment-utils.js.map +1 -1
- package/dist/src/core/increment/metadata-validator.js +1 -1
- package/dist/src/core/increment/metadata-validator.js.map +1 -1
- package/dist/src/core/living-docs/feature-id-manager.js +1 -1
- package/dist/src/core/living-docs/feature-id-manager.js.map +1 -1
- package/dist/src/core/living-docs/hierarchy-mapper.js +3 -3
- package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.d.ts +18 -0
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js +247 -0
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.d.ts +15 -0
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.js +138 -0
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.d.ts +24 -0
- package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.js +198 -0
- package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.d.ts +17 -0
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.js +241 -0
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/index.d.ts +28 -0
- package/dist/src/core/living-docs/intelligent-analyzer/index.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/index.js +197 -0
- package/dist/src/core/living-docs/intelligent-analyzer/index.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts +18 -0
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js +154 -0
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.d.ts +42 -0
- package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.js +343 -0
- package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts +146 -0
- package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/types.js +7 -0
- package/dist/src/core/living-docs/intelligent-analyzer/types.js.map +1 -0
- package/dist/src/core/living-docs/living-docs-sync.d.ts +5 -0
- package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +36 -2
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
- package/dist/src/core/sync/spec-increment-mapper.js +3 -3
- package/dist/src/core/sync/spec-increment-mapper.js.map +1 -1
- package/dist/src/importers/item-converter.d.ts +25 -0
- package/dist/src/importers/item-converter.d.ts.map +1 -1
- package/dist/src/importers/item-converter.js +135 -5
- package/dist/src/importers/item-converter.js.map +1 -1
- package/dist/src/init/architecture/types.d.ts +33 -140
- package/dist/src/init/architecture/types.d.ts.map +1 -1
- package/dist/src/init/compliance/types.d.ts +30 -27
- package/dist/src/init/compliance/types.d.ts.map +1 -1
- package/dist/src/init/repo/types.d.ts +11 -34
- package/dist/src/init/repo/types.d.ts.map +1 -1
- package/dist/src/init/research/src/config/types.d.ts +15 -82
- package/dist/src/init/research/src/config/types.d.ts.map +1 -1
- package/dist/src/init/research/types.d.ts +38 -93
- package/dist/src/init/research/types.d.ts.map +1 -1
- package/dist/src/init/team/types.d.ts +4 -42
- package/dist/src/init/team/types.d.ts.map +1 -1
- package/dist/src/types/dashboard-cache.d.ts +181 -0
- package/dist/src/types/dashboard-cache.d.ts.map +1 -0
- package/dist/src/types/dashboard-cache.js +65 -0
- package/dist/src/types/dashboard-cache.js.map +1 -0
- package/dist/src/utils/docs-validator.d.ts +131 -0
- package/dist/src/utils/docs-validator.d.ts.map +1 -0
- package/dist/src/utils/docs-validator.js +529 -0
- package/dist/src/utils/docs-validator.js.map +1 -0
- package/dist/src/utils/feature-id-collision.js +1 -1
- package/dist/src/utils/feature-id-collision.js.map +1 -1
- package/dist/src/utils/html-to-mdx.d.ts +1 -0
- package/dist/src/utils/html-to-mdx.d.ts.map +1 -1
- package/dist/src/utils/html-to-mdx.js +43 -5
- package/dist/src/utils/html-to-mdx.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/agents/pm/AGENT.md +10 -7
- package/plugins/specweave/commands/specweave-archive-features.md +5 -7
- package/plugins/specweave/commands/specweave-archive.md +2 -1
- package/plugins/specweave/commands/specweave-do.md +35 -1
- package/plugins/specweave/commands/specweave-done.md +96 -0
- package/plugins/specweave/commands/specweave-import-external.md +45 -18
- package/plugins/specweave/commands/specweave-increment.md +331 -33
- package/plugins/specweave/commands/specweave-jobs.md +2 -2
- package/plugins/specweave/commands/specweave-progress.md +4 -4
- package/plugins/specweave/commands/specweave-restore-feature.md +5 -4
- package/plugins/specweave/commands/specweave-sync-docs.md +1 -1
- package/plugins/specweave/commands/specweave-sync-specs.md +216 -322
- package/plugins/specweave/commands/specweave-validate-features.md +13 -8
- package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
- package/plugins/specweave/hooks/hooks.json +33 -4
- package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
- package/plugins/specweave/hooks/lib/common-setup.sh +375 -0
- package/plugins/specweave/hooks/lib/crash-prevention.sh +336 -0
- package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
- package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
- package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
- package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
- package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
- package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
- package/plugins/specweave/hooks/post-task-completion.sh +4 -23
- package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
- package/plugins/specweave/hooks/pre-command-deduplication.sh +1 -6
- package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
- package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
- package/plugins/specweave/hooks/pre-task-completion.sh +8 -37
- package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
- package/plugins/specweave/hooks/pre-tool-use.sh +2 -11
- package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
- package/plugins/specweave/hooks/universal/dispatcher.mjs +135 -42
- package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +183 -0
- package/plugins/specweave/hooks/user-prompt-submit.sh +140 -38
- package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +12 -0
- package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +89 -0
- package/plugins/specweave/hooks/v2/guards/bash-file-guard.sh +211 -0
- package/plugins/specweave/hooks/v2/guards/bash-file-guard.test.sh +163 -0
- package/plugins/specweave/hooks/v2/guards/completion-guard.sh +26 -28
- package/plugins/specweave/hooks/v2/guards/features-folder-guard.sh +50 -0
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +2 -2
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -1
- package/plugins/specweave/scripts/README.md +166 -0
- package/plugins/specweave/scripts/cleanup-state.sh +142 -0
- package/plugins/specweave/scripts/force-kill.sh +142 -0
- package/plugins/specweave/scripts/jobs.js +171 -0
- package/plugins/specweave/scripts/progress.js +170 -0
- package/plugins/specweave/scripts/read-costs.sh +132 -0
- package/plugins/specweave/scripts/read-jobs.sh +324 -0
- package/plugins/specweave/scripts/read-progress.sh +185 -0
- package/plugins/specweave/scripts/read-status.sh +146 -0
- package/plugins/specweave/scripts/read-workflow.sh +173 -0
- package/plugins/specweave/scripts/rebuild-dashboard-cache.sh +327 -0
- package/plugins/specweave/scripts/session-watchdog.sh +192 -0
- package/plugins/specweave/scripts/status.js +154 -0
- package/plugins/specweave/scripts/update-dashboard-cache.sh +281 -0
- package/plugins/specweave/skills/increment-planner/SKILL.md +333 -24
- package/plugins/specweave/skills/increment-planner/templates/spec-multi-project.md +17 -9
- package/plugins/specweave/skills/increment-planner/templates/spec-single-project.md +6 -2
- package/plugins/specweave/skills/instant-status/SKILL.md +70 -0
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
- package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
- package/plugins/specweave-docs/commands/build.md +32 -4
- package/plugins/specweave-docs/commands/preview.md +43 -1
- package/plugins/specweave-docs/commands/validate.md +250 -0
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +1262 -0
- package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
- package/plugins/specweave-github/lib/enhanced-github-sync.js +220 -0
- package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +134 -0
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +1254 -0
- package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
- package/plugins/specweave/hooks/post-edit-spec.sh +0 -265
- package/plugins/specweave/hooks/post-write-spec.sh +0 -267
- package/plugins/specweave/hooks/pre-edit-spec.sh +0 -151
- package/plugins/specweave/hooks/pre-write-spec.sh +0 -151
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architecture Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates C4 diagrams and detects architectural decisions
|
|
5
|
+
* from the organization structure and repo analyses.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import { extractJson, buildJsonPrompt } from '../../../utils/llm-json-extractor.js';
|
|
10
|
+
export async function generateArchitecture(repoAnalyses, orgResult, projectPath, llmProvider, onProgress, log) {
|
|
11
|
+
log('PHASE D: Architecture Generation');
|
|
12
|
+
onProgress('architecture', 0, 100, 'Generating C4 diagrams');
|
|
13
|
+
const context = buildArchitectureContext(repoAnalyses, orgResult);
|
|
14
|
+
if (!llmProvider) {
|
|
15
|
+
log(' No LLM provider, using basic diagram generation');
|
|
16
|
+
return createBasicArchitecture(repoAnalyses, orgResult);
|
|
17
|
+
}
|
|
18
|
+
onProgress('architecture', 20, 100, 'LLM C4 diagram generation');
|
|
19
|
+
try {
|
|
20
|
+
const c4Result = await generateC4Diagrams(context, llmProvider, log);
|
|
21
|
+
onProgress('architecture', 50, 100, 'Detecting architectural patterns');
|
|
22
|
+
const adrs = await detectArchitecturalDecisions(repoAnalyses, llmProvider, log);
|
|
23
|
+
onProgress('architecture', 80, 100, 'Finalizing architecture docs');
|
|
24
|
+
return {
|
|
25
|
+
c4Context: c4Result.context,
|
|
26
|
+
c4Container: c4Result.container,
|
|
27
|
+
dataFlow: c4Result.dataFlow,
|
|
28
|
+
detectedAdrs: adrs,
|
|
29
|
+
confidence: 'medium',
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
log(` Architecture generation error: ${err.message}`);
|
|
34
|
+
return createBasicArchitecture(repoAnalyses, orgResult);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function buildArchitectureContext(analyses, org) {
|
|
38
|
+
const lines = ['# System Overview', ''];
|
|
39
|
+
if (org.teams.length > 0) {
|
|
40
|
+
lines.push('## Teams');
|
|
41
|
+
for (const team of org.teams) {
|
|
42
|
+
lines.push(`- **${team.name}**: ${team.repos.join(', ')}`);
|
|
43
|
+
}
|
|
44
|
+
lines.push('');
|
|
45
|
+
}
|
|
46
|
+
if (org.microservices.length > 0) {
|
|
47
|
+
lines.push('## Microservices');
|
|
48
|
+
for (const svc of org.microservices) {
|
|
49
|
+
lines.push(`- **${svc.name}**: ${svc.description}`);
|
|
50
|
+
}
|
|
51
|
+
lines.push('');
|
|
52
|
+
}
|
|
53
|
+
lines.push('## Key APIs');
|
|
54
|
+
for (const [name, analysis] of analyses) {
|
|
55
|
+
if (analysis.mainApis.length > 0) {
|
|
56
|
+
const apis = analysis.mainApis.slice(0, 3).map(a => a.name).join(', ');
|
|
57
|
+
lines.push(`- **${name}**: ${apis}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
lines.push('');
|
|
61
|
+
lines.push('## Detected Patterns');
|
|
62
|
+
const allPatterns = new Map();
|
|
63
|
+
for (const [name, analysis] of analyses) {
|
|
64
|
+
for (const p of analysis.patternsUsed) {
|
|
65
|
+
if (!allPatterns.has(p.pattern))
|
|
66
|
+
allPatterns.set(p.pattern, []);
|
|
67
|
+
allPatterns.get(p.pattern).push(name);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
for (const [pattern, repos] of allPatterns) {
|
|
71
|
+
lines.push(`- **${pattern}**: ${repos.join(', ')}`);
|
|
72
|
+
}
|
|
73
|
+
return lines.join('\n');
|
|
74
|
+
}
|
|
75
|
+
async function generateC4Diagrams(context, llmProvider, log) {
|
|
76
|
+
const schema = {
|
|
77
|
+
contextDiagram: 'Mermaid C4Context diagram code',
|
|
78
|
+
containerDiagram: 'Mermaid C4Container diagram code',
|
|
79
|
+
dataFlowDiagram: 'Mermaid flowchart for data flow',
|
|
80
|
+
};
|
|
81
|
+
const prompt = buildJsonPrompt(`${context}\n\nGenerate Mermaid diagrams. Use C4Context for high-level, C4Container for services, flowchart TD for data flow.`, schema, 'Generate architecture diagrams in Mermaid format.');
|
|
82
|
+
try {
|
|
83
|
+
const result = await llmProvider.analyze(prompt);
|
|
84
|
+
if (!result?.content) {
|
|
85
|
+
return createBasicDiagrams();
|
|
86
|
+
}
|
|
87
|
+
const extraction = extractJson(result.content, { requiredFields: [] });
|
|
88
|
+
if (extraction.success && extraction.data) {
|
|
89
|
+
log(' C4 diagrams generated successfully');
|
|
90
|
+
return {
|
|
91
|
+
context: extraction.data.contextDiagram || createBasicContextDiagram(),
|
|
92
|
+
container: extraction.data.containerDiagram || createBasicContainerDiagram(),
|
|
93
|
+
dataFlow: extraction.data.dataFlowDiagram || createBasicDataFlow(),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
log(' C4 diagram generation failed, using basic');
|
|
99
|
+
}
|
|
100
|
+
return createBasicDiagrams();
|
|
101
|
+
}
|
|
102
|
+
async function detectArchitecturalDecisions(analyses, llmProvider, log) {
|
|
103
|
+
const patternMap = new Map();
|
|
104
|
+
for (const [name, analysis] of analyses) {
|
|
105
|
+
for (const p of analysis.patternsUsed) {
|
|
106
|
+
if (!patternMap.has(p.pattern)) {
|
|
107
|
+
patternMap.set(p.pattern, { repos: [], evidence: [] });
|
|
108
|
+
}
|
|
109
|
+
const entry = patternMap.get(p.pattern);
|
|
110
|
+
entry.repos.push(name);
|
|
111
|
+
entry.evidence.push(...p.evidence);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const adrs = [];
|
|
115
|
+
let adrNum = 1;
|
|
116
|
+
for (const [pattern, data] of patternMap) {
|
|
117
|
+
if (data.repos.length >= 2) {
|
|
118
|
+
adrs.push({
|
|
119
|
+
id: `DETECTED-${String(adrNum).padStart(4, '0')}`,
|
|
120
|
+
title: `Use ${pattern}`,
|
|
121
|
+
pattern,
|
|
122
|
+
status: 'Detected',
|
|
123
|
+
context: `Found ${pattern} pattern in ${data.repos.length} repositories.`,
|
|
124
|
+
decision: `The team has adopted ${pattern} as a standard approach.`,
|
|
125
|
+
consequences: [
|
|
126
|
+
`Consistent ${pattern} implementation across services`,
|
|
127
|
+
'Team familiarity with the pattern',
|
|
128
|
+
],
|
|
129
|
+
evidence: [{
|
|
130
|
+
repo: data.repos.join(', '),
|
|
131
|
+
files: [],
|
|
132
|
+
description: data.evidence.slice(0, 3).join('; '),
|
|
133
|
+
}],
|
|
134
|
+
confidence: data.repos.length >= 3 ? 'high' : 'medium',
|
|
135
|
+
});
|
|
136
|
+
adrNum++;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
log(` Detected ${adrs.length} architectural decisions`);
|
|
140
|
+
return adrs;
|
|
141
|
+
}
|
|
142
|
+
function createBasicArchitecture(analyses, org) {
|
|
143
|
+
return {
|
|
144
|
+
c4Context: createBasicContextDiagram(),
|
|
145
|
+
c4Container: createBasicContainerDiagram(),
|
|
146
|
+
dataFlow: createBasicDataFlow(),
|
|
147
|
+
detectedAdrs: [],
|
|
148
|
+
confidence: 'low',
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function createBasicDiagrams() {
|
|
152
|
+
return {
|
|
153
|
+
context: createBasicContextDiagram(),
|
|
154
|
+
container: createBasicContainerDiagram(),
|
|
155
|
+
dataFlow: createBasicDataFlow(),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function createBasicContextDiagram() {
|
|
159
|
+
return `C4Context
|
|
160
|
+
title System Context Diagram
|
|
161
|
+
Person(user, "User", "System user")
|
|
162
|
+
System(system, "System", "The system under analysis")
|
|
163
|
+
Rel(user, system, "Uses")`;
|
|
164
|
+
}
|
|
165
|
+
function createBasicContainerDiagram() {
|
|
166
|
+
return `C4Container
|
|
167
|
+
title Container Diagram
|
|
168
|
+
Container(api, "API", "REST/GraphQL", "Main API surface")
|
|
169
|
+
Container(db, "Database", "Storage", "Data persistence")
|
|
170
|
+
Rel(api, db, "Reads/Writes")`;
|
|
171
|
+
}
|
|
172
|
+
function createBasicDataFlow() {
|
|
173
|
+
return `flowchart TD
|
|
174
|
+
A[Client] --> B[API Gateway]
|
|
175
|
+
B --> C[Services]
|
|
176
|
+
C --> D[Database]`;
|
|
177
|
+
}
|
|
178
|
+
export async function saveArchitecture(projectPath, result) {
|
|
179
|
+
const savedFiles = [];
|
|
180
|
+
const archPath = path.join(projectPath, '.specweave/docs/internal/architecture');
|
|
181
|
+
const diagramsPath = path.join(archPath, 'diagrams');
|
|
182
|
+
const adrPath = path.join(archPath, 'adr');
|
|
183
|
+
fs.mkdirSync(diagramsPath, { recursive: true });
|
|
184
|
+
fs.mkdirSync(adrPath, { recursive: true });
|
|
185
|
+
const contextFile = path.join(diagramsPath, 'c4-context.md');
|
|
186
|
+
fs.writeFileSync(contextFile, [
|
|
187
|
+
'# C4 Context Diagram',
|
|
188
|
+
'',
|
|
189
|
+
'*Auto-generated by Intelligent Analyzer*',
|
|
190
|
+
'',
|
|
191
|
+
'```mermaid',
|
|
192
|
+
result.c4Context,
|
|
193
|
+
'```',
|
|
194
|
+
].join('\n'));
|
|
195
|
+
savedFiles.push(contextFile);
|
|
196
|
+
const containerFile = path.join(diagramsPath, 'c4-container.md');
|
|
197
|
+
fs.writeFileSync(containerFile, [
|
|
198
|
+
'# C4 Container Diagram',
|
|
199
|
+
'',
|
|
200
|
+
'*Auto-generated by Intelligent Analyzer*',
|
|
201
|
+
'',
|
|
202
|
+
'```mermaid',
|
|
203
|
+
result.c4Container,
|
|
204
|
+
'```',
|
|
205
|
+
].join('\n'));
|
|
206
|
+
savedFiles.push(containerFile);
|
|
207
|
+
const dataFlowFile = path.join(diagramsPath, 'data-flow.md');
|
|
208
|
+
fs.writeFileSync(dataFlowFile, [
|
|
209
|
+
'# Data Flow Diagram',
|
|
210
|
+
'',
|
|
211
|
+
'*Auto-generated by Intelligent Analyzer*',
|
|
212
|
+
'',
|
|
213
|
+
'```mermaid',
|
|
214
|
+
result.dataFlow,
|
|
215
|
+
'```',
|
|
216
|
+
].join('\n'));
|
|
217
|
+
savedFiles.push(dataFlowFile);
|
|
218
|
+
for (const adr of result.detectedAdrs) {
|
|
219
|
+
const adrFile = path.join(adrPath, `${adr.id}.md`);
|
|
220
|
+
const content = [
|
|
221
|
+
`# ${adr.id}: ${adr.title}`,
|
|
222
|
+
'',
|
|
223
|
+
`**Status**: ${adr.status}`,
|
|
224
|
+
`**Confidence**: ${adr.confidence}`,
|
|
225
|
+
'',
|
|
226
|
+
'## Context',
|
|
227
|
+
'',
|
|
228
|
+
adr.context,
|
|
229
|
+
'',
|
|
230
|
+
'## Decision',
|
|
231
|
+
'',
|
|
232
|
+
adr.decision,
|
|
233
|
+
'',
|
|
234
|
+
'## Consequences',
|
|
235
|
+
'',
|
|
236
|
+
...adr.consequences.map(c => `- ${c}`),
|
|
237
|
+
'',
|
|
238
|
+
'## Evidence',
|
|
239
|
+
'',
|
|
240
|
+
...adr.evidence.map(e => `- **${e.repo}**: ${e.description}`),
|
|
241
|
+
].join('\n');
|
|
242
|
+
fs.writeFileSync(adrFile, content);
|
|
243
|
+
savedFiles.push(adrFile);
|
|
244
|
+
}
|
|
245
|
+
return savedFiles;
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=architecture-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architecture-generator.js","sourceRoot":"","sources":["../../../../../src/core/living-docs/intelligent-analyzer/architecture-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep Repo Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Uses LLM to deeply understand each repository's purpose,
|
|
5
|
+
* key concepts, APIs, and patterns.
|
|
6
|
+
*/
|
|
7
|
+
import type { RepoAnalysis, LLMProvider, ProgressCallback } from './types.js';
|
|
8
|
+
export declare function analyzeRepo(repoPath: string, repoName: string, llmProvider: LLMProvider | null, log: (msg: string) => void): Promise<RepoAnalysis>;
|
|
9
|
+
export declare function analyzeAllRepos(repos: Array<{
|
|
10
|
+
name: string;
|
|
11
|
+
path: string;
|
|
12
|
+
}>, llmProvider: LLMProvider | null, onProgress: ProgressCallback, log: (msg: string) => void, checkpoint?: {
|
|
13
|
+
reposCompleted: string[];
|
|
14
|
+
}): Promise<Map<string, RepoAnalysis>>;
|
|
15
|
+
//# sourceMappingURL=deep-repo-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deep-repo-analyzer.d.ts","sourceRoot":"","sources":["../../../../../src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,YAAY,EAGZ,WAAW,EACX,gBAAgB,EAEjB,MAAM,YAAY,CAAC;AAEpB,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,WAAW,GAAG,IAAI,EAC/B,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GACzB,OAAO,CAAC,YAAY,CAAC,CA2BvB;AAmFD,wBAAsB,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAAE,UAAU,CAAC,EAAE;IAAE,cAAc,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAY5P"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep Repo Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Uses LLM to deeply understand each repository's purpose,
|
|
5
|
+
* key concepts, APIs, and patterns.
|
|
6
|
+
*/
|
|
7
|
+
import { sampleRepoFiles, formatSamplesForPrompt } from './file-sampler.js';
|
|
8
|
+
import { extractJson, buildJsonPrompt } from '../../../utils/llm-json-extractor.js';
|
|
9
|
+
export async function analyzeRepo(repoPath, repoName, llmProvider, log) {
|
|
10
|
+
log(` Sampling files from ${repoName}...`);
|
|
11
|
+
const samples = await sampleRepoFiles(repoPath);
|
|
12
|
+
log(` Sampled ${samples.length} files`);
|
|
13
|
+
if (!llmProvider) {
|
|
14
|
+
return createBasicAnalysis(repoPath, repoName, samples);
|
|
15
|
+
}
|
|
16
|
+
const prompt = buildRepoAnalysisPrompt(repoName, samples);
|
|
17
|
+
log(` Sending to LLM for deep analysis...`);
|
|
18
|
+
try {
|
|
19
|
+
const result = await llmProvider.analyze(prompt);
|
|
20
|
+
if (!result || !result.content) {
|
|
21
|
+
return createBasicAnalysis(repoPath, repoName, samples);
|
|
22
|
+
}
|
|
23
|
+
const extraction = extractJson(result.content, { requiredFields: ['purpose'] });
|
|
24
|
+
if (extraction.success && extraction.data) {
|
|
25
|
+
log(` LLM analysis successful`);
|
|
26
|
+
return convertLLMResponse(repoPath, repoName, extraction.data, samples.length);
|
|
27
|
+
}
|
|
28
|
+
return createBasicAnalysis(repoPath, repoName, samples);
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
log(` LLM error: ${err.message}`);
|
|
32
|
+
return createBasicAnalysis(repoPath, repoName, samples);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function buildRepoAnalysisPrompt(repoName, samples) {
|
|
36
|
+
const filesContent = formatSamplesForPrompt(samples);
|
|
37
|
+
const schema = {
|
|
38
|
+
purpose: 'string (2-3 sentences)',
|
|
39
|
+
keyConcepts: '["concept1", ...]',
|
|
40
|
+
mainApis: '[{name, type, description, location}, ...]',
|
|
41
|
+
patternsUsed: '[{pattern, category, evidence}, ...]',
|
|
42
|
+
internalDependencies: '["repo1", ...]',
|
|
43
|
+
externalDependencies: '["service1", ...]',
|
|
44
|
+
observations: '["observation1", ...]',
|
|
45
|
+
};
|
|
46
|
+
const context = `Repository: ${repoName}\n\nKey files:\n${filesContent}\n\nBe SPECIFIC. Don't say "handles data" - say "processes DICOM medical images".`;
|
|
47
|
+
return buildJsonPrompt(context, schema, 'Analyze this repository.');
|
|
48
|
+
}
|
|
49
|
+
function convertLLMResponse(repoPath, repoName, response, filesAnalyzed) {
|
|
50
|
+
return {
|
|
51
|
+
name: repoName, path: repoPath, purpose: response.purpose || 'Purpose not determined',
|
|
52
|
+
keyConcepts: response.keyConcepts || [],
|
|
53
|
+
mainApis: (response.mainApis || []).map(api => ({ name: api.name, type: api.type || 'function', description: api.description, location: api.location || '' })),
|
|
54
|
+
patternsUsed: (response.patternsUsed || []).map(p => ({ pattern: p.pattern, category: p.category || 'other', evidence: p.evidence || [], confidence: 'medium' })),
|
|
55
|
+
internalDependencies: response.internalDependencies || [], externalDependencies: response.externalDependencies || [],
|
|
56
|
+
filesAnalyzed, confidence: filesAnalyzed > 10 ? 'high' : filesAnalyzed > 5 ? 'medium' : 'low',
|
|
57
|
+
analyzedAt: new Date().toISOString(), observations: response.observations || [],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function createBasicAnalysis(repoPath, repoName, samples) {
|
|
61
|
+
const purpose = extractPurposeFromReadme(samples) || `Repository with ${samples.length} files`;
|
|
62
|
+
return { name: repoName, path: repoPath, purpose, keyConcepts: [], mainApis: extractBasicApis(samples),
|
|
63
|
+
patternsUsed: detectBasicPatterns(samples), internalDependencies: [], externalDependencies: extractDependencies(samples),
|
|
64
|
+
filesAnalyzed: samples.length, confidence: 'low', analyzedAt: new Date().toISOString(), observations: [] };
|
|
65
|
+
}
|
|
66
|
+
function extractPurposeFromReadme(samples) {
|
|
67
|
+
const readme = samples.find(s => s.type === 'readme');
|
|
68
|
+
if (!readme)
|
|
69
|
+
return null;
|
|
70
|
+
const lines = readme.content.split('\n');
|
|
71
|
+
let foundTitle = false, purposeLines = [];
|
|
72
|
+
for (const line of lines) {
|
|
73
|
+
if (line.startsWith('#') && !foundTitle) {
|
|
74
|
+
foundTitle = true;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (foundTitle && line.trim()) {
|
|
78
|
+
if (line.startsWith('#'))
|
|
79
|
+
break;
|
|
80
|
+
purposeLines.push(line.trim());
|
|
81
|
+
if (purposeLines.length >= 3)
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return purposeLines.length > 0 ? purposeLines.join(' ') : null;
|
|
86
|
+
}
|
|
87
|
+
function detectBasicPatterns(samples) {
|
|
88
|
+
const patterns = [];
|
|
89
|
+
const content = samples.map(s => s.content).join('\n');
|
|
90
|
+
if (content.includes('express') || content.includes('fastify'))
|
|
91
|
+
patterns.push({ pattern: 'REST API', category: 'api', evidence: ['Framework detected'], confidence: 'high' });
|
|
92
|
+
if (content.includes('graphql'))
|
|
93
|
+
patterns.push({ pattern: 'GraphQL', category: 'api', evidence: ['GraphQL imports'], confidence: 'high' });
|
|
94
|
+
if (content.includes('prisma') || content.includes('typeorm'))
|
|
95
|
+
patterns.push({ pattern: 'ORM', category: 'data', evidence: ['ORM detected'], confidence: 'high' });
|
|
96
|
+
if (content.includes('jwt'))
|
|
97
|
+
patterns.push({ pattern: 'JWT Auth', category: 'auth', evidence: ['JWT library'], confidence: 'high' });
|
|
98
|
+
return patterns;
|
|
99
|
+
}
|
|
100
|
+
function extractBasicApis(samples) {
|
|
101
|
+
const apis = [];
|
|
102
|
+
for (const s of samples.filter(s => s.type === 'api' || s.type === 'entry')) {
|
|
103
|
+
const matches = s.content.matchAll(/export\s+(async\s+)?(?:function|const|class)\s+(\w+)/g);
|
|
104
|
+
for (const m of matches)
|
|
105
|
+
apis.push({ name: m[2], type: m[0].includes('class') ? 'class' : 'function', description: 'From ' + s.path, location: s.path });
|
|
106
|
+
}
|
|
107
|
+
return apis.slice(0, 10);
|
|
108
|
+
}
|
|
109
|
+
function extractDependencies(samples) {
|
|
110
|
+
const pkg = samples.find(s => s.path === 'package.json');
|
|
111
|
+
if (!pkg)
|
|
112
|
+
return [];
|
|
113
|
+
try {
|
|
114
|
+
const p = JSON.parse(pkg.content);
|
|
115
|
+
return Object.keys(p.dependencies || {}).filter(d => /aws|azure|redis|mongo|postgres|kafka/.test(d)).slice(0, 5);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
export async function analyzeAllRepos(repos, llmProvider, onProgress, log, checkpoint) {
|
|
122
|
+
const results = new Map();
|
|
123
|
+
const completed = new Set(checkpoint?.reposCompleted || []);
|
|
124
|
+
for (let i = 0; i < repos.length; i++) {
|
|
125
|
+
const repo = repos[i];
|
|
126
|
+
if (completed.has(repo.name)) {
|
|
127
|
+
log(` Skipping ${repo.name} (done)`);
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
onProgress('deep-analysis', i + 1, repos.length, `Analyzing ${repo.name}`);
|
|
131
|
+
log(`Analyzing ${i + 1}/${repos.length}: ${repo.name}`);
|
|
132
|
+
results.set(repo.name, await analyzeRepo(repo.path, repo.name, llmProvider, log));
|
|
133
|
+
if (llmProvider && i < repos.length - 1)
|
|
134
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
135
|
+
}
|
|
136
|
+
return results;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=deep-repo-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deep-repo-analyzer.js","sourceRoot":"","sources":["../../../../../src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Sampler
|
|
3
|
+
*
|
|
4
|
+
* Intelligently selects representative files from a repo for LLM analysis.
|
|
5
|
+
* Prioritizes high-value files while respecting size limits.
|
|
6
|
+
*/
|
|
7
|
+
import type { FileSample } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Configuration for file sampling
|
|
10
|
+
*/
|
|
11
|
+
export interface SamplingConfig {
|
|
12
|
+
maxFiles: number;
|
|
13
|
+
maxLinesPerFile: number;
|
|
14
|
+
maxTotalChars: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Sample files from a repo for LLM analysis
|
|
18
|
+
*/
|
|
19
|
+
export declare function sampleRepoFiles(repoPath: string, config?: SamplingConfig): Promise<FileSample[]>;
|
|
20
|
+
/**
|
|
21
|
+
* Format samples for LLM prompt
|
|
22
|
+
*/
|
|
23
|
+
export declare function formatSamplesForPrompt(samples: FileSample[]): string;
|
|
24
|
+
//# sourceMappingURL=file-sampler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-sampler.d.ts","sourceRoot":"","sources":["../../../../../src/core/living-docs/intelligent-analyzer/file-sampler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;CACvB;AAqDD;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,cAA+B,GACtC,OAAO,CAAC,UAAU,EAAE,CAAC,CA4EvB;AAmED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CASpE"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Sampler
|
|
3
|
+
*
|
|
4
|
+
* Intelligently selects representative files from a repo for LLM analysis.
|
|
5
|
+
* Prioritizes high-value files while respecting size limits.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import { glob } from 'glob';
|
|
10
|
+
const DEFAULT_CONFIG = {
|
|
11
|
+
maxFiles: 20,
|
|
12
|
+
maxLinesPerFile: 500,
|
|
13
|
+
maxTotalChars: 100000, // ~100KB total
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Priority file patterns - checked in order
|
|
17
|
+
*/
|
|
18
|
+
const PRIORITY_PATTERNS = [
|
|
19
|
+
// Tier 1: Always include if exists
|
|
20
|
+
{ pattern: 'README.md', type: 'readme', priority: 1 },
|
|
21
|
+
{ pattern: 'readme.md', type: 'readme', priority: 1 },
|
|
22
|
+
{ pattern: 'package.json', type: 'config', priority: 1 },
|
|
23
|
+
{ pattern: 'tsconfig.json', type: 'config', priority: 1 },
|
|
24
|
+
{ pattern: 'pyproject.toml', type: 'config', priority: 1 },
|
|
25
|
+
{ pattern: 'go.mod', type: 'config', priority: 1 },
|
|
26
|
+
{ pattern: 'Cargo.toml', type: 'config', priority: 1 },
|
|
27
|
+
{ pattern: 'pom.xml', type: 'config', priority: 1 },
|
|
28
|
+
// Tier 2: Entry points
|
|
29
|
+
{ pattern: 'src/index.ts', type: 'entry', priority: 2 },
|
|
30
|
+
{ pattern: 'src/main.ts', type: 'entry', priority: 2 },
|
|
31
|
+
{ pattern: 'src/app.ts', type: 'entry', priority: 2 },
|
|
32
|
+
{ pattern: 'src/server.ts', type: 'entry', priority: 2 },
|
|
33
|
+
{ pattern: 'index.ts', type: 'entry', priority: 2 },
|
|
34
|
+
{ pattern: 'main.ts', type: 'entry', priority: 2 },
|
|
35
|
+
{ pattern: 'app.ts', type: 'entry', priority: 2 },
|
|
36
|
+
{ pattern: 'main.py', type: 'entry', priority: 2 },
|
|
37
|
+
{ pattern: 'app.py', type: 'entry', priority: 2 },
|
|
38
|
+
{ pattern: 'main.go', type: 'entry', priority: 2 },
|
|
39
|
+
{ pattern: 'cmd/main.go', type: 'entry', priority: 2 },
|
|
40
|
+
// Tier 3: API surfaces (glob patterns)
|
|
41
|
+
{ pattern: 'src/routes/**/*.ts', type: 'api', priority: 3 },
|
|
42
|
+
{ pattern: 'src/api/**/*.ts', type: 'api', priority: 3 },
|
|
43
|
+
{ pattern: 'src/controllers/**/*.ts', type: 'api', priority: 3 },
|
|
44
|
+
{ pattern: 'src/handlers/**/*.ts', type: 'api', priority: 3 },
|
|
45
|
+
{ pattern: 'routes/**/*.ts', type: 'api', priority: 3 },
|
|
46
|
+
{ pattern: 'api/**/*.ts', type: 'api', priority: 3 },
|
|
47
|
+
// Tier 4: Domain models
|
|
48
|
+
{ pattern: 'src/models/**/*.ts', type: 'model', priority: 4 },
|
|
49
|
+
{ pattern: 'src/types/**/*.ts', type: 'model', priority: 4 },
|
|
50
|
+
{ pattern: 'src/entities/**/*.ts', type: 'model', priority: 4 },
|
|
51
|
+
{ pattern: 'src/schemas/**/*.ts', type: 'model', priority: 4 },
|
|
52
|
+
{ pattern: 'src/domain/**/*.ts', type: 'model', priority: 4 },
|
|
53
|
+
{ pattern: 'models/**/*.ts', type: 'model', priority: 4 },
|
|
54
|
+
{ pattern: 'types/**/*.ts', type: 'model', priority: 4 },
|
|
55
|
+
];
|
|
56
|
+
/**
|
|
57
|
+
* Sample files from a repo for LLM analysis
|
|
58
|
+
*/
|
|
59
|
+
export async function sampleRepoFiles(repoPath, config = DEFAULT_CONFIG) {
|
|
60
|
+
const samples = [];
|
|
61
|
+
const includedPaths = new Set();
|
|
62
|
+
let totalChars = 0;
|
|
63
|
+
// Phase 1: Include priority files
|
|
64
|
+
for (const { pattern, type, priority } of PRIORITY_PATTERNS) {
|
|
65
|
+
if (samples.length >= config.maxFiles)
|
|
66
|
+
break;
|
|
67
|
+
if (totalChars >= config.maxTotalChars)
|
|
68
|
+
break;
|
|
69
|
+
try {
|
|
70
|
+
const matches = await glob(pattern, {
|
|
71
|
+
cwd: repoPath,
|
|
72
|
+
nodir: true,
|
|
73
|
+
ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**'],
|
|
74
|
+
});
|
|
75
|
+
for (const match of matches.slice(0, priority === 1 ? 5 : 2)) {
|
|
76
|
+
if (includedPaths.has(match))
|
|
77
|
+
continue;
|
|
78
|
+
if (samples.length >= config.maxFiles)
|
|
79
|
+
break;
|
|
80
|
+
const sample = await readFileSample(repoPath, match, type, config.maxLinesPerFile);
|
|
81
|
+
if (sample && totalChars + sample.content.length <= config.maxTotalChars) {
|
|
82
|
+
samples.push(sample);
|
|
83
|
+
includedPaths.add(match);
|
|
84
|
+
totalChars += sample.content.length;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Pattern didn't match, continue
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Phase 2: Fill remaining slots with other interesting files
|
|
93
|
+
if (samples.length < config.maxFiles && totalChars < config.maxTotalChars) {
|
|
94
|
+
try {
|
|
95
|
+
const allFiles = await glob('**/*.{ts,js,tsx,jsx,py,go,java,rs}', {
|
|
96
|
+
cwd: repoPath,
|
|
97
|
+
nodir: true,
|
|
98
|
+
ignore: [
|
|
99
|
+
'**/node_modules/**',
|
|
100
|
+
'**/dist/**',
|
|
101
|
+
'**/build/**',
|
|
102
|
+
'**/.git/**',
|
|
103
|
+
'**/*.test.*',
|
|
104
|
+
'**/*.spec.*',
|
|
105
|
+
'**/__tests__/**',
|
|
106
|
+
],
|
|
107
|
+
});
|
|
108
|
+
// Sort by likely importance (shorter paths, src/ prefix)
|
|
109
|
+
const sortedFiles = allFiles
|
|
110
|
+
.filter(f => !includedPaths.has(f))
|
|
111
|
+
.sort((a, b) => {
|
|
112
|
+
const aScore = getFileImportanceScore(a);
|
|
113
|
+
const bScore = getFileImportanceScore(b);
|
|
114
|
+
return bScore - aScore;
|
|
115
|
+
});
|
|
116
|
+
for (const file of sortedFiles) {
|
|
117
|
+
if (samples.length >= config.maxFiles)
|
|
118
|
+
break;
|
|
119
|
+
if (totalChars >= config.maxTotalChars)
|
|
120
|
+
break;
|
|
121
|
+
const sample = await readFileSample(repoPath, file, 'other', config.maxLinesPerFile);
|
|
122
|
+
if (sample && totalChars + sample.content.length <= config.maxTotalChars) {
|
|
123
|
+
samples.push(sample);
|
|
124
|
+
includedPaths.add(file);
|
|
125
|
+
totalChars += sample.content.length;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// Glob failed, continue with what we have
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return samples;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Read a file and create a sample
|
|
137
|
+
*/
|
|
138
|
+
async function readFileSample(repoPath, relativePath, type, maxLines) {
|
|
139
|
+
const fullPath = path.join(repoPath, relativePath);
|
|
140
|
+
try {
|
|
141
|
+
const stats = fs.statSync(fullPath);
|
|
142
|
+
if (stats.size > 500000)
|
|
143
|
+
return null; // Skip files > 500KB
|
|
144
|
+
let content = fs.readFileSync(fullPath, 'utf-8');
|
|
145
|
+
let truncated = false;
|
|
146
|
+
const lines = content.split('\n');
|
|
147
|
+
if (lines.length > maxLines) {
|
|
148
|
+
content = lines.slice(0, maxLines).join('\n');
|
|
149
|
+
content += `\n\n// ... truncated (${lines.length - maxLines} more lines)`;
|
|
150
|
+
truncated = true;
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
path: relativePath,
|
|
154
|
+
content,
|
|
155
|
+
type,
|
|
156
|
+
truncated,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Score file importance for sorting
|
|
165
|
+
*/
|
|
166
|
+
function getFileImportanceScore(filePath) {
|
|
167
|
+
let score = 0;
|
|
168
|
+
// Prefer shorter paths (closer to root)
|
|
169
|
+
score += Math.max(0, 10 - filePath.split('/').length);
|
|
170
|
+
// Prefer src/ files
|
|
171
|
+
if (filePath.startsWith('src/'))
|
|
172
|
+
score += 5;
|
|
173
|
+
// Prefer index files
|
|
174
|
+
if (filePath.includes('index.'))
|
|
175
|
+
score += 3;
|
|
176
|
+
// Prefer files with meaningful names
|
|
177
|
+
const name = path.basename(filePath, path.extname(filePath));
|
|
178
|
+
if (['app', 'main', 'server', 'client', 'api', 'service', 'controller'].includes(name)) {
|
|
179
|
+
score += 4;
|
|
180
|
+
}
|
|
181
|
+
// Deprioritize utility files
|
|
182
|
+
if (['utils', 'helpers', 'constants', 'config'].includes(name)) {
|
|
183
|
+
score -= 2;
|
|
184
|
+
}
|
|
185
|
+
return score;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Format samples for LLM prompt
|
|
189
|
+
*/
|
|
190
|
+
export function formatSamplesForPrompt(samples) {
|
|
191
|
+
const sections = [];
|
|
192
|
+
for (const sample of samples) {
|
|
193
|
+
const header = `=== ${sample.path} (${sample.type}) ===`;
|
|
194
|
+
sections.push(`${header}\n${sample.content}`);
|
|
195
|
+
}
|
|
196
|
+
return sections.join('\n\n');
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=file-sampler.js.map
|