Skip to content

Commit 17e8b5e

Browse files
author
StackMemory Bot (CLI)
committed
feat(gepa): --auto-apply flag for autonomous prompt deployment
2 parents b9cedca + eba41c0 commit 17e8b5e

3 files changed

Lines changed: 35 additions & 5 deletions

File tree

CLAUDE.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ stackmemory conductor start # Autonomous Linear→worktree→agent orchestrat
8787
stackmemory conductor learn # Analyze agent outcomes (success rate, failure phases, error patterns)
8888
stackmemory conductor learn --evolve # Auto-mutate prompt template from failure data (GEPA)
8989
stackmemory conductor status # Live agent status dashboard
90+
91+
# GEPA Optimizer (scripts/gepa/optimize.js)
92+
node scripts/gepa/optimize.js run [gens] [--auto-apply] # Full optimization loop
93+
node scripts/gepa/optimize.js score [--auto-apply] # Score variants, select best
94+
node scripts/gepa/optimize.js run --target skill:start # Optimize specific target
95+
node scripts/gepa/optimize.js mutate --auto-phase # Auto-detect worst phase
96+
# Flags: --auto-apply (deploy winner), --no-cache (fresh eval), --target <name>, --phase <name>
9097
stackmemory conductor monitor # Real-time TUI with phase tracking
9198
stackmemory conductor finalize # Clean up dead/stale agents
9299
stackmemory conductor traces <issue-id> # View conversation traces for an agent run

scripts/gepa/hooks/gepa-session-hook.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ function triggerOptimization(hookState) {
117117
const { execSync } = await import('child_process');
118118
try {
119119
execSync('node ${optimizePath} mutate --auto-phase', { stdio: 'pipe', timeout: 300000 });
120-
execSync('node ${optimizePath} score', { stdio: 'pipe', timeout: 300000 });
120+
execSync('node ${optimizePath} score --auto-apply', { stdio: 'pipe', timeout: 300000 });
121121
122122
// Read result and notify
123123
const fs = await import('fs');

scripts/gepa/optimize.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,18 @@
88
* node optimize.js init # Initialize with current CLAUDE.md
99
* node optimize.js mutate # Generate new variants
1010
* node optimize.js eval [variant] # Run evals on variant(s)
11-
* node optimize.js score # Score all variants in generation
11+
* node optimize.js score [--auto-apply] # Score all variants in generation
1212
* node optimize.js select # Select best, advance generation
13-
* node optimize.js run [generations] # Full optimization loop
13+
* node optimize.js run [gens] [--auto-apply] # Full optimization loop
1414
* node optimize.js status # Show current status
1515
* node optimize.js diff [a] [b] # Compare two variants
16+
*
17+
* Flags:
18+
* --auto-apply Apply winning variant to target file automatically
19+
* --no-cache Bypass eval response cache (force fresh eval)
20+
* --target <name> Optimize a specific target from config.targets[]
21+
* --phase <name> Phase-scoped mutation for conductor prompts
22+
* --auto-phase Auto-detect worst phase from outcomes.jsonl
1623
*/
1724

1825
import fs from 'fs';
@@ -96,6 +103,10 @@ const phaseIdx = process.argv.indexOf('--phase');
96103
const phaseName = phaseIdx !== -1 ? process.argv[phaseIdx + 1] : null;
97104
if (phaseIdx !== -1) process.argv.splice(phaseIdx, 2);
98105

106+
// --auto-apply: automatically apply winning variant when threshold is reached
107+
const autoApply = process.argv.includes('--auto-apply');
108+
if (autoApply) process.argv.splice(process.argv.indexOf('--auto-apply'), 1);
109+
99110
const CONDUCTOR_PROMPTS_DIR = path.join(
100111
process.env.HOME || '',
101112
'.stackmemory',
@@ -1630,7 +1641,14 @@ async function run(generations = config.evolution.generations) {
16301641
console.log(`Best variant: ${state.bestVariant}`);
16311642
console.log(`Best score: ${(state.bestScore * 100).toFixed(1)}%`);
16321643
console.log(`Generations: ${state.currentGeneration}`);
1633-
console.log(`\nTo apply: node optimize.js apply`);
1644+
1645+
// Auto-apply winning variant if flag set and improvement found
1646+
if (autoApply && state.bestVariant !== 'baseline') {
1647+
console.log(`\n[auto-apply] Deploying ${state.bestVariant} to target...`);
1648+
await apply();
1649+
} else {
1650+
console.log(`\nTo apply: node optimize.js apply`);
1651+
}
16341652
}
16351653

16361654
/**
@@ -2031,7 +2049,12 @@ switch (command) {
20312049
break;
20322050
case 'select':
20332051
case 'score':
2034-
scoreAndSelect();
2052+
scoreAndSelect().then((best) => {
2053+
if (autoApply && best && best.variant !== 'baseline') {
2054+
console.log(`\n[auto-apply] Deploying ${best.variant}...`);
2055+
return apply();
2056+
}
2057+
});
20352058
break;
20362059
case 'run':
20372060
run(parseInt(arg1) || config.evolution.generations);

0 commit comments

Comments
 (0)