evalbuff 0.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 +79 -0
- package/dist/carve-features.d.ts +42 -0
- package/dist/carve-features.d.ts.map +1 -0
- package/dist/carve-features.js +305 -0
- package/dist/carve-features.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +42 -0
- package/dist/cli.js.map +1 -0
- package/dist/docs-refactor.d.ts +4 -0
- package/dist/docs-refactor.d.ts.map +1 -0
- package/dist/docs-refactor.js +122 -0
- package/dist/docs-refactor.js.map +1 -0
- package/dist/docs-writer.d.ts +4 -0
- package/dist/docs-writer.d.ts.map +1 -0
- package/dist/docs-writer.js +122 -0
- package/dist/docs-writer.js.map +1 -0
- package/dist/eval-helpers.d.ts +19 -0
- package/dist/eval-helpers.d.ts.map +1 -0
- package/dist/eval-helpers.js +327 -0
- package/dist/eval-helpers.js.map +1 -0
- package/dist/eval-runner.d.ts +42 -0
- package/dist/eval-runner.d.ts.map +1 -0
- package/dist/eval-runner.js +193 -0
- package/dist/eval-runner.js.map +1 -0
- package/dist/judge.d.ts +22 -0
- package/dist/judge.d.ts.map +1 -0
- package/dist/judge.js +284 -0
- package/dist/judge.js.map +1 -0
- package/dist/perfect-feature.d.ts +2 -0
- package/dist/perfect-feature.d.ts.map +1 -0
- package/dist/perfect-feature.js +666 -0
- package/dist/perfect-feature.js.map +1 -0
- package/dist/report.d.ts +31 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +249 -0
- package/dist/report.js.map +1 -0
- package/dist/run-evalbuff.d.ts +12 -0
- package/dist/run-evalbuff.d.ts.map +1 -0
- package/dist/run-evalbuff.js +383 -0
- package/dist/run-evalbuff.js.map +1 -0
- package/dist/runners/claude.d.ts +10 -0
- package/dist/runners/claude.d.ts.map +1 -0
- package/dist/runners/claude.js +80 -0
- package/dist/runners/claude.js.map +1 -0
- package/dist/runners/codebuff.d.ts +24 -0
- package/dist/runners/codebuff.d.ts.map +1 -0
- package/dist/runners/codebuff.js +88 -0
- package/dist/runners/codebuff.js.map +1 -0
- package/dist/runners/codex.d.ts +8 -0
- package/dist/runners/codex.d.ts.map +1 -0
- package/dist/runners/codex.js +131 -0
- package/dist/runners/codex.js.map +1 -0
- package/dist/runners/index.d.ts +5 -0
- package/dist/runners/index.d.ts.map +1 -0
- package/dist/runners/index.js +4 -0
- package/dist/runners/index.js.map +1 -0
- package/dist/runners/runner.d.ts +11 -0
- package/dist/runners/runner.d.ts.map +1 -0
- package/dist/runners/runner.js +2 -0
- package/dist/runners/runner.js.map +1 -0
- package/dist/test-repo-utils.d.ts +21 -0
- package/dist/test-repo-utils.d.ts.map +1 -0
- package/dist/test-repo-utils.js +109 -0
- package/dist/test-repo-utils.js.map +1 -0
- package/dist/trace-compressor.d.ts +130 -0
- package/dist/trace-compressor.d.ts.map +1 -0
- package/dist/trace-compressor.js +680 -0
- package/dist/trace-compressor.js.map +1 -0
- package/dist/tui/data.d.ts +84 -0
- package/dist/tui/data.d.ts.map +1 -0
- package/dist/tui/data.js +80 -0
- package/dist/tui/data.js.map +1 -0
- package/dist/tui/events.d.ts +86 -0
- package/dist/tui/events.d.ts.map +1 -0
- package/dist/tui/events.js +52 -0
- package/dist/tui/events.js.map +1 -0
- package/dist/vendor/error.d.ts +18 -0
- package/dist/vendor/error.d.ts.map +1 -0
- package/dist/vendor/error.js +64 -0
- package/dist/vendor/error.js.map +1 -0
- package/dist/vendor/print-mode.d.ts +75 -0
- package/dist/vendor/print-mode.d.ts.map +1 -0
- package/dist/vendor/print-mode.js +2 -0
- package/dist/vendor/print-mode.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Evalbuff
|
|
2
|
+
|
|
3
|
+
**Improve your coding agent's performance through automated practice.**
|
|
4
|
+
|
|
5
|
+
Evalbuff runs your coding agent on practice tasks carved from your codebase, watches it fail, writes docs to fix the pattern, and keeps only the changes that measurably help. The result is a `docs/` directory of markdown files that encode the missing knowledge your agent needs to produce correct changes.
|
|
6
|
+
|
|
7
|
+
## Why it works
|
|
8
|
+
|
|
9
|
+
Your coding agent is missing context. It doesn't understand your product. It edits the wrong package. It doesn't know how to verify changes end-to-end.
|
|
10
|
+
|
|
11
|
+
All of this is solvable with the right context — missing domain knowledge, subtle conventions, step-by-step verification workflows. And all of that context can be recorded in plain markdown files.
|
|
12
|
+
|
|
13
|
+
### Hierarchical docs > skills
|
|
14
|
+
|
|
15
|
+
[OpenAI](https://openai.com/index/harness-engineering/) and [Vercel](https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals) have independently converged on a pattern for increasing agent performance:
|
|
16
|
+
|
|
17
|
+
- A `docs/` directory with nested markdown files
|
|
18
|
+
- A table of contents in `AGENTS.md` (or `CLAUDE.md`) with descriptions so the agent reads the right docs
|
|
19
|
+
|
|
20
|
+
Evalbuff automates building and maintaining this docs directory — and validates every change against real evals.
|
|
21
|
+
|
|
22
|
+
### Not just docs, evalmaxxing docs
|
|
23
|
+
|
|
24
|
+
The goal isn't to produce docs that explain your project. The goal is to include whatever knowledge or instructions **increase the performance of your coding agent on evals** — domain knowledge missing from raw code, processes for end-to-end verification, and guardrails that prevent common mistakes.
|
|
25
|
+
|
|
26
|
+
## How it works
|
|
27
|
+
|
|
28
|
+
Evalbuff creates practice tasks by **carving** — surgically removing a feature from your codebase (deleting the relevant code while keeping everything else intact) and then challenging an agent to rebuild it from scratch. The original implementation serves as ground truth for judging the result.
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
1. Identify features in the repo that can be cleanly carved out
|
|
32
|
+
2. Carve a random subset of n features (delete the code, keep the rest)
|
|
33
|
+
3. Baseline: have agents rebuild each carved feature in parallel, judge the results
|
|
34
|
+
against the original implementation, collect scores + doc suggestions
|
|
35
|
+
4. Loop N times:
|
|
36
|
+
a. Docs refactor agent reads judge suggestions and edits docs holistically
|
|
37
|
+
b. Re-eval: rebuild in parallel, judge, get new scores + doc suggestions
|
|
38
|
+
c. Keep only doc changes that improve scores
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
Try it now! Simply run the `run-evalbuff.ts` script with the path to your repo:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
bun run src/run-evalbuff.ts \
|
|
47
|
+
--repo /path/to/repo \
|
|
48
|
+
[--n 20] \
|
|
49
|
+
[--parallelism 3] \
|
|
50
|
+
[--loops 3] \
|
|
51
|
+
[--init-command "npm install"]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
| Flag | Description |
|
|
55
|
+
|------|-------------|
|
|
56
|
+
| `--repo` | Path to the repo to optimize docs for |
|
|
57
|
+
| `--n` | Number of features to carve per eval round (default: 20) |
|
|
58
|
+
| `--parallelism` | How many agent runs to execute in parallel (default: 3) |
|
|
59
|
+
| `--loops` | Number of doc-improvement iterations (default: 3) |
|
|
60
|
+
| `--init-command` | Setup command to run in the repo before each agent run (e.g. `npm install`) |
|
|
61
|
+
| `--coding-model` | Model for the coding agent (default: sonnet) |
|
|
62
|
+
| `--docs-model` | Model for the docs writer agent (default: opus) |
|
|
63
|
+
|
|
64
|
+
## Testing
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
bun run test
|
|
68
|
+
bun run test:all
|
|
69
|
+
bun run test:e2e
|
|
70
|
+
bun run typecheck
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Artifacts
|
|
74
|
+
|
|
75
|
+
Run artifacts are written under:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
$TMPDIR/evalbuff-run-<timestamp>/
|
|
79
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface CarveCandidate {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
prompt: string;
|
|
5
|
+
description: string;
|
|
6
|
+
files: string[];
|
|
7
|
+
relevantFiles: string[];
|
|
8
|
+
complexity: 'small' | 'medium' | 'large';
|
|
9
|
+
}
|
|
10
|
+
export interface CarvePlan {
|
|
11
|
+
candidates: CarveCandidate[];
|
|
12
|
+
reasoning: string;
|
|
13
|
+
}
|
|
14
|
+
export interface FileOperation {
|
|
15
|
+
path: string;
|
|
16
|
+
action: 'delete' | 'modify';
|
|
17
|
+
newContent?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface CarvedFeature {
|
|
20
|
+
id: string;
|
|
21
|
+
prompt: string;
|
|
22
|
+
description: string;
|
|
23
|
+
complexity: 'small' | 'medium' | 'large';
|
|
24
|
+
/** Files as they exist before carving (the "ground truth" to rebuild) */
|
|
25
|
+
originalFiles: Record<string, string>;
|
|
26
|
+
/** Operations to perform to carve the feature out */
|
|
27
|
+
operations: FileOperation[];
|
|
28
|
+
/** Unified diff of the carving (from git diff) */
|
|
29
|
+
diff: string;
|
|
30
|
+
}
|
|
31
|
+
export interface CarveResult {
|
|
32
|
+
repoPath: string;
|
|
33
|
+
generationDate: string;
|
|
34
|
+
features: CarvedFeature[];
|
|
35
|
+
}
|
|
36
|
+
export declare function planFeatures(repoPath: string): Promise<CarvePlan>;
|
|
37
|
+
export declare function carveFeature(repoPath: string, candidate: CarveCandidate): Promise<CarvedFeature | null>;
|
|
38
|
+
export declare function carveFeatures(repoPath: string, options?: {
|
|
39
|
+
count?: number;
|
|
40
|
+
outputPath?: string;
|
|
41
|
+
}): Promise<CarveResult>;
|
|
42
|
+
//# sourceMappingURL=carve-features.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"carve-features.d.ts","sourceRoot":"","sources":["../src/carve-features.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,UAAU,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAA;CACzC;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,cAAc,EAAE,CAAA;IAC5B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAA;IACxC,yEAAyE;IACzE,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,qDAAqD;IACrD,UAAU,EAAE,aAAa,EAAE,CAAA;IAC3B,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,aAAa,EAAE,CAAA;CAC1B;AAQD,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CA6FvE;AAID,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,cAAc,GACxB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA+G/B;AAoCD,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IACP,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAA;CACf,GACL,OAAO,CAAC,WAAW,CAAC,CAsDtB"}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature Carver for evalbuff v2.
|
|
3
|
+
*
|
|
4
|
+
* Uses Codex agents to:
|
|
5
|
+
* 1. Analyze a codebase to identify discrete, self-contained features
|
|
6
|
+
* 2. Carve each feature out in an isolated git worktree, running typecheck/tests to verify
|
|
7
|
+
* 3. Capture the real git diff as the ground truth
|
|
8
|
+
*/
|
|
9
|
+
import { execSync } from 'child_process';
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { Codex } from '@openai/codex-sdk';
|
|
13
|
+
// --- Constants ---
|
|
14
|
+
const RESULT_FILE = 'evalbuff-carve-result.json';
|
|
15
|
+
// --- Phase 1: Identify features to carve (Codex agent) ---
|
|
16
|
+
export async function planFeatures(repoPath) {
|
|
17
|
+
const codex = new Codex({
|
|
18
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
19
|
+
});
|
|
20
|
+
const thread = codex.startThread({
|
|
21
|
+
model: 'gpt-5.4',
|
|
22
|
+
workingDirectory: repoPath,
|
|
23
|
+
approvalPolicy: 'never',
|
|
24
|
+
sandboxMode: 'read-only',
|
|
25
|
+
webSearchMode: 'live',
|
|
26
|
+
modelReasoningEffort: 'high',
|
|
27
|
+
});
|
|
28
|
+
console.log('Planning features to carve...');
|
|
29
|
+
const prompt = `You are an expert software architect. Analyze this codebase to identify 15-25 discrete, self-contained features that can be cleanly "carved out" (deleted) and used as coding evaluation tasks.
|
|
30
|
+
|
|
31
|
+
Explore the codebase thoroughly — read the file tree, key config files, entry points, and source files to understand the architecture.
|
|
32
|
+
|
|
33
|
+
## What makes a GOOD carve candidate
|
|
34
|
+
|
|
35
|
+
- A React component + its usage sites + unit tests + docs
|
|
36
|
+
- An API endpoint (route + handler + types + unit tests + docs)
|
|
37
|
+
- A CLI subcommand or flag
|
|
38
|
+
- A utility module used in a few places
|
|
39
|
+
- A feature behind a config/flag including tests and docs
|
|
40
|
+
- A test suite for a specific module
|
|
41
|
+
- A middleware or plugin
|
|
42
|
+
- An integration with an external service
|
|
43
|
+
|
|
44
|
+
Each feature should:
|
|
45
|
+
1. Be self-contained — removing it leaves the rest of the codebase functional
|
|
46
|
+
2. Be describable in 1-2 sentences — a developer could ask for it naturally
|
|
47
|
+
3. Be non-trivial but bounded — not a one-liner, but not "rewrite the whole app"
|
|
48
|
+
4. Not overlap with other candidates
|
|
49
|
+
|
|
50
|
+
## What makes a BAD candidate
|
|
51
|
+
|
|
52
|
+
- Core infrastructure that everything depends on (routing, auth framework, database connection)
|
|
53
|
+
- A single function that's called in 50 places
|
|
54
|
+
- Trivially small changes (rename, config tweak)
|
|
55
|
+
- Auto-generated or boilerplate code
|
|
56
|
+
|
|
57
|
+
## Output
|
|
58
|
+
|
|
59
|
+
After your analysis, write a file called \`${RESULT_FILE}\` with this JSON structure:
|
|
60
|
+
|
|
61
|
+
\`\`\`json
|
|
62
|
+
{
|
|
63
|
+
"reasoning": "Your analysis of the codebase and approach to selecting features",
|
|
64
|
+
"candidates": [
|
|
65
|
+
{
|
|
66
|
+
"id": "short-kebab-id",
|
|
67
|
+
"name": "Human readable name",
|
|
68
|
+
"prompt": "Natural prompt a developer would use to ask for this feature, 1-2 sentences",
|
|
69
|
+
"description": "What this feature does and why it exists",
|
|
70
|
+
"files": ["path/to/file1.ts", "path/to/file2.tsx"],
|
|
71
|
+
"relevantFiles": ["path/to/importer.ts"],
|
|
72
|
+
"complexity": "small|medium|large"
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
\`\`\`
|
|
77
|
+
|
|
78
|
+
- **files**: The files that ARE the feature (to be deleted or modified to remove it). Be thorough — missing a file means the carve won't be clean.
|
|
79
|
+
- **relevantFiles**: Other files that import or reference the feature.
|
|
80
|
+
|
|
81
|
+
You MUST write the result file as your last action.`;
|
|
82
|
+
const result = await thread.run(prompt);
|
|
83
|
+
// Read the result file
|
|
84
|
+
const resultPath = path.join(repoPath, RESULT_FILE);
|
|
85
|
+
if (!fs.existsSync(resultPath)) {
|
|
86
|
+
// Try to extract from the agent's final response
|
|
87
|
+
const jsonMatch = result.finalResponse.match(/\{[\s\S]*"candidates"[\s\S]*\}/);
|
|
88
|
+
if (jsonMatch) {
|
|
89
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
90
|
+
console.log(`Identified ${parsed.candidates.length} carve candidates (from response)`);
|
|
91
|
+
return parsed;
|
|
92
|
+
}
|
|
93
|
+
throw new Error('Codex agent did not produce a result file');
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
const raw = fs.readFileSync(resultPath, 'utf-8');
|
|
97
|
+
const parsed = JSON.parse(raw);
|
|
98
|
+
console.log(`Identified ${parsed.candidates.length} carve candidates`);
|
|
99
|
+
return parsed;
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
fs.rmSync(resultPath, { force: true });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// --- Phase 2: Carve a feature in an isolated worktree ---
|
|
106
|
+
export async function carveFeature(repoPath, candidate) {
|
|
107
|
+
console.log(` Carving feature: ${candidate.id}...`);
|
|
108
|
+
// Save original files before carving
|
|
109
|
+
const originalFiles = {};
|
|
110
|
+
for (const filePath of candidate.files) {
|
|
111
|
+
const fullPath = path.join(repoPath, filePath);
|
|
112
|
+
if (fs.existsSync(fullPath)) {
|
|
113
|
+
originalFiles[filePath] = fs.readFileSync(fullPath, 'utf-8');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Create a git worktree for isolated carving
|
|
117
|
+
const worktreePath = `${repoPath}-carve-${candidate.id}`;
|
|
118
|
+
const branchName = `evalbuff-carve-${candidate.id}-${Date.now()}`;
|
|
119
|
+
try {
|
|
120
|
+
execSync(`git worktree add -b "${branchName}" "${worktreePath}" HEAD`, {
|
|
121
|
+
cwd: repoPath,
|
|
122
|
+
stdio: 'ignore',
|
|
123
|
+
});
|
|
124
|
+
// Run the Codex agent in the worktree to carve the feature
|
|
125
|
+
const codex = new Codex({
|
|
126
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
127
|
+
});
|
|
128
|
+
const thread = codex.startThread({
|
|
129
|
+
model: 'gpt-5.4',
|
|
130
|
+
workingDirectory: worktreePath,
|
|
131
|
+
approvalPolicy: 'never',
|
|
132
|
+
sandboxMode: 'workspace-write',
|
|
133
|
+
webSearchMode: 'live',
|
|
134
|
+
modelReasoningEffort: 'high',
|
|
135
|
+
});
|
|
136
|
+
const prompt = `You are a precise code surgeon. Your job is to cleanly remove the following feature from this codebase.
|
|
137
|
+
|
|
138
|
+
## Feature to Remove
|
|
139
|
+
**Name:** ${candidate.name}
|
|
140
|
+
**Description:** ${candidate.description}
|
|
141
|
+
|
|
142
|
+
**Feature files (to delete or modify):** ${candidate.files.join(', ')}
|
|
143
|
+
**Other relevant files to check for references:** ${candidate.relevantFiles?.join(', ') || '(none)'}
|
|
144
|
+
|
|
145
|
+
## Rules
|
|
146
|
+
|
|
147
|
+
1. **Delete completely** — remove ALL code related to the feature: components, handlers, types, tests, docs, imports, route registrations, etc.
|
|
148
|
+
2. **Don't break the rest** — the remaining code must still compile and pass tests. Fix imports, remove dead references, etc.
|
|
149
|
+
3. **Minimal collateral** — only remove what's necessary. Don't "improve" or refactor surrounding code.
|
|
150
|
+
4. **Be thorough** — search for references in other files. If file A imports something from the feature, update file A's imports.
|
|
151
|
+
5. **Verify your work** — after making changes, run the typecheck command (check package.json for the right command, typically \`tsc --noEmit\` or \`npx tsc --noEmit\`). Fix any errors that result from your changes. Also run the test suite if one exists.
|
|
152
|
+
|
|
153
|
+
## Process
|
|
154
|
+
|
|
155
|
+
1. Read the feature files and understand what to remove
|
|
156
|
+
2. Search for all references/imports of the feature across the codebase
|
|
157
|
+
3. Delete feature-only files, edit shared files to remove feature code
|
|
158
|
+
4. Run typecheck and fix any compilation errors
|
|
159
|
+
5. Run tests if available and fix any failures caused by the removal (remove tests for the deleted feature, fix tests that referenced it)
|
|
160
|
+
|
|
161
|
+
Do NOT create any result files — just make the edits directly.`;
|
|
162
|
+
await thread.run(prompt);
|
|
163
|
+
// Capture the diff
|
|
164
|
+
execSync('git add -A', { cwd: worktreePath, stdio: 'ignore' });
|
|
165
|
+
const diff = execSync('git diff --cached HEAD', {
|
|
166
|
+
cwd: worktreePath,
|
|
167
|
+
encoding: 'utf-8',
|
|
168
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
169
|
+
});
|
|
170
|
+
if (!diff.trim()) {
|
|
171
|
+
console.warn(` No changes made for ${candidate.id}`);
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
// Build operations from the actual git diff
|
|
175
|
+
const operations = buildOperationsFromDiff(worktreePath, repoPath, candidate.files);
|
|
176
|
+
console.log(` Carved ${candidate.id}: ${operations.length} file operations, ${diff.split('\n').length} diff lines`);
|
|
177
|
+
return {
|
|
178
|
+
id: candidate.id,
|
|
179
|
+
prompt: candidate.prompt,
|
|
180
|
+
description: candidate.description,
|
|
181
|
+
complexity: candidate.complexity,
|
|
182
|
+
originalFiles,
|
|
183
|
+
operations,
|
|
184
|
+
diff,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
189
|
+
console.error(` Failed to carve ${candidate.id}: ${msg.slice(0, 200)}`);
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
finally {
|
|
193
|
+
// Clean up worktree and branch
|
|
194
|
+
try {
|
|
195
|
+
execSync(`git worktree remove --force "${worktreePath}"`, {
|
|
196
|
+
cwd: repoPath,
|
|
197
|
+
stdio: 'ignore',
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
catch { /* ignore */ }
|
|
201
|
+
try {
|
|
202
|
+
execSync(`git branch -D "${branchName}"`, {
|
|
203
|
+
cwd: repoPath,
|
|
204
|
+
stdio: 'ignore',
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
catch { /* ignore */ }
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Build FileOperation[] by comparing worktree state against the original repo.
|
|
212
|
+
*/
|
|
213
|
+
function buildOperationsFromDiff(worktreePath, repoPath, featureFiles) {
|
|
214
|
+
const operations = [];
|
|
215
|
+
// Get list of changed files from git
|
|
216
|
+
const statusOutput = execSync('git diff --cached --name-status HEAD', {
|
|
217
|
+
cwd: worktreePath,
|
|
218
|
+
encoding: 'utf-8',
|
|
219
|
+
});
|
|
220
|
+
for (const line of statusOutput.trim().split('\n')) {
|
|
221
|
+
if (!line.trim())
|
|
222
|
+
continue;
|
|
223
|
+
const [status, ...pathParts] = line.split('\t');
|
|
224
|
+
const filePath = pathParts.join('\t');
|
|
225
|
+
if (status === 'D') {
|
|
226
|
+
operations.push({ path: filePath, action: 'delete' });
|
|
227
|
+
}
|
|
228
|
+
else if (status === 'M' || status === 'A') {
|
|
229
|
+
const newContent = fs.readFileSync(path.join(worktreePath, filePath), 'utf-8');
|
|
230
|
+
operations.push({ path: filePath, action: 'modify', newContent });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return operations;
|
|
234
|
+
}
|
|
235
|
+
// --- Main orchestrator ---
|
|
236
|
+
export async function carveFeatures(repoPath, options = {}) {
|
|
237
|
+
const { count = 10, outputPath } = options;
|
|
238
|
+
console.log(`\nCarving features from: ${repoPath}`);
|
|
239
|
+
console.log(`Target: ${count} features\n`);
|
|
240
|
+
// Phase 1: Plan
|
|
241
|
+
const plan = await planFeatures(repoPath);
|
|
242
|
+
console.log(`\nPlanning complete. Reasoning:\n${plan.reasoning}\n`);
|
|
243
|
+
console.log('Candidates:');
|
|
244
|
+
for (const c of plan.candidates) {
|
|
245
|
+
console.log(` ${c.id} (${c.complexity}): ${c.name}`);
|
|
246
|
+
console.log(` Prompt: ${c.prompt}`);
|
|
247
|
+
console.log(` Files: ${c.files.join(', ')}`);
|
|
248
|
+
}
|
|
249
|
+
// Select top N candidates (prefer medium complexity)
|
|
250
|
+
const ranked = [...plan.candidates].sort((a, b) => {
|
|
251
|
+
const complexityOrder = { medium: 0, small: 1, large: 2 };
|
|
252
|
+
return complexityOrder[a.complexity] - complexityOrder[b.complexity];
|
|
253
|
+
});
|
|
254
|
+
const selected = ranked.slice(0, count);
|
|
255
|
+
console.log(`\nSelected ${selected.length} features for carving:\n`);
|
|
256
|
+
// Phase 2: Carve each feature
|
|
257
|
+
const features = [];
|
|
258
|
+
for (const candidate of selected) {
|
|
259
|
+
try {
|
|
260
|
+
const carved = await carveFeature(repoPath, candidate);
|
|
261
|
+
if (carved) {
|
|
262
|
+
features.push(carved);
|
|
263
|
+
console.log(` Done: ${carved.id} — ${carved.operations.length} file operations`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
console.error(` Failed: ${candidate.id}:`, error);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const result = {
|
|
271
|
+
repoPath,
|
|
272
|
+
generationDate: new Date().toISOString(),
|
|
273
|
+
features,
|
|
274
|
+
};
|
|
275
|
+
// Save output
|
|
276
|
+
const outPath = outputPath ||
|
|
277
|
+
path.join(repoPath, `carve-${new Date().toISOString().slice(0, 10)}.json`);
|
|
278
|
+
fs.writeFileSync(outPath, JSON.stringify(result, null, 2));
|
|
279
|
+
console.log(`\nSaved ${features.length} carved features to: ${outPath}`);
|
|
280
|
+
return result;
|
|
281
|
+
}
|
|
282
|
+
// --- CLI ---
|
|
283
|
+
if (import.meta.main) {
|
|
284
|
+
const args = process.argv.slice(2);
|
|
285
|
+
const getArg = (name, defaultValue) => {
|
|
286
|
+
const idx = args.indexOf(`--${name}`);
|
|
287
|
+
if (idx >= 0 && idx + 1 < args.length)
|
|
288
|
+
return args[idx + 1];
|
|
289
|
+
if (defaultValue !== undefined)
|
|
290
|
+
return defaultValue;
|
|
291
|
+
throw new Error(`Missing required argument: --${name}`);
|
|
292
|
+
};
|
|
293
|
+
const repoPath = getArg('repo');
|
|
294
|
+
const count = parseInt(getArg('count', '10'));
|
|
295
|
+
const outputPath = args.indexOf('--output') >= 0 ? getArg('output') : undefined;
|
|
296
|
+
carveFeatures(repoPath, { count, outputPath })
|
|
297
|
+
.then((result) => {
|
|
298
|
+
console.log(`\nDone! Carved ${result.features.length} features.`);
|
|
299
|
+
})
|
|
300
|
+
.catch((error) => {
|
|
301
|
+
console.error('Carving failed:', error);
|
|
302
|
+
process.exit(1);
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=carve-features.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"carve-features.js","sourceRoot":"","sources":["../src/carve-features.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AA4CzC,oBAAoB;AAEpB,MAAM,WAAW,GAAG,4BAA4B,CAAA;AAEhD,4DAA4D;AAE5D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACtB,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;KACnC,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC;QAC/B,KAAK,EAAE,SAAS;QAChB,gBAAgB,EAAE,QAAQ;QAC1B,cAAc,EAAE,OAAO;QACvB,WAAW,EAAE,WAAW;QACxB,aAAa,EAAE,MAAM;QACrB,oBAAoB,EAAE,MAAM;KAC7B,CAAC,CAAA;IAEF,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAA;IAE5C,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6CA8B4B,WAAW;;;;;;;;;;;;;;;;;;;;;;oDAsBJ,CAAA;IAElD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAEvC,uBAAuB;IACvB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAA;IACnD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,iDAAiD;QACjD,MAAM,SAAS,GAAG,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAA;QAC9E,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAc,CAAA;YACpD,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,UAAU,CAAC,MAAM,mCAAmC,CAAC,CAAA;YACtF,OAAO,MAAM,CAAA;QACf,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAC9D,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAc,CAAA;QAC3C,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,UAAU,CAAC,MAAM,mBAAmB,CAAC,CAAA;QACtE,OAAO,MAAM,CAAA;IACf,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACxC,CAAC;AACH,CAAC;AAED,2DAA2D;AAE3D,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAgB,EAChB,SAAyB;IAEzB,OAAO,CAAC,GAAG,CAAC,sBAAsB,SAAS,CAAC,EAAE,KAAK,CAAC,CAAA;IAEpD,qCAAqC;IACrC,MAAM,aAAa,GAA2B,EAAE,CAAA;IAChD,KAAK,MAAM,QAAQ,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;QAC9C,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,aAAa,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QAC9D,CAAC;IACH,CAAC;IAED,6CAA6C;IAC7C,MAAM,YAAY,GAAG,GAAG,QAAQ,UAAU,SAAS,CAAC,EAAE,EAAE,CAAA;IACxD,MAAM,UAAU,GAAG,kBAAkB,SAAS,CAAC,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAA;IAEjE,IAAI,CAAC;QACH,QAAQ,CAAC,wBAAwB,UAAU,MAAM,YAAY,QAAQ,EAAE;YACrE,GAAG,EAAE,QAAQ;YACb,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAA;QAEF,2DAA2D;QAC3D,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;YACtB,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;SACnC,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC;YAC/B,KAAK,EAAE,SAAS;YAChB,gBAAgB,EAAE,YAAY;YAC9B,cAAc,EAAE,OAAO;YACvB,WAAW,EAAE,iBAAiB;YAC9B,aAAa,EAAE,MAAM;YACrB,oBAAoB,EAAE,MAAM;SAC7B,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG;;;YAGP,SAAS,CAAC,IAAI;mBACP,SAAS,CAAC,WAAW;;2CAEG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;oDACjB,SAAS,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ;;;;;;;;;;;;;;;;;;+DAkBpC,CAAA;QAE3D,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAExB,mBAAmB;QACnB,QAAQ,CAAC,YAAY,EAAE,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC9D,MAAM,IAAI,GAAG,QAAQ,CAAC,wBAAwB,EAAE;YAC9C,GAAG,EAAE,YAAY;YACjB,QAAQ,EAAE,OAAO;YACjB,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;SAC5B,CAAC,CAAA;QAEF,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,yBAAyB,SAAS,CAAC,EAAE,EAAE,CAAC,CAAA;YACrD,OAAO,IAAI,CAAA;QACb,CAAC;QAED,4CAA4C;QAC5C,MAAM,UAAU,GAAG,uBAAuB,CAAC,YAAY,EAAE,QAAQ,EAAE,SAAS,CAAC,KAAK,CAAC,CAAA;QAEnF,OAAO,CAAC,GAAG,CAAC,YAAY,SAAS,CAAC,EAAE,KAAK,UAAU,CAAC,MAAM,qBAAqB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,aAAa,CAAC,CAAA;QAEpH,OAAO;YACL,EAAE,EAAE,SAAS,CAAC,EAAE;YAChB,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,WAAW,EAAE,SAAS,CAAC,WAAW;YAClC,UAAU,EAAE,SAAS,CAAC,UAAU;YAChC,aAAa;YACb,UAAU;YACV,IAAI;SACL,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAClE,OAAO,CAAC,KAAK,CAAC,qBAAqB,SAAS,CAAC,EAAE,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;QACxE,OAAO,IAAI,CAAA;IACb,CAAC;YAAS,CAAC;QACT,+BAA+B;QAC/B,IAAI,CAAC;YACH,QAAQ,CAAC,gCAAgC,YAAY,GAAG,EAAE;gBACxD,GAAG,EAAE,QAAQ;gBACb,KAAK,EAAE,QAAQ;aAChB,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QACxB,IAAI,CAAC;YACH,QAAQ,CAAC,kBAAkB,UAAU,GAAG,EAAE;gBACxC,GAAG,EAAE,QAAQ;gBACb,KAAK,EAAE,QAAQ;aAChB,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAC9B,YAAoB,EACpB,QAAgB,EAChB,YAAsB;IAEtB,MAAM,UAAU,GAAoB,EAAE,CAAA;IAEtC,qCAAqC;IACrC,MAAM,YAAY,GAAG,QAAQ,CAAC,sCAAsC,EAAE;QACpE,GAAG,EAAE,YAAY;QACjB,QAAQ,EAAE,OAAO;KAClB,CAAC,CAAA;IAEF,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,SAAQ;QAC1B,MAAM,CAAC,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC/C,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAErC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAA;QACvD,CAAC;aAAM,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5C,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAA;YAC9E,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAA;QACnE,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,4BAA4B;AAE5B,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAgB,EAChB,UAGI,EAAE;IAEN,MAAM,EAAE,KAAK,GAAG,EAAE,EAAE,UAAU,EAAE,GAAG,OAAO,CAAA;IAE1C,OAAO,CAAC,GAAG,CAAC,4BAA4B,QAAQ,EAAE,CAAC,CAAA;IACnD,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,aAAa,CAAC,CAAA;IAE1C,gBAAgB;IAChB,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAA;IAEzC,OAAO,CAAC,GAAG,CAAC,oCAAoC,IAAI,CAAC,SAAS,IAAI,CAAC,CAAA;IACnE,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;IAC1B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,UAAU,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;QACrD,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,MAAM,EAAE,CAAC,CAAA;QACtC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACjD,CAAC;IAED,qDAAqD;IACrD,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAChD,MAAM,eAAe,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;QACzD,OAAO,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC,CAAA;IACtE,CAAC,CAAC,CAAA;IACF,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IAEvC,OAAO,CAAC,GAAG,CAAC,cAAc,QAAQ,CAAC,MAAM,0BAA0B,CAAC,CAAA;IAEpE,8BAA8B;IAC9B,MAAM,QAAQ,GAAoB,EAAE,CAAA;IACpC,KAAK,MAAM,SAAS,IAAI,QAAQ,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;YACtD,IAAI,MAAM,EAAE,CAAC;gBACX,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;gBACrB,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC,UAAU,CAAC,MAAM,kBAAkB,CAAC,CAAA;YACnF,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,aAAa,SAAS,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;QACpD,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAgB;QAC1B,QAAQ;QACR,cAAc,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACxC,QAAQ;KACT,CAAA;IAED,cAAc;IACd,MAAM,OAAO,GACX,UAAU;QACV,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAA;IAC5E,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;IAC1D,OAAO,CAAC,GAAG,CAAC,WAAW,QAAQ,CAAC,MAAM,wBAAwB,OAAO,EAAE,CAAC,CAAA;IAExE,OAAO,MAAM,CAAA;AACf,CAAC;AAED,cAAc;AAEd,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACrB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAElC,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,YAAqB,EAAU,EAAE;QAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;QACrC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;QAC3D,IAAI,YAAY,KAAK,SAAS;YAAE,OAAO,YAAY,CAAA;QACnD,MAAM,IAAI,KAAK,CAAC,gCAAgC,IAAI,EAAE,CAAC,CAAA;IACzD,CAAC,CAAA;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;IAC/B,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAA;IAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAE/E,aAAa,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;SAC3C,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;QACf,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,CAAC,QAAQ,CAAC,MAAM,YAAY,CAAC,CAAA;IACnE,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACf,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAA;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC,CAAC,CAAA;AACN,CAAC"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Evalbuff CLI entry point.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* evalbuff --repo /path/to/repo [--n 20] [--parallelism 10] [--loops 3]
|
|
7
|
+
* [--init-command "npm install"] [--coding-model sonnet] [--docs-model opus]
|
|
8
|
+
* [--cached-features /path/to/features.json]
|
|
9
|
+
*/
|
|
10
|
+
import { runEvalbuff } from './run-evalbuff';
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
const getArg = (name, defaultValue) => {
|
|
13
|
+
const idx = args.indexOf(`--${name}`);
|
|
14
|
+
if (idx >= 0 && idx + 1 < args.length)
|
|
15
|
+
return args[idx + 1];
|
|
16
|
+
if (defaultValue !== undefined)
|
|
17
|
+
return defaultValue;
|
|
18
|
+
throw new Error(`Missing required argument: --${name}`);
|
|
19
|
+
};
|
|
20
|
+
const hasArg = (name) => args.includes(`--${name}`);
|
|
21
|
+
const repoPath = getArg('repo');
|
|
22
|
+
const n = parseInt(getArg('n', '20'));
|
|
23
|
+
const parallelism = parseInt(getArg('parallelism', '10'));
|
|
24
|
+
const loops = parseInt(getArg('loops', '3'));
|
|
25
|
+
const initCommand = hasArg('init-command') ? getArg('init-command') : undefined;
|
|
26
|
+
const codingModel = getArg('coding-model', 'sonnet');
|
|
27
|
+
const docsModel = getArg('docs-model', 'opus');
|
|
28
|
+
const cachedFeatures = hasArg('cached-features') ? getArg('cached-features') : undefined;
|
|
29
|
+
runEvalbuff({
|
|
30
|
+
repoPath,
|
|
31
|
+
n,
|
|
32
|
+
parallelism,
|
|
33
|
+
loops,
|
|
34
|
+
initCommand,
|
|
35
|
+
codingModel,
|
|
36
|
+
docsModel,
|
|
37
|
+
cachedFeatures,
|
|
38
|
+
}).catch((error) => {
|
|
39
|
+
console.error('Evalbuff run failed:', error);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AAElC,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,YAAqB,EAAU,EAAE;IAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;IACrC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;IAC3D,IAAI,YAAY,KAAK,SAAS;QAAE,OAAO,YAAY,CAAA;IACnD,MAAM,IAAI,KAAK,CAAC,gCAAgC,IAAI,EAAE,CAAC,CAAA;AACzD,CAAC,CAAA;AACD,MAAM,MAAM,GAAG,CAAC,IAAY,EAAW,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;AAEpE,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;AAC/B,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAA;AACrC,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,CAAA;AACzD,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAA;AAC5C,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AAC/E,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAA;AACpD,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;AAC9C,MAAM,cAAc,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AAExF,WAAW,CAAC;IACV,QAAQ;IACR,CAAC;IACD,WAAW;IACX,KAAK;IACL,WAAW;IACX,WAAW;IACX,SAAS;IACT,cAAc;CACf,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAA;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { TaskResult } from './eval-runner';
|
|
2
|
+
export declare function collectDocSuggestions(tasks: TaskResult[]): string;
|
|
3
|
+
export declare function runDocsRefactorAgent(repoPath: string, judgeSuggestions: string, model: string): Promise<void>;
|
|
4
|
+
//# sourceMappingURL=docs-refactor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs-refactor.d.ts","sourceRoot":"","sources":["../src/docs-refactor.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE/C,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,CAcjE;AAED,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,gBAAgB,EAAE,MAAM,EACxB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAwGf"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { ClaudeRunner } from './runners/claude';
|
|
6
|
+
import { syncDocsIntoRepo } from './eval-helpers';
|
|
7
|
+
export function collectDocSuggestions(tasks) {
|
|
8
|
+
const sections = [];
|
|
9
|
+
for (const task of tasks) {
|
|
10
|
+
const suggestions = task.judging.docSuggestions;
|
|
11
|
+
if (!suggestions || suggestions.length === 0)
|
|
12
|
+
continue;
|
|
13
|
+
sections.push(`### ${task.featureId} (score: ${task.score.toFixed(1)}/10)\n` +
|
|
14
|
+
suggestions.map((s) => `- ${s}`).join('\n'));
|
|
15
|
+
}
|
|
16
|
+
return sections.join('\n\n');
|
|
17
|
+
}
|
|
18
|
+
export async function runDocsRefactorAgent(repoPath, judgeSuggestions, model) {
|
|
19
|
+
console.log(`\n [DocsRefactor] Running holistic docs refactor...`);
|
|
20
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'evalbuff-docs-'));
|
|
21
|
+
const repoDir = path.join(tempDir, 'repo');
|
|
22
|
+
const prompt = `Read ALL existing documentation (docs/, AGENTS.md, CLAUDE.md), consider the judge suggestions below, and make the documentation as useful as possible for coding agents.
|
|
23
|
+
|
|
24
|
+
## Goal
|
|
25
|
+
|
|
26
|
+
The purpose of these docs is to help a coding agent successfully build NEW features it has never seen before. The docs should teach the agent how the project works — its architecture, patterns, conventions, and rules — so it can confidently build anything, not just reconstruct specific existing features.
|
|
27
|
+
|
|
28
|
+
## Judge Suggestions
|
|
29
|
+
|
|
30
|
+
Multiple judge agents reviewed coding agent attempts and identified documentation gaps. Here are their suggestions:
|
|
31
|
+
|
|
32
|
+
${judgeSuggestions || '(No suggestions were made)'}
|
|
33
|
+
|
|
34
|
+
## What to do
|
|
35
|
+
|
|
36
|
+
1. **Extract general patterns** — each judge suggestion reflects a specific failure, but your job is to identify the underlying pattern or convention that would prevent a whole class of similar failures. Ask: "What general rule would help an agent get this right for ANY feature?"
|
|
37
|
+
2. **Do NOT reference specific features** — never mention a specific feature, component, or endpoint by name as an example of what to build. Instead, document the pattern it follows. For example, instead of "the UserProfile component fetches data in useEffect", write "components in this project fetch data using useEffect on mount, following the pattern in src/hooks/".
|
|
38
|
+
3. **Document architecture and data flow** — describe how the project is structured, how data flows through it, and where new code should be placed. These are the things an agent building something new needs most.
|
|
39
|
+
4. **Edit existing docs** — when a suggestion maps to an existing doc, make fine-grained edits rather than rewriting from scratch.
|
|
40
|
+
5. **Create new docs** — when a suggestion identifies a missing pattern or convention, create a concise new doc for it.
|
|
41
|
+
6. **Merge overlapping docs** — if multiple suggestions or existing docs cover similar topics, combine them.
|
|
42
|
+
7. **Remove redundancy** — consolidate duplicate advice. Dense, actionable information beats verbose explanations.
|
|
43
|
+
8. **Fix contradictions** — if docs disagree, pick the correct advice and remove the wrong one.
|
|
44
|
+
9. **Prune stale docs** — remove docs that reference files/patterns that no longer exist in the codebase.
|
|
45
|
+
|
|
46
|
+
Rules:
|
|
47
|
+
- ONLY modify files in docs/, AGENTS.md, or CLAUDE.md. Do NOT modify source code.
|
|
48
|
+
- **Do NOT edit AGENTS.md beyond adding new docs to its index.** The only allowed changes to AGENTS.md are: (a) adding/removing entries in the doc index when you create or delete files under docs/, and (b) correcting existing information that is factually wrong. Do NOT add new paragraphs, prose, sections, or explanatory text above or below existing content. Put all new guidance in docs/ files and link to them from the index.
|
|
49
|
+
- It's OK to delete doc files that are redundant or low-value.
|
|
50
|
+
- The goal is a minimal, high-signal set of docs that a coding agent can use to build ANY feature, including ones that don't exist yet.
|
|
51
|
+
- Less is more — 5 great docs are better than 15 mediocre ones.
|
|
52
|
+
- Document patterns, conventions, and architectural rules — not specific feature implementations.
|
|
53
|
+
- Be specific about file paths, directory structure, and conventions — but generic about what gets built.
|
|
54
|
+
|
|
55
|
+
## Docs Must Match Source Code
|
|
56
|
+
|
|
57
|
+
Docs that describe nonexistent code are WORSE than no docs at all — they actively mislead coding agents and cause them to fail.
|
|
58
|
+
|
|
59
|
+
Before writing any doc that references a helper, function, type, or script:
|
|
60
|
+
1. **grep for the exact symbol name** to confirm it exists. If it doesn't exist, DO NOT document it.
|
|
61
|
+
2. **Never document aspirational/future behavior.** Only document what the code does RIGHT NOW.
|
|
62
|
+
3. **If a judge suggestion references a helper that doesn't exist**, document the PATTERN the agent should follow instead — not a fictional API.
|
|
63
|
+
|
|
64
|
+
Wrong: "Use \`captureGitDiff()\` from src/eval-helpers.ts to capture diffs" (if it doesn't exist)
|
|
65
|
+
Right: "Diff capture should use an explicit base SHA recorded before the agent runs" (describes the pattern)
|
|
66
|
+
|
|
67
|
+
## Final Step: Spawn a Critique Sub-Agent
|
|
68
|
+
|
|
69
|
+
Before you finish, you MUST spawn a critique sub-agent via the Task tool (subagent_type: "general-purpose") to review the docs you just wrote or modified. Then apply every valid fix it identifies.
|
|
70
|
+
|
|
71
|
+
Use this exact prompt for the sub-agent:
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
You are a documentation critic. Review every file under docs/, plus AGENTS.md and CLAUDE.md, and report violations of the rules below. For each violation, give the file path, the offending text or line range, and a concrete fix (exact replacement text, the section to remove, or the split to perform).
|
|
75
|
+
|
|
76
|
+
Rules (enforce strictly):
|
|
77
|
+
|
|
78
|
+
1. **No overfitting to a single task.** Docs must describe general patterns, conventions, and architecture that apply to building ANY feature — not one specific task. Flag:
|
|
79
|
+
- Feature-specific function, type, component, endpoint, table, or CLI-subcommand names that only matter for one task and are not shared infrastructure.
|
|
80
|
+
- Examples phrased around one feature ("the UserProfile component fetches data via useEffect") instead of the general pattern ("components in src/components/ fetch data in useEffect on mount").
|
|
81
|
+
- Any symbol reference that does not represent a shared utility, pattern, or architectural boundary used by multiple features.
|
|
82
|
+
The fix is to rewrite the passage as a general rule about the pattern, directory, or convention — or delete it if it does not generalize.
|
|
83
|
+
|
|
84
|
+
2. **No code excerpts unless documenting a common utility or shared pattern.** A code block is only allowed when it shows:
|
|
85
|
+
- The signature or usage of a shared helper multiple features rely on, OR
|
|
86
|
+
- A canonical pattern every agent should copy (error handling, a standard import shape, etc.).
|
|
87
|
+
Flag any code block that shows task-specific implementation details. The fix is to delete the block or replace it with a one-line prose description of the pattern.
|
|
88
|
+
|
|
89
|
+
3. **Individual markdown files must stay focused and reasonably short.** If any single file exceeds roughly 300 lines, OR covers multiple unrelated topics, recommend splitting it into smaller topic-scoped files and specify the split (new filenames + which sections move where). Prefer many small focused docs over one large doc.
|
|
90
|
+
|
|
91
|
+
4. **Docs must match source code.** Before flagging a missing symbol, grep the repo to confirm it does not exist. Flag references to helpers, functions, types, files, or scripts that are not present in the code.
|
|
92
|
+
|
|
93
|
+
Return a numbered list of violations with fixes. If a file is clean, say so. Do not edit any files yourself — only report.
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
After the sub-agent returns, apply every valid fix it identified by editing the doc files directly. If it recommended splitting a long doc, perform the split. Re-read each affected file after fixing to confirm the result. Only then finish.`;
|
|
97
|
+
try {
|
|
98
|
+
execSync(`git clone --no-checkout "${repoPath}" "${repoDir}"`, { stdio: 'ignore' });
|
|
99
|
+
const headSha = execSync('git rev-parse HEAD', {
|
|
100
|
+
cwd: repoPath,
|
|
101
|
+
encoding: 'utf-8',
|
|
102
|
+
}).trim();
|
|
103
|
+
execSync(`git checkout ${headSha}`, { cwd: repoDir, stdio: 'ignore' });
|
|
104
|
+
syncDocsIntoRepo(repoPath, repoDir);
|
|
105
|
+
const runner = new ClaudeRunner(repoDir, {}, model, 'high');
|
|
106
|
+
await runner.run(prompt);
|
|
107
|
+
syncDocsIntoRepo(repoDir, repoPath);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
111
|
+
console.warn(` [DocsRefactor] Failed: ${msg.slice(0, 200)}`);
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
try {
|
|
115
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// ignore cleanup failures
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=docs-refactor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs-refactor.js","sourceRoot":"","sources":["../src/docs-refactor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { TaskResult } from './eval-runner';
|
|
2
|
+
export declare function collectDocSuggestions(tasks: TaskResult[]): string;
|
|
3
|
+
export declare function runDocsWriterAgent(repoPath: string, judgeSuggestions: string, model: string): Promise<void>;
|
|
4
|
+
//# sourceMappingURL=docs-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs-writer.d.ts","sourceRoot":"","sources":["../src/docs-writer.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE/C,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,CAcjE;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,gBAAgB,EAAE,MAAM,EACxB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAwGf"}
|