opencode-autognosis 1.0.1 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +346 -76
- package/dist/activeset.d.ts +3 -0
- package/dist/activeset.js +498 -0
- package/dist/chunk-cards.d.ts +29 -0
- package/dist/chunk-cards.js +982 -0
- package/dist/git-worktree.d.ts +3 -0
- package/dist/git-worktree.js +384 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +16 -3
- package/dist/module-summaries.d.ts +3 -0
- package/dist/module-summaries.js +510 -0
- package/dist/performance-optimization.d.ts +3 -0
- package/dist/performance-optimization.js +748 -0
- package/dist/testing-infrastructure.d.ts +3 -0
- package/dist/testing-infrastructure.js +603 -0
- package/package.json +27 -3
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin";
|
|
2
|
+
import * as fs from "node:fs/promises";
|
|
3
|
+
import * as fsSync from "node:fs";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import * as crypto from "node:crypto";
|
|
6
|
+
const PROJECT_ROOT = process.cwd();
|
|
7
|
+
const OPENCODE_DIR = path.join(PROJECT_ROOT, ".opencode");
|
|
8
|
+
const CHUNK_DIR = path.join(OPENCODE_DIR, "chunks");
|
|
9
|
+
const MODULE_DIR = path.join(OPENCODE_DIR, "modules");
|
|
10
|
+
// Internal logging
|
|
11
|
+
function log(message, data) {
|
|
12
|
+
console.error(`[ModuleSummaries] ${message}`, data || '');
|
|
13
|
+
}
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// HELPERS
|
|
16
|
+
// =============================================================================
|
|
17
|
+
async function ensureModuleDir() {
|
|
18
|
+
await fs.mkdir(MODULE_DIR, { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
async function loadChunkCard(cardId) {
|
|
21
|
+
try {
|
|
22
|
+
const cardPath = path.join(CHUNK_DIR, `${cardId}.json`);
|
|
23
|
+
if (!fsSync.existsSync(cardPath)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const content = await fs.readFile(cardPath, 'utf-8');
|
|
27
|
+
return JSON.parse(content);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function findChunkCardsForFile(filePath) {
|
|
34
|
+
const cards = [];
|
|
35
|
+
try {
|
|
36
|
+
const files = await fs.readdir(CHUNK_DIR);
|
|
37
|
+
for (const file of files) {
|
|
38
|
+
if (file.endsWith('.json')) {
|
|
39
|
+
try {
|
|
40
|
+
const cardPath = path.join(CHUNK_DIR, file);
|
|
41
|
+
const card = JSON.parse(await fs.readFile(cardPath, 'utf-8'));
|
|
42
|
+
if (card.file_path === filePath) {
|
|
43
|
+
cards.push(card);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
// Skip corrupted files
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
// Return empty list if directory doesn't exist
|
|
55
|
+
}
|
|
56
|
+
return cards;
|
|
57
|
+
}
|
|
58
|
+
function generateModuleId(filePath) {
|
|
59
|
+
const relativePath = path.relative(PROJECT_ROOT, filePath);
|
|
60
|
+
const hash = crypto.createHash('md5').update(relativePath).digest('hex').slice(0, 8);
|
|
61
|
+
return `module-${relativePath.replace(/[^a-zA-Z0-9]/g, '-')}-${hash}`;
|
|
62
|
+
}
|
|
63
|
+
function calculateModuleMetrics(chunkCards) {
|
|
64
|
+
const totalChunks = chunkCards.length;
|
|
65
|
+
const complexityScore = chunkCards.reduce((sum, card) => sum + card.metadata.complexity_score, 0) / totalChunks;
|
|
66
|
+
const apiSurface = chunkCards.filter(card => card.chunk_type === 'api').length;
|
|
67
|
+
return {
|
|
68
|
+
total_chunks: totalChunks,
|
|
69
|
+
complexity_score: Math.round(complexityScore * 100) / 100,
|
|
70
|
+
api_surface: apiSurface
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function extractRelationships(chunkCards) {
|
|
74
|
+
const allDependencies = new Set();
|
|
75
|
+
const allExports = new Set();
|
|
76
|
+
const allSymbols = new Set();
|
|
77
|
+
chunkCards.forEach(card => {
|
|
78
|
+
card.metadata.dependencies.forEach(dep => allDependencies.add(dep));
|
|
79
|
+
card.metadata.symbols.forEach(symbol => allSymbols.add(symbol));
|
|
80
|
+
// Extract exports from API chunks
|
|
81
|
+
if (card.chunk_type === 'api') {
|
|
82
|
+
const exports = extractExportsFromContent(card.content);
|
|
83
|
+
exports.forEach(exp => allExports.add(exp));
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return {
|
|
87
|
+
imports: Array.from(allDependencies),
|
|
88
|
+
exports: Array.from(allExports),
|
|
89
|
+
dependents: [] // Would need cross-module analysis to populate
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function extractExportsFromContent(content) {
|
|
93
|
+
const exports = [];
|
|
94
|
+
// Match export statements
|
|
95
|
+
const exportMatches = content.match(/export\s+(?:const|let|var|function|class|interface|type)\s+(\w+)/g);
|
|
96
|
+
if (exportMatches) {
|
|
97
|
+
exports.push(...exportMatches.map(match => match.split(/\s+/)[2]));
|
|
98
|
+
}
|
|
99
|
+
return exports;
|
|
100
|
+
}
|
|
101
|
+
function synthesizeHierarchy(chunkCards) {
|
|
102
|
+
const summaryCard = chunkCards.find(card => card.chunk_type === 'summary');
|
|
103
|
+
const apiCard = chunkCards.find(card => card.chunk_type === 'api');
|
|
104
|
+
const invariantCard = chunkCards.find(card => card.chunk_type === 'invariant');
|
|
105
|
+
return {
|
|
106
|
+
summary_level: summaryCard?.content || "No summary available",
|
|
107
|
+
signature_level: apiCard?.content || "No API documentation available",
|
|
108
|
+
implementation_level: invariantCard?.content || "No invariant analysis available"
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
// =============================================================================
|
|
112
|
+
// MODULE SUMMARIES TOOLS
|
|
113
|
+
// =============================================================================
|
|
114
|
+
export function moduleSummariesTools() {
|
|
115
|
+
return {
|
|
116
|
+
module_synthesize: tool({
|
|
117
|
+
description: "Synthesize a Module Summary from existing Chunk Cards. Creates hierarchical understanding of the module.",
|
|
118
|
+
args: {
|
|
119
|
+
file_path: tool.schema.string().describe("File path to synthesize module summary for"),
|
|
120
|
+
force_resynthesize: tool.schema.boolean().optional().default(false).describe("Force re-synthesis even if summary exists"),
|
|
121
|
+
include_reasoning: tool.schema.boolean().optional().default(true).describe("Include hierarchical reasoning analysis")
|
|
122
|
+
},
|
|
123
|
+
async execute({ file_path, force_resynthesize, include_reasoning }) {
|
|
124
|
+
log("Tool call: module_synthesize", { file_path, force_resynthesize, include_reasoning });
|
|
125
|
+
try {
|
|
126
|
+
await ensureModuleDir();
|
|
127
|
+
// Validate file exists
|
|
128
|
+
if (!fsSync.existsSync(file_path)) {
|
|
129
|
+
return JSON.stringify({
|
|
130
|
+
status: "ERROR",
|
|
131
|
+
message: `File not found: ${file_path}`
|
|
132
|
+
}, null, 2);
|
|
133
|
+
}
|
|
134
|
+
const moduleId = generateModuleId(file_path);
|
|
135
|
+
const modulePath = path.join(MODULE_DIR, `${moduleId}.json`);
|
|
136
|
+
// Check if module summary already exists
|
|
137
|
+
if (!force_resynthesize && fsSync.existsSync(modulePath)) {
|
|
138
|
+
const existingModule = JSON.parse(await fs.readFile(modulePath, 'utf-8'));
|
|
139
|
+
return JSON.stringify({
|
|
140
|
+
status: "EXISTS",
|
|
141
|
+
module_summary: existingModule,
|
|
142
|
+
message: "Module summary already exists. Use force_resynthesize=true to override."
|
|
143
|
+
}, null, 2);
|
|
144
|
+
}
|
|
145
|
+
// Find chunk cards for this file
|
|
146
|
+
const chunkCards = await findChunkCardsForFile(file_path);
|
|
147
|
+
if (chunkCards.length === 0) {
|
|
148
|
+
return JSON.stringify({
|
|
149
|
+
status: "NO_CHUNKS",
|
|
150
|
+
message: `No chunk cards found for file: ${file_path}. Create chunk cards first.`,
|
|
151
|
+
file_path,
|
|
152
|
+
module_id: moduleId
|
|
153
|
+
}, null, 2);
|
|
154
|
+
}
|
|
155
|
+
// Create module summary
|
|
156
|
+
const moduleSummary = {
|
|
157
|
+
module_id: moduleId,
|
|
158
|
+
file_path,
|
|
159
|
+
chunk_cards: chunkCards,
|
|
160
|
+
hierarchy: synthesizeHierarchy(chunkCards),
|
|
161
|
+
relationships: extractRelationships(chunkCards),
|
|
162
|
+
metrics: calculateModuleMetrics(chunkCards),
|
|
163
|
+
synthesis_metadata: {
|
|
164
|
+
created_at: new Date().toISOString(),
|
|
165
|
+
updated_at: new Date().toISOString(),
|
|
166
|
+
version: "1.0.0",
|
|
167
|
+
synthesis_method: "chunk_card_synthesis"
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
// Save module summary
|
|
171
|
+
await fs.writeFile(modulePath, JSON.stringify(moduleSummary, null, 2));
|
|
172
|
+
const response = {
|
|
173
|
+
status: "SUCCESS",
|
|
174
|
+
module_summary: moduleSummary,
|
|
175
|
+
saved_to: modulePath
|
|
176
|
+
};
|
|
177
|
+
// Include hierarchical reasoning if requested
|
|
178
|
+
if (include_reasoning) {
|
|
179
|
+
response.reasoning = await generateHierarchicalReasoning(moduleSummary);
|
|
180
|
+
}
|
|
181
|
+
return JSON.stringify(response, null, 2);
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
return JSON.stringify({
|
|
185
|
+
status: "ERROR",
|
|
186
|
+
message: error instanceof Error ? error.message : `${error}`
|
|
187
|
+
}, null, 2);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}),
|
|
191
|
+
module_get_summary: tool({
|
|
192
|
+
description: "Retrieve a Module Summary by file path or module ID.",
|
|
193
|
+
args: {
|
|
194
|
+
file_path: tool.schema.string().optional().describe("File path to get summary for"),
|
|
195
|
+
module_id: tool.schema.string().optional().describe("Module ID to retrieve"),
|
|
196
|
+
include_reasoning: tool.schema.boolean().optional().default(false).describe("Include hierarchical reasoning")
|
|
197
|
+
},
|
|
198
|
+
async execute({ file_path, module_id, include_reasoning }) {
|
|
199
|
+
log("Tool call: module_get_summary", { file_path, module_id, include_reasoning });
|
|
200
|
+
try {
|
|
201
|
+
let targetModuleId = module_id;
|
|
202
|
+
if (file_path && !module_id) {
|
|
203
|
+
targetModuleId = generateModuleId(file_path);
|
|
204
|
+
}
|
|
205
|
+
if (!targetModuleId) {
|
|
206
|
+
return JSON.stringify({
|
|
207
|
+
status: "ERROR",
|
|
208
|
+
message: "Either file_path or module_id must be provided"
|
|
209
|
+
}, null, 2);
|
|
210
|
+
}
|
|
211
|
+
const modulePath = path.join(MODULE_DIR, `${targetModuleId}.json`);
|
|
212
|
+
if (!fsSync.existsSync(modulePath)) {
|
|
213
|
+
return JSON.stringify({
|
|
214
|
+
status: "NOT_FOUND",
|
|
215
|
+
message: `Module summary not found: ${targetModuleId}`,
|
|
216
|
+
module_id: targetModuleId
|
|
217
|
+
}, null, 2);
|
|
218
|
+
}
|
|
219
|
+
const moduleSummary = JSON.parse(await fs.readFile(modulePath, 'utf-8'));
|
|
220
|
+
const response = {
|
|
221
|
+
status: "SUCCESS",
|
|
222
|
+
module_summary: moduleSummary
|
|
223
|
+
};
|
|
224
|
+
// Include hierarchical reasoning if requested
|
|
225
|
+
if (include_reasoning) {
|
|
226
|
+
response.reasoning = await generateHierarchicalReasoning(moduleSummary);
|
|
227
|
+
}
|
|
228
|
+
return JSON.stringify(response, null, 2);
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
return JSON.stringify({
|
|
232
|
+
status: "ERROR",
|
|
233
|
+
message: error instanceof Error ? error.message : `${error}`
|
|
234
|
+
}, null, 2);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}),
|
|
238
|
+
module_list_summaries: tool({
|
|
239
|
+
description: "List all available Module Summaries with optional filtering.",
|
|
240
|
+
args: {
|
|
241
|
+
file_pattern: tool.schema.string().optional().describe("Filter by file path pattern (regex)"),
|
|
242
|
+
limit: tool.schema.number().optional().default(20).describe("Maximum number of summaries to return"),
|
|
243
|
+
include_metrics: tool.schema.boolean().optional().default(true).describe("Include module metrics")
|
|
244
|
+
},
|
|
245
|
+
async execute({ file_pattern, limit, include_metrics }) {
|
|
246
|
+
log("Tool call: module_list_summaries", { file_pattern, limit, include_metrics });
|
|
247
|
+
try {
|
|
248
|
+
await ensureModuleDir();
|
|
249
|
+
const files = await fs.readdir(MODULE_DIR);
|
|
250
|
+
const summaries = [];
|
|
251
|
+
for (const file of files) {
|
|
252
|
+
if (file.endsWith('.json')) {
|
|
253
|
+
try {
|
|
254
|
+
const modulePath = path.join(MODULE_DIR, file);
|
|
255
|
+
const summary = JSON.parse(await fs.readFile(modulePath, 'utf-8'));
|
|
256
|
+
// Apply file pattern filter if specified
|
|
257
|
+
if (file_pattern && !new RegExp(file_pattern).test(summary.file_path)) {
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
const summaryInfo = {
|
|
261
|
+
module_id: summary.module_id,
|
|
262
|
+
file_path: summary.file_path,
|
|
263
|
+
created_at: summary.synthesis_metadata.created_at,
|
|
264
|
+
updated_at: summary.synthesis_metadata.updated_at,
|
|
265
|
+
chunk_count: summary.chunk_cards.length
|
|
266
|
+
};
|
|
267
|
+
if (include_metrics) {
|
|
268
|
+
Object.assign(summaryInfo, summary.metrics);
|
|
269
|
+
}
|
|
270
|
+
summaries.push(summaryInfo);
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
// Skip corrupted files
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
// Sort by updated date (most recent first)
|
|
279
|
+
summaries.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime());
|
|
280
|
+
// Apply limit
|
|
281
|
+
const limitedSummaries = summaries.slice(0, limit);
|
|
282
|
+
return JSON.stringify({
|
|
283
|
+
status: "SUCCESS",
|
|
284
|
+
summaries: limitedSummaries,
|
|
285
|
+
total_count: summaries.length,
|
|
286
|
+
returned_count: limitedSummaries.length,
|
|
287
|
+
filters: {
|
|
288
|
+
file_pattern,
|
|
289
|
+
limit
|
|
290
|
+
}
|
|
291
|
+
}, null, 2);
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
return JSON.stringify({
|
|
295
|
+
status: "ERROR",
|
|
296
|
+
message: error instanceof Error ? error.message : `${error}`
|
|
297
|
+
}, null, 2);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}),
|
|
301
|
+
module_hierarchical_reasoning: tool({
|
|
302
|
+
description: "Generate detailed hierarchical reasoning for a module across summary, signature, and implementation levels.",
|
|
303
|
+
args: {
|
|
304
|
+
module_id: tool.schema.string().describe("Module ID to analyze"),
|
|
305
|
+
reasoning_depth: tool.schema.enum(["shallow", "medium", "deep"]).optional().default("medium").describe("Depth of reasoning analysis")
|
|
306
|
+
},
|
|
307
|
+
async execute({ module_id, reasoning_depth }) {
|
|
308
|
+
log("Tool call: module_hierarchical_reasoning", { module_id, reasoning_depth });
|
|
309
|
+
try {
|
|
310
|
+
const modulePath = path.join(MODULE_DIR, `${module_id}.json`);
|
|
311
|
+
if (!fsSync.existsSync(modulePath)) {
|
|
312
|
+
return JSON.stringify({
|
|
313
|
+
status: "NOT_FOUND",
|
|
314
|
+
message: `Module summary not found: ${module_id}`
|
|
315
|
+
}, null, 2);
|
|
316
|
+
}
|
|
317
|
+
const moduleSummary = JSON.parse(await fs.readFile(modulePath, 'utf-8'));
|
|
318
|
+
const reasoning = await generateHierarchicalReasoning(moduleSummary, reasoning_depth);
|
|
319
|
+
return JSON.stringify({
|
|
320
|
+
status: "SUCCESS",
|
|
321
|
+
module_id,
|
|
322
|
+
reasoning_depth,
|
|
323
|
+
reasoning,
|
|
324
|
+
generated_at: new Date().toISOString()
|
|
325
|
+
}, null, 2);
|
|
326
|
+
}
|
|
327
|
+
catch (error) {
|
|
328
|
+
return JSON.stringify({
|
|
329
|
+
status: "ERROR",
|
|
330
|
+
message: error instanceof Error ? error.message : `${error}`
|
|
331
|
+
}, null, 2);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}),
|
|
335
|
+
module_cross_reference: tool({
|
|
336
|
+
description: "Find cross-references and relationships between modules.",
|
|
337
|
+
args: {
|
|
338
|
+
module_id: tool.schema.string().describe("Module ID to analyze"),
|
|
339
|
+
reference_depth: tool.schema.number().optional().default(2).describe("How many levels of references to follow"),
|
|
340
|
+
include_symbols: tool.schema.boolean().optional().default(true).describe("Include shared symbol analysis")
|
|
341
|
+
},
|
|
342
|
+
async execute({ module_id, reference_depth, include_symbols }) {
|
|
343
|
+
log("Tool call: module_cross_reference", { module_id, reference_depth, include_symbols });
|
|
344
|
+
try {
|
|
345
|
+
const modulePath = path.join(MODULE_DIR, `${module_id}.json`);
|
|
346
|
+
if (!fsSync.existsSync(modulePath)) {
|
|
347
|
+
return JSON.stringify({
|
|
348
|
+
status: "NOT_FOUND",
|
|
349
|
+
message: `Module summary not found: ${module_id}`
|
|
350
|
+
}, null, 2);
|
|
351
|
+
}
|
|
352
|
+
const moduleSummary = JSON.parse(await fs.readFile(modulePath, 'utf-8'));
|
|
353
|
+
const crossReferences = await generateCrossReferences(moduleSummary, reference_depth, include_symbols);
|
|
354
|
+
return JSON.stringify({
|
|
355
|
+
status: "SUCCESS",
|
|
356
|
+
module_id,
|
|
357
|
+
reference_depth,
|
|
358
|
+
cross_references: crossReferences,
|
|
359
|
+
generated_at: new Date().toISOString()
|
|
360
|
+
}, null, 2);
|
|
361
|
+
}
|
|
362
|
+
catch (error) {
|
|
363
|
+
return JSON.stringify({
|
|
364
|
+
status: "ERROR",
|
|
365
|
+
message: error instanceof Error ? error.message : `${error}`
|
|
366
|
+
}, null, 2);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}),
|
|
370
|
+
module_delete_summary: tool({
|
|
371
|
+
description: "Delete a Module Summary.",
|
|
372
|
+
args: {
|
|
373
|
+
module_id: tool.schema.string().describe("Module ID to delete")
|
|
374
|
+
},
|
|
375
|
+
async execute({ module_id }) {
|
|
376
|
+
log("Tool call: module_delete_summary", { module_id });
|
|
377
|
+
try {
|
|
378
|
+
const modulePath = path.join(MODULE_DIR, `${module_id}.json`);
|
|
379
|
+
if (!fsSync.existsSync(modulePath)) {
|
|
380
|
+
return JSON.stringify({
|
|
381
|
+
status: "NOT_FOUND",
|
|
382
|
+
message: `Module summary not found: ${module_id}`
|
|
383
|
+
}, null, 2);
|
|
384
|
+
}
|
|
385
|
+
await fs.unlink(modulePath);
|
|
386
|
+
return JSON.stringify({
|
|
387
|
+
status: "SUCCESS",
|
|
388
|
+
message: `Module summary deleted: ${module_id}`
|
|
389
|
+
}, null, 2);
|
|
390
|
+
}
|
|
391
|
+
catch (error) {
|
|
392
|
+
return JSON.stringify({
|
|
393
|
+
status: "ERROR",
|
|
394
|
+
message: error instanceof Error ? error.message : `${error}`
|
|
395
|
+
}, null, 2);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
})
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
// =============================================================================
|
|
402
|
+
// HIERARCHICAL REASONING GENERATION
|
|
403
|
+
// =============================================================================
|
|
404
|
+
async function generateHierarchicalReasoning(moduleSummary, depth = "medium") {
|
|
405
|
+
const chunkCards = moduleSummary.chunk_cards;
|
|
406
|
+
const summaryCard = chunkCards.find(card => card.chunk_type === 'summary');
|
|
407
|
+
const apiCard = chunkCards.find(card => card.chunk_type === 'api');
|
|
408
|
+
const invariantCard = chunkCards.find(card => card.chunk_type === 'invariant');
|
|
409
|
+
const reasoning = {
|
|
410
|
+
module_id: moduleSummary.module_id,
|
|
411
|
+
reasoning_levels: {
|
|
412
|
+
summary: {
|
|
413
|
+
purpose: extractPurposeFromSummary(summaryCard?.content || ""),
|
|
414
|
+
key_concepts: extractKeyConcepts(summaryCard?.content || ""),
|
|
415
|
+
high_level_structure: extractHighLevelStructure(summaryCard?.content || "")
|
|
416
|
+
},
|
|
417
|
+
signature: {
|
|
418
|
+
public_api: extractPublicApi(apiCard?.content || ""),
|
|
419
|
+
interfaces: extractInterfaces(apiCard?.content || ""),
|
|
420
|
+
contracts: extractContracts(apiCard?.content || "")
|
|
421
|
+
},
|
|
422
|
+
implementation: {
|
|
423
|
+
internal_structure: extractInternalStructure(invariantCard?.content || ""),
|
|
424
|
+
algorithms: extractAlgorithms(invariantCard?.content || ""),
|
|
425
|
+
data_flow: extractDataFlow(invariantCard?.content || "")
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
cross_references: {
|
|
429
|
+
related_modules: await findRelatedModules(moduleSummary),
|
|
430
|
+
shared_symbols: moduleSummary.relationships.exports,
|
|
431
|
+
dependency_graph: generateDependencyGraph(moduleSummary)
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
return reasoning;
|
|
435
|
+
}
|
|
436
|
+
async function generateCrossReferences(moduleSummary, depth, includeSymbols) {
|
|
437
|
+
// This would analyze other modules to find relationships
|
|
438
|
+
// For now, return a placeholder implementation
|
|
439
|
+
return {
|
|
440
|
+
direct_dependencies: moduleSummary.relationships.imports,
|
|
441
|
+
dependents: moduleSummary.relationships.dependents,
|
|
442
|
+
shared_symbols: includeSymbols ? moduleSummary.relationships.exports : [],
|
|
443
|
+
related_modules: [],
|
|
444
|
+
analysis_depth: depth
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
// =============================================================================
|
|
448
|
+
// REASONING EXTRACTION HELPERS
|
|
449
|
+
// =============================================================================
|
|
450
|
+
function extractPurposeFromSummary(summaryContent) {
|
|
451
|
+
const purposeMatch = summaryContent.match(/## Purpose\s*\n\s*(.+?)(?=\n\n|\n#|$)/s);
|
|
452
|
+
return purposeMatch ? purposeMatch[1].trim() : "Purpose not explicitly documented";
|
|
453
|
+
}
|
|
454
|
+
function extractKeyConcepts(summaryContent) {
|
|
455
|
+
const concepts = [];
|
|
456
|
+
// Extract from Key Components section
|
|
457
|
+
const componentsMatch = summaryContent.match(/## Key Components\s*\n(.+?)(?=\n\n|\n#|$)/s);
|
|
458
|
+
if (componentsMatch) {
|
|
459
|
+
const lines = componentsMatch[1].split('\n');
|
|
460
|
+
lines.forEach(line => {
|
|
461
|
+
const match = line.match(/-\s*\*\*([^*]+)\*\*:\s*(.+)/);
|
|
462
|
+
if (match) {
|
|
463
|
+
concepts.push(match[1]);
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
return concepts;
|
|
468
|
+
}
|
|
469
|
+
function extractHighLevelStructure(summaryContent) {
|
|
470
|
+
// Extract structural information from summary
|
|
471
|
+
return "High-level structure analysis not implemented";
|
|
472
|
+
}
|
|
473
|
+
function extractPublicApi(apiContent) {
|
|
474
|
+
const apis = [];
|
|
475
|
+
// Extract public functions
|
|
476
|
+
const functionMatches = apiContent.match(/###\s+(\w+)\s*\n/g);
|
|
477
|
+
if (functionMatches) {
|
|
478
|
+
apis.push(...functionMatches.map(match => match.replace(/###\s+/, '').trim()));
|
|
479
|
+
}
|
|
480
|
+
return apis;
|
|
481
|
+
}
|
|
482
|
+
function extractInterfaces(apiContent) {
|
|
483
|
+
const interfaces = [];
|
|
484
|
+
// Extract interfaces
|
|
485
|
+
const interfaceMatches = apiContent.match(/###\s+(\w+)\s*\n/g);
|
|
486
|
+
if (interfaceMatches) {
|
|
487
|
+
interfaces.push(...interfaceMatches.map(match => match.replace(/###\s+/, '').trim()));
|
|
488
|
+
}
|
|
489
|
+
return interfaces;
|
|
490
|
+
}
|
|
491
|
+
function extractContracts(apiContent) {
|
|
492
|
+
// Extract contracts/invariants
|
|
493
|
+
return [];
|
|
494
|
+
}
|
|
495
|
+
function extractInternalStructure(invariantContent) {
|
|
496
|
+
return "Internal structure analysis not implemented";
|
|
497
|
+
}
|
|
498
|
+
function extractAlgorithms(invariantContent) {
|
|
499
|
+
return [];
|
|
500
|
+
}
|
|
501
|
+
function extractDataFlow(invariantContent) {
|
|
502
|
+
return "Data flow analysis not implemented";
|
|
503
|
+
}
|
|
504
|
+
async function findRelatedModules(moduleSummary) {
|
|
505
|
+
// This would search for other modules that reference this module
|
|
506
|
+
return [];
|
|
507
|
+
}
|
|
508
|
+
function generateDependencyGraph(moduleSummary) {
|
|
509
|
+
return `Dependency graph for ${moduleSummary.module_id} not implemented`;
|
|
510
|
+
}
|