Implement all stubs: parsePackageMap, LLM heuristics, tree-sitter AST, patch rewrite, reinit

- format.ts: Full parsePackageMap implementation with round-trip support
- llm-extract.ts: Heuristic-based extraction without LLM API (regex exports,
  imports, purpose inference from filename patterns)
- ast-extract.ts: Tree-sitter integration for TypeScript/TSX with fallback
  for other languages
- init.ts: Refactored to expose generateDirectoryMap helper, reinitPath
  delegates to initProject
- patch.ts: Small packages now use generateDirectoryMap for full rewrite
- discover.ts: Cleaned up require('fs') to use proper ES import
- Tests: 8 tests covering format round-trip and LLM heuristics
- All TypeScript compiles clean, all tests pass
This commit is contained in:
2026-06-09 18:04:57 +02:00
parent fd958671ca
commit d311c8fb3c
14 changed files with 1032 additions and 305 deletions
+37 -31
View File
@@ -1,42 +1,48 @@
import { discoverProject } from './discover.js';
import { renderPackageMap, type PackageMapData } from './format.js';
import { extractFileLLM } from './llm-extract.js';
import { extractFileAST } from './ast-extract.js';
import { mergeFileData } from './merge.js';
import { extractPackageLLM } from './llm-extract.js';
import { writeFileSync } from 'fs';
import { join } from 'path';
import { discoverProject, type DirectoryEntry } from "./discover.js";
import { renderPackageMap, type PackageMapData, type FileEntry } from "./format.js";
import { extractFileLLM, extractPackageLLM } from "./llm-extract.js";
import { extractFileAST } from "./ast-extract.js";
import { mergeFileData } from "./merge.js";
import { writeFileSync } from "fs";
import { join } from "path";
export async function initProject(rootPath: string): Promise<void> {
const entries = discoverProject(rootPath);
const entries = discoverProject(rootPath);
for (const entry of entries) {
const fileData = [];
for (const file of entry.files) {
const filePath = join(entry.dirPath, file);
const llmData = await extractFileLLM(filePath);
const astData = await extractFileAST(filePath);
fileData.push(mergeFileData(file, llmData, astData));
}
for (const entry of entries) {
await generateDirectoryMap(entry);
}
const packageData = await extractPackageLLM(entry.relativePath, fileData);
console.log(`Generated ${entries.length} .pi-map.md files`);
}
const mapData: PackageMapData = {
path: entry.relativePath,
role: packageData.role,
files: fileData,
arch: packageData.arch,
dirty: '-'
};
export async function generateDirectoryMap(
entry: DirectoryEntry,
): Promise<FileEntry[]> {
const fileData: FileEntry[] = [];
for (const file of entry.files) {
const filePath = join(entry.dirPath, file);
const llmData = await extractFileLLM(filePath);
const astData = await extractFileAST(filePath);
fileData.push(mergeFileData(file, llmData, astData));
}
const outPath = join(entry.dirPath, '.pi-map.md');
writeFileSync(outPath, renderPackageMap(mapData));
}
const packageData = await extractPackageLLM(entry.relativePath, fileData);
console.log(`Generated ${entries.length} .pi-map.md files`);
const mapData: PackageMapData = {
path: entry.relativePath,
role: packageData.role,
files: fileData,
arch: packageData.arch,
dirty: "-",
};
const outPath = join(entry.dirPath, ".pi-map.md");
writeFileSync(outPath, renderPackageMap(mapData));
return fileData;
}
export async function reinitPath(path: string): Promise<void> {
// TODO: clear dirty markers and force regeneration
await initProject(path);
// Full regeneration clears all dirty markers by overwriting every .pi-map.md
await initProject(path);
}