autodocs-engine 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +185 -0
- package/dist/analysis-builder.d.ts +13 -0
- package/dist/analysis-builder.js +268 -0
- package/dist/analysis-builder.js.map +1 -0
- package/dist/anti-pattern-detector.d.ts +9 -0
- package/dist/anti-pattern-detector.js +58 -0
- package/dist/anti-pattern-detector.js.map +1 -0
- package/dist/architecture-detector.d.ts +7 -0
- package/dist/architecture-detector.js +212 -0
- package/dist/architecture-detector.js.map +1 -0
- package/dist/ast-parser.d.ts +5 -0
- package/dist/ast-parser.js +635 -0
- package/dist/ast-parser.js.map +1 -0
- package/dist/benchmark/code-generator.d.ts +20 -0
- package/dist/benchmark/code-generator.js +206 -0
- package/dist/benchmark/code-generator.js.map +1 -0
- package/dist/benchmark/pr-miner.d.ts +61 -0
- package/dist/benchmark/pr-miner.js +304 -0
- package/dist/benchmark/pr-miner.js.map +1 -0
- package/dist/benchmark/pr-runner.d.ts +58 -0
- package/dist/benchmark/pr-runner.js +346 -0
- package/dist/benchmark/pr-runner.js.map +1 -0
- package/dist/benchmark/pr-scorer.d.ts +48 -0
- package/dist/benchmark/pr-scorer.js +222 -0
- package/dist/benchmark/pr-scorer.js.map +1 -0
- package/dist/benchmark/pr-task-gen.d.ts +16 -0
- package/dist/benchmark/pr-task-gen.js +129 -0
- package/dist/benchmark/pr-task-gen.js.map +1 -0
- package/dist/benchmark/report.d.ts +9 -0
- package/dist/benchmark/report.js +131 -0
- package/dist/benchmark/report.js.map +1 -0
- package/dist/benchmark/runner.d.ts +6 -0
- package/dist/benchmark/runner.js +183 -0
- package/dist/benchmark/runner.js.map +1 -0
- package/dist/benchmark/scorer.d.ts +6 -0
- package/dist/benchmark/scorer.js +549 -0
- package/dist/benchmark/scorer.js.map +1 -0
- package/dist/benchmark/shuffler.d.ts +5 -0
- package/dist/benchmark/shuffler.js +70 -0
- package/dist/benchmark/shuffler.js.map +1 -0
- package/dist/benchmark/statistics.d.ts +36 -0
- package/dist/benchmark/statistics.js +159 -0
- package/dist/benchmark/statistics.js.map +1 -0
- package/dist/benchmark/task-generator.d.ts +20 -0
- package/dist/benchmark/task-generator.js +388 -0
- package/dist/benchmark/task-generator.js.map +1 -0
- package/dist/benchmark/types.d.ts +111 -0
- package/dist/benchmark/types.js +3 -0
- package/dist/benchmark/types.js.map +1 -0
- package/dist/bin/autodocs-engine.d.ts +2 -0
- package/dist/bin/autodocs-engine.js +296 -0
- package/dist/bin/autodocs-engine.js.map +1 -0
- package/dist/bin/benchmark.d.ts +14 -0
- package/dist/bin/benchmark.js +172 -0
- package/dist/bin/benchmark.js.map +1 -0
- package/dist/bin/check.d.ts +13 -0
- package/dist/bin/check.js +79 -0
- package/dist/bin/check.js.map +1 -0
- package/dist/bin/init.d.ts +11 -0
- package/dist/bin/init.js +268 -0
- package/dist/bin/init.js.map +1 -0
- package/dist/bin/serve.d.ts +4 -0
- package/dist/bin/serve.js +29 -0
- package/dist/bin/serve.js.map +1 -0
- package/dist/budget-validator.d.ts +22 -0
- package/dist/budget-validator.js +119 -0
- package/dist/budget-validator.js.map +1 -0
- package/dist/command-extractor.d.ts +10 -0
- package/dist/command-extractor.js +276 -0
- package/dist/command-extractor.js.map +1 -0
- package/dist/config-analyzer.d.ts +5 -0
- package/dist/config-analyzer.js +364 -0
- package/dist/config-analyzer.js.map +1 -0
- package/dist/config.d.ts +33 -0
- package/dist/config.js +172 -0
- package/dist/config.js.map +1 -0
- package/dist/contribution-patterns.d.ts +6 -0
- package/dist/contribution-patterns.js +263 -0
- package/dist/contribution-patterns.js.map +1 -0
- package/dist/convention-extractor.d.ts +17 -0
- package/dist/convention-extractor.js +90 -0
- package/dist/convention-extractor.js.map +1 -0
- package/dist/cross-package.d.ts +5 -0
- package/dist/cross-package.js +71 -0
- package/dist/cross-package.js.map +1 -0
- package/dist/dependency-analyzer.d.ts +5 -0
- package/dist/dependency-analyzer.js +233 -0
- package/dist/dependency-analyzer.js.map +1 -0
- package/dist/detectors/build-tool.d.ts +2 -0
- package/dist/detectors/build-tool.js +67 -0
- package/dist/detectors/build-tool.js.map +1 -0
- package/dist/detectors/component-patterns.d.ts +2 -0
- package/dist/detectors/component-patterns.js +49 -0
- package/dist/detectors/component-patterns.js.map +1 -0
- package/dist/detectors/data-fetching.d.ts +2 -0
- package/dist/detectors/data-fetching.js +127 -0
- package/dist/detectors/data-fetching.js.map +1 -0
- package/dist/detectors/database.d.ts +2 -0
- package/dist/detectors/database.js +54 -0
- package/dist/detectors/database.js.map +1 -0
- package/dist/detectors/error-handling.d.ts +2 -0
- package/dist/detectors/error-handling.js +47 -0
- package/dist/detectors/error-handling.js.map +1 -0
- package/dist/detectors/export-patterns.d.ts +2 -0
- package/dist/detectors/export-patterns.js +64 -0
- package/dist/detectors/export-patterns.js.map +1 -0
- package/dist/detectors/file-naming.d.ts +2 -0
- package/dist/detectors/file-naming.js +74 -0
- package/dist/detectors/file-naming.js.map +1 -0
- package/dist/detectors/graphql-patterns.d.ts +2 -0
- package/dist/detectors/graphql-patterns.js +47 -0
- package/dist/detectors/graphql-patterns.js.map +1 -0
- package/dist/detectors/hook-patterns.d.ts +2 -0
- package/dist/detectors/hook-patterns.js +105 -0
- package/dist/detectors/hook-patterns.js.map +1 -0
- package/dist/detectors/import-patterns.d.ts +2 -0
- package/dist/detectors/import-patterns.js +88 -0
- package/dist/detectors/import-patterns.js.map +1 -0
- package/dist/detectors/telemetry-patterns.d.ts +2 -0
- package/dist/detectors/telemetry-patterns.js +42 -0
- package/dist/detectors/telemetry-patterns.js.map +1 -0
- package/dist/detectors/test-framework-ecosystem.d.ts +2 -0
- package/dist/detectors/test-framework-ecosystem.js +95 -0
- package/dist/detectors/test-framework-ecosystem.js.map +1 -0
- package/dist/detectors/test-patterns.d.ts +2 -0
- package/dist/detectors/test-patterns.js +60 -0
- package/dist/detectors/test-patterns.js.map +1 -0
- package/dist/detectors/web-framework.d.ts +2 -0
- package/dist/detectors/web-framework.js +51 -0
- package/dist/detectors/web-framework.js.map +1 -0
- package/dist/deterministic-formatter.d.ts +54 -0
- package/dist/deterministic-formatter.js +922 -0
- package/dist/deterministic-formatter.js.map +1 -0
- package/dist/diff-analyzer.d.ts +7 -0
- package/dist/diff-analyzer.js +126 -0
- package/dist/diff-analyzer.js.map +1 -0
- package/dist/example-extractor.d.ts +6 -0
- package/dist/example-extractor.js +115 -0
- package/dist/example-extractor.js.map +1 -0
- package/dist/existing-docs.d.ts +36 -0
- package/dist/existing-docs.js +257 -0
- package/dist/existing-docs.js.map +1 -0
- package/dist/file-discovery.d.ts +6 -0
- package/dist/file-discovery.js +154 -0
- package/dist/file-discovery.js.map +1 -0
- package/dist/git-history.d.ts +41 -0
- package/dist/git-history.js +401 -0
- package/dist/git-history.js.map +1 -0
- package/dist/impact-classifier.d.ts +22 -0
- package/dist/impact-classifier.js +87 -0
- package/dist/impact-classifier.js.map +1 -0
- package/dist/impact-radius.d.ts +23 -0
- package/dist/impact-radius.js +130 -0
- package/dist/impact-radius.js.map +1 -0
- package/dist/import-chain.d.ts +12 -0
- package/dist/import-chain.js +93 -0
- package/dist/import-chain.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/inferability.d.ts +16 -0
- package/dist/inferability.js +142 -0
- package/dist/inferability.js.map +1 -0
- package/dist/llm/adapter.d.ts +33 -0
- package/dist/llm/adapter.js +202 -0
- package/dist/llm/adapter.js.map +1 -0
- package/dist/llm/client.d.ts +5 -0
- package/dist/llm/client.js +68 -0
- package/dist/llm/client.js.map +1 -0
- package/dist/llm/hierarchical.d.ts +23 -0
- package/dist/llm/hierarchical.js +126 -0
- package/dist/llm/hierarchical.js.map +1 -0
- package/dist/llm/serializer.d.ts +19 -0
- package/dist/llm/serializer.js +363 -0
- package/dist/llm/serializer.js.map +1 -0
- package/dist/llm/template-selector.d.ts +7 -0
- package/dist/llm/template-selector.js +21 -0
- package/dist/llm/template-selector.js.map +1 -0
- package/dist/llm-adapter.d.ts +2 -0
- package/dist/llm-adapter.js +5 -0
- package/dist/llm-adapter.js.map +1 -0
- package/dist/mcp/cache.d.ts +30 -0
- package/dist/mcp/cache.js +112 -0
- package/dist/mcp/cache.js.map +1 -0
- package/dist/mcp/errors.d.ts +21 -0
- package/dist/mcp/errors.js +27 -0
- package/dist/mcp/errors.js.map +1 -0
- package/dist/mcp/queries.d.ts +27 -0
- package/dist/mcp/queries.js +121 -0
- package/dist/mcp/queries.js.map +1 -0
- package/dist/mcp/server.d.ts +14 -0
- package/dist/mcp/server.js +131 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +39 -0
- package/dist/mcp/tools.js +249 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mermaid-generator.d.ts +6 -0
- package/dist/mermaid-generator.js +59 -0
- package/dist/mermaid-generator.js.map +1 -0
- package/dist/meta-tool-detector.d.ts +23 -0
- package/dist/meta-tool-detector.js +177 -0
- package/dist/meta-tool-detector.js.map +1 -0
- package/dist/output-validator.d.ts +6 -0
- package/dist/output-validator.js +471 -0
- package/dist/output-validator.js.map +1 -0
- package/dist/pattern-fingerprinter.d.ts +7 -0
- package/dist/pattern-fingerprinter.js +241 -0
- package/dist/pattern-fingerprinter.js.map +1 -0
- package/dist/pipeline.d.ts +5 -0
- package/dist/pipeline.js +374 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/plugin-loader.d.ts +19 -0
- package/dist/plugin-loader.js +124 -0
- package/dist/plugin-loader.js.map +1 -0
- package/dist/role-inferrer.d.ts +5 -0
- package/dist/role-inferrer.js +159 -0
- package/dist/role-inferrer.js.map +1 -0
- package/dist/symbol-graph.d.ts +11 -0
- package/dist/symbol-graph.js +613 -0
- package/dist/symbol-graph.js.map +1 -0
- package/dist/templates/agents-md.d.ts +20 -0
- package/dist/templates/agents-md.js +346 -0
- package/dist/templates/agents-md.js.map +1 -0
- package/dist/templates/claude-md.d.ts +4 -0
- package/dist/templates/claude-md.js +23 -0
- package/dist/templates/claude-md.js.map +1 -0
- package/dist/templates/cursorrules.d.ts +4 -0
- package/dist/templates/cursorrules.js +18 -0
- package/dist/templates/cursorrules.js.map +1 -0
- package/dist/tier-classifier.d.ts +7 -0
- package/dist/tier-classifier.js +32 -0
- package/dist/tier-classifier.js.map +1 -0
- package/dist/types.d.ts +428 -0
- package/dist/types.js +42 -0
- package/dist/types.js.map +1 -0
- package/dist/workflow-rules.d.ts +18 -0
- package/dist/workflow-rules.js +131 -0
- package/dist/workflow-rules.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ResolvedConfig } from "../types.js";
|
|
2
|
+
import type { BenchmarkTask, BenchmarkCondition, GeneratedFile } from "./types.js";
|
|
3
|
+
export interface CodeGenResult {
|
|
4
|
+
files: GeneratedFile[];
|
|
5
|
+
tokensUsed: number;
|
|
6
|
+
latencyMs: number;
|
|
7
|
+
error?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generate code for a benchmark task under a specific condition.
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateCode(task: BenchmarkTask, condition: BenchmarkCondition, agentsMd: string | null, shuffledAgentsMd: string | null, llmConfig: ResolvedConfig["llm"]): Promise<CodeGenResult>;
|
|
13
|
+
/**
|
|
14
|
+
* Parse LLM response to extract generated files from code blocks.
|
|
15
|
+
* Handles multiple format variants:
|
|
16
|
+
* - ```filepath\ncontent```
|
|
17
|
+
* - ```ts\n// filepath: path/to/file.ts\ncontent```
|
|
18
|
+
* - ```typescript path/to/file.ts\ncontent```
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseCodeBlocks(response: string): GeneratedFile[];
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// src/benchmark/code-generator.ts — Generate code via LLM for benchmark conditions
|
|
2
|
+
// Builds fair prompts for treatment (A), realistic control (B),
|
|
3
|
+
// impoverished control (C), and negative control (N).
|
|
4
|
+
import { callLLMWithRetry } from "../llm/client.js";
|
|
5
|
+
/**
|
|
6
|
+
* Generate code for a benchmark task under a specific condition.
|
|
7
|
+
*/
|
|
8
|
+
export async function generateCode(task, condition, agentsMd, shuffledAgentsMd, llmConfig) {
|
|
9
|
+
const systemPrompt = buildSystemPrompt(task.packageName, task.taskType);
|
|
10
|
+
const userPrompt = buildUserPrompt(task, condition, agentsMd, shuffledAgentsMd);
|
|
11
|
+
const start = performance.now();
|
|
12
|
+
try {
|
|
13
|
+
const response = await callLLMWithRetry(systemPrompt, userPrompt, llmConfig);
|
|
14
|
+
const latencyMs = Math.round(performance.now() - start);
|
|
15
|
+
let files = parseCodeBlocks(response);
|
|
16
|
+
// Rough token estimate: 1 token ≈ 4 chars
|
|
17
|
+
const tokensUsed = Math.round((systemPrompt.length + userPrompt.length + response.length) / 4);
|
|
18
|
+
// For Q&A tasks (command, architecture), the raw response IS the answer.
|
|
19
|
+
// If no code blocks were parsed, wrap the full response as a virtual file.
|
|
20
|
+
if (files.length === 0 && response.trim().length > 0) {
|
|
21
|
+
files = [{ path: "__response__", content: response }];
|
|
22
|
+
}
|
|
23
|
+
return { files, tokensUsed, latencyMs };
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
27
|
+
return {
|
|
28
|
+
files: [],
|
|
29
|
+
tokensUsed: 0,
|
|
30
|
+
latencyMs: Math.round(performance.now() - start),
|
|
31
|
+
error: `LLM call failed: ${msg}`,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// ─── Prompt Construction ─────────────────────────────────────────────────────
|
|
36
|
+
function buildSystemPrompt(packageName, taskType) {
|
|
37
|
+
if (taskType === "command") {
|
|
38
|
+
return [
|
|
39
|
+
`You are an expert TypeScript developer working on the ${packageName} project.`,
|
|
40
|
+
`Your task is to write a build/CI configuration using this project's exact commands.`,
|
|
41
|
+
`Output the configuration file in a code block with filepath:`,
|
|
42
|
+
"",
|
|
43
|
+
"```filepath",
|
|
44
|
+
"// file content here",
|
|
45
|
+
"```",
|
|
46
|
+
"",
|
|
47
|
+
`Use the EXACT commands and package manager from this project. Do not guess or use defaults.`,
|
|
48
|
+
].join("\n");
|
|
49
|
+
}
|
|
50
|
+
if (taskType === "architecture") {
|
|
51
|
+
return [
|
|
52
|
+
`You are an expert TypeScript developer working on the ${packageName} project.`,
|
|
53
|
+
`Your task is to determine where new code should be placed in this project's structure.`,
|
|
54
|
+
`Respond with:`,
|
|
55
|
+
`1. The directory path where the code should go`,
|
|
56
|
+
`2. A brief justification (2-3 sentences) explaining why`,
|
|
57
|
+
``,
|
|
58
|
+
`Be specific — use actual directory names from this project, not generic suggestions.`,
|
|
59
|
+
].join("\n");
|
|
60
|
+
}
|
|
61
|
+
return [
|
|
62
|
+
`You are an expert TypeScript developer working on the ${packageName} project.`,
|
|
63
|
+
`Your task is to add new code to this codebase.`,
|
|
64
|
+
`For each file you create or modify, output it in this format:`,
|
|
65
|
+
"",
|
|
66
|
+
"```filepath",
|
|
67
|
+
"// file content here",
|
|
68
|
+
"```",
|
|
69
|
+
"",
|
|
70
|
+
`If you modify an existing file, output the COMPLETE modified file (all existing code plus your changes).`,
|
|
71
|
+
`Include ALL files needed: implementation, tests, and any existing files that need updates.`,
|
|
72
|
+
`Do not add explanations outside the code blocks.`,
|
|
73
|
+
].join("\n");
|
|
74
|
+
}
|
|
75
|
+
function buildUserPrompt(task, condition, agentsMd, shuffledAgentsMd) {
|
|
76
|
+
const parts = [];
|
|
77
|
+
// Shared context: registration and barrel files (ALL conditions get these)
|
|
78
|
+
if (task.context.registrationFile) {
|
|
79
|
+
parts.push(`<file path="${task.context.registrationFile.path}">`);
|
|
80
|
+
parts.push(task.context.registrationFile.content);
|
|
81
|
+
parts.push(`</file>`);
|
|
82
|
+
parts.push("");
|
|
83
|
+
}
|
|
84
|
+
if (task.context.barrelFile) {
|
|
85
|
+
parts.push(`<file path="${task.context.barrelFile.path}">`);
|
|
86
|
+
parts.push(task.context.barrelFile.content);
|
|
87
|
+
parts.push(`</file>`);
|
|
88
|
+
parts.push("");
|
|
89
|
+
}
|
|
90
|
+
// Condition-specific context
|
|
91
|
+
switch (condition) {
|
|
92
|
+
case "treatment":
|
|
93
|
+
// A: AGENTS.md + sibling files + dir listing
|
|
94
|
+
if (agentsMd) {
|
|
95
|
+
parts.push("<agents-md>");
|
|
96
|
+
parts.push(agentsMd);
|
|
97
|
+
parts.push("</agents-md>");
|
|
98
|
+
parts.push("");
|
|
99
|
+
}
|
|
100
|
+
for (const sibling of task.context.siblingFiles) {
|
|
101
|
+
parts.push(`<file path="${sibling.path}">`);
|
|
102
|
+
parts.push(sibling.content);
|
|
103
|
+
parts.push(`</file>`);
|
|
104
|
+
parts.push("");
|
|
105
|
+
}
|
|
106
|
+
break;
|
|
107
|
+
case "realistic-control":
|
|
108
|
+
// B: sibling files + dir listing (no AGENTS.md)
|
|
109
|
+
for (const sibling of task.context.siblingFiles) {
|
|
110
|
+
parts.push(`<file path="${sibling.path}">`);
|
|
111
|
+
parts.push(sibling.content);
|
|
112
|
+
parts.push(`</file>`);
|
|
113
|
+
parts.push("");
|
|
114
|
+
}
|
|
115
|
+
break;
|
|
116
|
+
case "impoverished-control":
|
|
117
|
+
// C: dir listing only (no siblings, no AGENTS.md)
|
|
118
|
+
break;
|
|
119
|
+
case "negative-control":
|
|
120
|
+
// N: shuffled AGENTS.md + dir listing (no siblings)
|
|
121
|
+
if (shuffledAgentsMd) {
|
|
122
|
+
parts.push("<agents-md>");
|
|
123
|
+
parts.push(shuffledAgentsMd);
|
|
124
|
+
parts.push("</agents-md>");
|
|
125
|
+
parts.push("");
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
// Directory listing (all conditions)
|
|
130
|
+
if (task.context.directoryListing.length > 0) {
|
|
131
|
+
parts.push(`Directory listing of ${task.expectedDirectory}:`);
|
|
132
|
+
for (const file of task.context.directoryListing.slice(0, 30)) {
|
|
133
|
+
parts.push(` ${file}`);
|
|
134
|
+
}
|
|
135
|
+
parts.push("");
|
|
136
|
+
}
|
|
137
|
+
// Task prompt
|
|
138
|
+
parts.push(`Task: ${task.prompt}`);
|
|
139
|
+
return parts.join("\n");
|
|
140
|
+
}
|
|
141
|
+
// ─── Code Block Parsing ──────────────────────────────────────────────────────
|
|
142
|
+
/**
|
|
143
|
+
* Parse LLM response to extract generated files from code blocks.
|
|
144
|
+
* Handles multiple format variants:
|
|
145
|
+
* - ```filepath\ncontent```
|
|
146
|
+
* - ```ts\n// filepath: path/to/file.ts\ncontent```
|
|
147
|
+
* - ```typescript path/to/file.ts\ncontent```
|
|
148
|
+
*/
|
|
149
|
+
export function parseCodeBlocks(response) {
|
|
150
|
+
const files = [];
|
|
151
|
+
// Match fenced code blocks: ```[lang] [path]\n...\n```
|
|
152
|
+
const blockRegex = /```([^\n]*)\n([\s\S]*?)```/g;
|
|
153
|
+
let match;
|
|
154
|
+
while ((match = blockRegex.exec(response)) !== null) {
|
|
155
|
+
const header = match[1].trim();
|
|
156
|
+
const body = match[2];
|
|
157
|
+
let filepath = extractFilePath(header, body);
|
|
158
|
+
if (!filepath)
|
|
159
|
+
continue;
|
|
160
|
+
// Normalize path
|
|
161
|
+
filepath = filepath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
162
|
+
files.push({ path: filepath, content: body.trimEnd() });
|
|
163
|
+
}
|
|
164
|
+
return files;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Extract file path from code block header or first line of body.
|
|
168
|
+
*/
|
|
169
|
+
function extractFilePath(header, body) {
|
|
170
|
+
// Case 1: Header IS the filepath (e.g., ```src/foo.ts)
|
|
171
|
+
if (header && looksLikeFilePath(header)) {
|
|
172
|
+
return header;
|
|
173
|
+
}
|
|
174
|
+
// Case 2: Header is "lang filepath" (e.g., ```typescript src/foo.ts)
|
|
175
|
+
if (header) {
|
|
176
|
+
const parts = header.split(/\s+/);
|
|
177
|
+
if (parts.length >= 2) {
|
|
178
|
+
const maybePath = parts.slice(1).join(" ");
|
|
179
|
+
if (looksLikeFilePath(maybePath))
|
|
180
|
+
return maybePath;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Case 3: First line of body is a filepath comment (e.g., // filepath: src/foo.ts)
|
|
184
|
+
const firstLine = body.split("\n")[0]?.trim() ?? "";
|
|
185
|
+
const commentMatch = firstLine.match(/^\/\/\s*(?:filepath:\s*)?(.+\.[a-z]{1,4})\s*$/i);
|
|
186
|
+
if (commentMatch && looksLikeFilePath(commentMatch[1])) {
|
|
187
|
+
return commentMatch[1];
|
|
188
|
+
}
|
|
189
|
+
// Case 4: First line IS a filepath (e.g., src/foo.ts)
|
|
190
|
+
if (looksLikeFilePath(firstLine)) {
|
|
191
|
+
return firstLine;
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
function looksLikeFilePath(s) {
|
|
196
|
+
// Must contain a dot, no spaces (spaces suggest "lang path" format), not a language name
|
|
197
|
+
if (!s || !s.includes(".") || s.includes(" "))
|
|
198
|
+
return false;
|
|
199
|
+
// Language names to reject
|
|
200
|
+
const langs = new Set(["typescript", "ts", "tsx", "javascript", "js", "jsx", "json", "md", "yaml", "yml", "bash", "sh"]);
|
|
201
|
+
if (langs.has(s.toLowerCase()))
|
|
202
|
+
return false;
|
|
203
|
+
// Must end with a file extension
|
|
204
|
+
return /\.[a-z]{1,5}$/i.test(s);
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=code-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-generator.js","sourceRoot":"","sources":["../../src/benchmark/code-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export interface MinedTask {
|
|
2
|
+
id: string;
|
|
3
|
+
commitSha: string;
|
|
4
|
+
commitMessage: string;
|
|
5
|
+
commitDate: string;
|
|
6
|
+
groundTruth: {
|
|
7
|
+
path: string;
|
|
8
|
+
content: string;
|
|
9
|
+
directory: string;
|
|
10
|
+
filename: string;
|
|
11
|
+
lineCount: number;
|
|
12
|
+
};
|
|
13
|
+
context: {
|
|
14
|
+
siblingFiles: {
|
|
15
|
+
path: string;
|
|
16
|
+
content: string;
|
|
17
|
+
}[];
|
|
18
|
+
directoryListing: string[];
|
|
19
|
+
barrelFile?: {
|
|
20
|
+
path: string;
|
|
21
|
+
content: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export interface MinerOptions {
|
|
26
|
+
maxTasks?: number;
|
|
27
|
+
maxCommits?: number;
|
|
28
|
+
sinceDays?: number;
|
|
29
|
+
minFileLines?: number;
|
|
30
|
+
maxFileLines?: number;
|
|
31
|
+
minSiblings?: number;
|
|
32
|
+
minMessageLength?: number;
|
|
33
|
+
maxFilesPerCommit?: number;
|
|
34
|
+
verbose?: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface MinerStats {
|
|
37
|
+
totalCommits: number;
|
|
38
|
+
commitsWithAddedTs: number;
|
|
39
|
+
afterQualityFilter: number;
|
|
40
|
+
afterDiversityFilter: number;
|
|
41
|
+
selected: number;
|
|
42
|
+
filterReasons: Record<string, number>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Mine a git repository for qualifying "add file" commits.
|
|
46
|
+
* Returns tasks sorted by recency, with diverse directory coverage.
|
|
47
|
+
*/
|
|
48
|
+
export declare function mineCommits(repoPath: string, options?: MinerOptions): {
|
|
49
|
+
tasks: MinedTask[];
|
|
50
|
+
stats: MinerStats;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Read a file's content at a specific commit SHA.
|
|
54
|
+
* Returns null if the file doesn't exist at that commit.
|
|
55
|
+
*/
|
|
56
|
+
export declare function readFileAtCommit(gitRoot: string, sha: string, filePath: string): string | null;
|
|
57
|
+
/**
|
|
58
|
+
* List files in a directory at a specific commit SHA.
|
|
59
|
+
* Returns repo-relative paths.
|
|
60
|
+
*/
|
|
61
|
+
export declare function listDirAtCommit(gitRoot: string, sha: string, dirPath: string): string[];
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
// src/benchmark/pr-miner.ts — Mine git history for real "add file" commits
|
|
2
|
+
// Uses actual developer commits as ground truth for benchmark tasks.
|
|
3
|
+
// Reads all files at commit time (not HEAD) to avoid time-travel leakage.
|
|
4
|
+
import { execSync } from "node:child_process";
|
|
5
|
+
import { resolve, dirname, basename, extname } from "node:path";
|
|
6
|
+
// ─── Constants ──────────────────────────────────────────────────────────────
|
|
7
|
+
const DEFAULTS = {
|
|
8
|
+
maxTasks: 30,
|
|
9
|
+
maxCommits: 500,
|
|
10
|
+
sinceDays: 365,
|
|
11
|
+
minFileLines: 20,
|
|
12
|
+
maxFileLines: 500,
|
|
13
|
+
minSiblings: 3,
|
|
14
|
+
minMessageLength: 15,
|
|
15
|
+
maxFilesPerCommit: 10,
|
|
16
|
+
verbose: false,
|
|
17
|
+
};
|
|
18
|
+
const TS_EXTENSIONS = /\.(ts|tsx)$/;
|
|
19
|
+
const SKIP_PATTERNS = [
|
|
20
|
+
/\.test\.(ts|tsx)$/,
|
|
21
|
+
/\.spec\.(ts|tsx)$/,
|
|
22
|
+
/\.d\.(ts|tsx)$/,
|
|
23
|
+
/\.config\.(ts|tsx)$/,
|
|
24
|
+
/\.stories\.(ts|tsx)$/,
|
|
25
|
+
/\.e2e\.(ts|tsx)$/,
|
|
26
|
+
/\/__tests__\//,
|
|
27
|
+
/\/test\//,
|
|
28
|
+
/\/fixtures?\//,
|
|
29
|
+
/\/mocks?\//,
|
|
30
|
+
];
|
|
31
|
+
const SKIP_FILENAMES = new Set([
|
|
32
|
+
"index.ts", "index.tsx", "mod.ts", // barrel files
|
|
33
|
+
"types.ts", "constants.ts", // typically type-only
|
|
34
|
+
"package.json", "tsconfig.json",
|
|
35
|
+
]);
|
|
36
|
+
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
37
|
+
/**
|
|
38
|
+
* Mine a git repository for qualifying "add file" commits.
|
|
39
|
+
* Returns tasks sorted by recency, with diverse directory coverage.
|
|
40
|
+
*/
|
|
41
|
+
export function mineCommits(repoPath, options = {}) {
|
|
42
|
+
const opts = { ...DEFAULTS, ...options };
|
|
43
|
+
const absRepo = resolve(repoPath);
|
|
44
|
+
const gitRoot = getGitRoot(absRepo);
|
|
45
|
+
if (!gitRoot) {
|
|
46
|
+
throw new Error(`Not a git repository: ${absRepo}`);
|
|
47
|
+
}
|
|
48
|
+
const stats = {
|
|
49
|
+
totalCommits: 0,
|
|
50
|
+
commitsWithAddedTs: 0,
|
|
51
|
+
afterQualityFilter: 0,
|
|
52
|
+
afterDiversityFilter: 0,
|
|
53
|
+
selected: 0,
|
|
54
|
+
filterReasons: {},
|
|
55
|
+
};
|
|
56
|
+
// Phase 1: Find commits that added TS files
|
|
57
|
+
const rawCommits = findAddFileCommits(gitRoot, opts);
|
|
58
|
+
stats.totalCommits = rawCommits.length;
|
|
59
|
+
// Phase 2: Filter each commit's added files by quality criteria
|
|
60
|
+
const candidates = [];
|
|
61
|
+
for (const commit of rawCommits) {
|
|
62
|
+
stats.commitsWithAddedTs++;
|
|
63
|
+
for (const filePath of commit.addedFiles) {
|
|
64
|
+
const task = processCandidate(gitRoot, commit, filePath, opts, stats);
|
|
65
|
+
if (task)
|
|
66
|
+
candidates.push(task);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
stats.afterQualityFilter = candidates.length;
|
|
70
|
+
// Phase 3: Enforce directory diversity (max 2 tasks per directory)
|
|
71
|
+
const diverse = enforceDiversity(candidates);
|
|
72
|
+
stats.afterDiversityFilter = diverse.length;
|
|
73
|
+
// Phase 4: Select top N, preferring recent and diverse
|
|
74
|
+
const selected = diverse.slice(0, opts.maxTasks);
|
|
75
|
+
stats.selected = selected.length;
|
|
76
|
+
if (opts.verbose) {
|
|
77
|
+
logStats(stats);
|
|
78
|
+
}
|
|
79
|
+
return { tasks: selected, stats };
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Find commits that added TypeScript files.
|
|
83
|
+
* Uses `git log --diff-filter=A --name-only` to efficiently find additions.
|
|
84
|
+
*/
|
|
85
|
+
function findAddFileCommits(gitRoot, opts) {
|
|
86
|
+
const raw = gitExec(gitRoot, `git log --no-merges --diff-filter=A --name-only ` +
|
|
87
|
+
`--format="COMMIT:%H|%s|%aI" ` +
|
|
88
|
+
`--since="${opts.sinceDays} days ago" ` +
|
|
89
|
+
`-n ${opts.maxCommits} ` +
|
|
90
|
+
`-- "*.ts" "*.tsx"`);
|
|
91
|
+
if (!raw)
|
|
92
|
+
return [];
|
|
93
|
+
const commits = [];
|
|
94
|
+
let current = null;
|
|
95
|
+
for (const line of raw.split("\n")) {
|
|
96
|
+
if (line.startsWith("COMMIT:")) {
|
|
97
|
+
if (current)
|
|
98
|
+
commits.push(current);
|
|
99
|
+
const parts = line.slice(7).split("|");
|
|
100
|
+
current = {
|
|
101
|
+
sha: parts[0],
|
|
102
|
+
message: parts.slice(1, -1).join("|"), // message may contain |
|
|
103
|
+
date: parts[parts.length - 1],
|
|
104
|
+
totalFilesChanged: 0,
|
|
105
|
+
addedFiles: [],
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
else if (line.trim() && current) {
|
|
109
|
+
current.addedFiles.push(line.trim());
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (current)
|
|
113
|
+
commits.push(current);
|
|
114
|
+
// Get total files changed per commit (including non-additions)
|
|
115
|
+
for (const commit of commits) {
|
|
116
|
+
const stat = gitExec(gitRoot, `git diff-tree --no-commit-id --name-only -r ${commit.sha}`);
|
|
117
|
+
commit.totalFilesChanged = stat
|
|
118
|
+
? stat.split("\n").filter(l => l.trim()).length
|
|
119
|
+
: commit.addedFiles.length;
|
|
120
|
+
}
|
|
121
|
+
return commits;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Read a file's content at a specific commit SHA.
|
|
125
|
+
* Returns null if the file doesn't exist at that commit.
|
|
126
|
+
*/
|
|
127
|
+
export function readFileAtCommit(gitRoot, sha, filePath) {
|
|
128
|
+
return gitExec(gitRoot, `git show ${sha}:${filePath}`);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* List files in a directory at a specific commit SHA.
|
|
132
|
+
* Returns repo-relative paths.
|
|
133
|
+
*/
|
|
134
|
+
export function listDirAtCommit(gitRoot, sha, dirPath) {
|
|
135
|
+
// Ensure dirPath ends with / for git ls-tree
|
|
136
|
+
const dir = dirPath.endsWith("/") ? dirPath : dirPath + "/";
|
|
137
|
+
const raw = gitExec(gitRoot, `git ls-tree --name-only ${sha} ${dir}`);
|
|
138
|
+
if (!raw)
|
|
139
|
+
return [];
|
|
140
|
+
return raw.split("\n").filter(l => l.trim()).map(f => basename(f));
|
|
141
|
+
}
|
|
142
|
+
// ─── Candidate Processing ───────────────────────────────────────────────────
|
|
143
|
+
function processCandidate(gitRoot, commit, filePath, opts, stats) {
|
|
144
|
+
const reason = (r) => {
|
|
145
|
+
stats.filterReasons[r] = (stats.filterReasons[r] ?? 0) + 1;
|
|
146
|
+
return null;
|
|
147
|
+
};
|
|
148
|
+
// Filter: commit changed too many files (bulk import/refactor)
|
|
149
|
+
if (commit.totalFilesChanged > opts.maxFilesPerCommit) {
|
|
150
|
+
return reason("too-many-files-changed");
|
|
151
|
+
}
|
|
152
|
+
// Filter: commit message too short
|
|
153
|
+
if (commit.message.length < opts.minMessageLength) {
|
|
154
|
+
return reason("short-commit-message");
|
|
155
|
+
}
|
|
156
|
+
// Filter: skip test/config/type/fixture files
|
|
157
|
+
const fileName = basename(filePath);
|
|
158
|
+
if (SKIP_FILENAMES.has(fileName)) {
|
|
159
|
+
return reason("skip-filename");
|
|
160
|
+
}
|
|
161
|
+
if (SKIP_PATTERNS.some(p => p.test(filePath))) {
|
|
162
|
+
return reason("skip-pattern");
|
|
163
|
+
}
|
|
164
|
+
// Filter: must be TS/TSX
|
|
165
|
+
if (!TS_EXTENSIONS.test(filePath)) {
|
|
166
|
+
return reason("not-typescript");
|
|
167
|
+
}
|
|
168
|
+
// Read ground truth at commit time
|
|
169
|
+
const content = readFileAtCommit(gitRoot, commit.sha, filePath);
|
|
170
|
+
if (!content) {
|
|
171
|
+
return reason("file-unreadable");
|
|
172
|
+
}
|
|
173
|
+
// Filter: file size
|
|
174
|
+
const lineCount = content.split("\n").length;
|
|
175
|
+
if (lineCount < opts.minFileLines) {
|
|
176
|
+
return reason("too-small");
|
|
177
|
+
}
|
|
178
|
+
if (lineCount > opts.maxFileLines) {
|
|
179
|
+
return reason("too-large");
|
|
180
|
+
}
|
|
181
|
+
// Get directory context from PARENT commit (before the file was added)
|
|
182
|
+
const dir = dirname(filePath);
|
|
183
|
+
const parentSha = commit.sha + "^";
|
|
184
|
+
// List siblings at parent commit
|
|
185
|
+
const siblings = listDirAtCommit(gitRoot, parentSha, dir);
|
|
186
|
+
const tsSiblings = siblings.filter(f => TS_EXTENSIONS.test(f) && f !== fileName);
|
|
187
|
+
// Filter: must have enough siblings for context
|
|
188
|
+
if (tsSiblings.length < opts.minSiblings) {
|
|
189
|
+
return reason("too-few-siblings");
|
|
190
|
+
}
|
|
191
|
+
// Read sibling files (up to 5, sorted alphabetically for determinism)
|
|
192
|
+
const siblingFiles = [];
|
|
193
|
+
const sibsToRead = tsSiblings.sort().slice(0, 5);
|
|
194
|
+
for (const sib of sibsToRead) {
|
|
195
|
+
const sibPath = dir + "/" + sib;
|
|
196
|
+
const sibContent = readFileAtCommit(gitRoot, parentSha, sibPath);
|
|
197
|
+
if (sibContent) {
|
|
198
|
+
siblingFiles.push({
|
|
199
|
+
path: sibPath,
|
|
200
|
+
content: truncate(sibContent, 100),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// Check for barrel file at parent commit
|
|
205
|
+
let barrelFile;
|
|
206
|
+
for (const barrelName of ["index.ts", "index.tsx"]) {
|
|
207
|
+
const barrelPath = dir + "/" + barrelName;
|
|
208
|
+
const barrelContent = readFileAtCommit(gitRoot, parentSha, barrelPath);
|
|
209
|
+
if (barrelContent) {
|
|
210
|
+
barrelFile = { path: barrelPath, content: barrelContent };
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// Directory listing at parent commit (all files, not just TS)
|
|
215
|
+
const dirListing = listDirAtCommit(gitRoot, parentSha, dir);
|
|
216
|
+
// Build task ID from directory and filename
|
|
217
|
+
const id = `pr-${dir.replace(/\//g, "-")}-${basename(filePath, extname(filePath))}`;
|
|
218
|
+
return {
|
|
219
|
+
id,
|
|
220
|
+
commitSha: commit.sha,
|
|
221
|
+
commitMessage: commit.message.trim(),
|
|
222
|
+
commitDate: commit.date,
|
|
223
|
+
groundTruth: {
|
|
224
|
+
path: filePath,
|
|
225
|
+
content,
|
|
226
|
+
directory: dir,
|
|
227
|
+
filename: fileName,
|
|
228
|
+
lineCount,
|
|
229
|
+
},
|
|
230
|
+
context: {
|
|
231
|
+
siblingFiles,
|
|
232
|
+
directoryListing: dirListing,
|
|
233
|
+
barrelFile,
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
// ─── Diversity & Selection ──────────────────────────────────────────────────
|
|
238
|
+
/**
|
|
239
|
+
* Enforce directory diversity: max 2 tasks per directory, max 4 per package.
|
|
240
|
+
* Preserves order (most recent first from git log).
|
|
241
|
+
*/
|
|
242
|
+
function enforceDiversity(candidates) {
|
|
243
|
+
const dirCounts = new Map();
|
|
244
|
+
const pkgCounts = new Map();
|
|
245
|
+
const result = [];
|
|
246
|
+
for (const task of candidates) {
|
|
247
|
+
const dir = task.groundTruth.directory;
|
|
248
|
+
const pkg = getPackageRoot(dir);
|
|
249
|
+
const dirCount = dirCounts.get(dir) ?? 0;
|
|
250
|
+
const pkgCount = pkgCounts.get(pkg) ?? 0;
|
|
251
|
+
if (dirCount >= 2 || pkgCount >= 4)
|
|
252
|
+
continue;
|
|
253
|
+
dirCounts.set(dir, dirCount + 1);
|
|
254
|
+
pkgCounts.set(pkg, pkgCount + 1);
|
|
255
|
+
result.push(task);
|
|
256
|
+
}
|
|
257
|
+
return result;
|
|
258
|
+
}
|
|
259
|
+
function getPackageRoot(dir) {
|
|
260
|
+
// Extract package root: packages/<name>/ or apps/<name>/ or just the first 2 segments
|
|
261
|
+
const parts = dir.split("/");
|
|
262
|
+
if (parts[0] === "packages" || parts[0] === "apps") {
|
|
263
|
+
return parts.slice(0, 2).join("/");
|
|
264
|
+
}
|
|
265
|
+
return parts.slice(0, Math.min(2, parts.length)).join("/");
|
|
266
|
+
}
|
|
267
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
268
|
+
function gitExec(cwd, command) {
|
|
269
|
+
try {
|
|
270
|
+
return execSync(command, {
|
|
271
|
+
cwd,
|
|
272
|
+
encoding: "utf-8",
|
|
273
|
+
timeout: 15_000,
|
|
274
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
275
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
276
|
+
}).trimEnd();
|
|
277
|
+
}
|
|
278
|
+
catch {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function getGitRoot(dir) {
|
|
283
|
+
return gitExec(dir, "git rev-parse --show-toplevel");
|
|
284
|
+
}
|
|
285
|
+
function truncate(content, maxLines) {
|
|
286
|
+
const lines = content.split("\n");
|
|
287
|
+
if (lines.length <= maxLines)
|
|
288
|
+
return content;
|
|
289
|
+
return lines.slice(0, maxLines).join("\n") + "\n// ... truncated";
|
|
290
|
+
}
|
|
291
|
+
function logStats(stats) {
|
|
292
|
+
console.error(`[pr-miner] Commits scanned: ${stats.totalCommits}`);
|
|
293
|
+
console.error(`[pr-miner] With added TS files: ${stats.commitsWithAddedTs}`);
|
|
294
|
+
console.error(`[pr-miner] After quality filter: ${stats.afterQualityFilter}`);
|
|
295
|
+
console.error(`[pr-miner] After diversity filter: ${stats.afterDiversityFilter}`);
|
|
296
|
+
console.error(`[pr-miner] Selected: ${stats.selected}`);
|
|
297
|
+
if (Object.keys(stats.filterReasons).length > 0) {
|
|
298
|
+
console.error(`[pr-miner] Filter reasons:`);
|
|
299
|
+
for (const [reason, count] of Object.entries(stats.filterReasons).sort((a, b) => b[1] - a[1])) {
|
|
300
|
+
console.error(` ${reason}: ${count}`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=pr-miner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-miner.js","sourceRoot":"","sources":["../../src/benchmark/pr-miner.ts"],"names":[],"mappings":"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"}
|