wiggum-cli 0.16.0 → 0.17.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/bin/ralph.js +0 -0
- package/dist/agent/memory/ingest.d.ts +14 -0
- package/dist/agent/memory/ingest.js +77 -0
- package/dist/agent/memory/store.d.ts +15 -0
- package/dist/agent/memory/store.js +98 -0
- package/dist/agent/memory/types.d.ts +16 -0
- package/dist/agent/memory/types.js +14 -0
- package/dist/agent/orchestrator.d.ts +7 -0
- package/dist/agent/orchestrator.js +266 -0
- package/dist/agent/resolve-config.d.ts +26 -0
- package/dist/agent/resolve-config.js +43 -0
- package/dist/agent/tools/backlog.d.ts +27 -0
- package/dist/agent/tools/backlog.js +51 -0
- package/dist/agent/tools/dry-run.d.ts +106 -0
- package/dist/agent/tools/dry-run.js +119 -0
- package/dist/agent/tools/execution.d.ts +51 -0
- package/dist/agent/tools/execution.js +256 -0
- package/dist/agent/tools/feature-state.d.ts +43 -0
- package/dist/agent/tools/feature-state.js +184 -0
- package/dist/agent/tools/introspection.d.ts +23 -0
- package/dist/agent/tools/introspection.js +40 -0
- package/dist/agent/tools/memory.d.ts +44 -0
- package/dist/agent/tools/memory.js +99 -0
- package/dist/agent/tools/preflight.d.ts +7 -0
- package/dist/agent/tools/preflight.js +137 -0
- package/dist/agent/tools/reporting.d.ts +58 -0
- package/dist/agent/tools/reporting.js +119 -0
- package/dist/agent/tools/schemas.d.ts +2 -0
- package/dist/agent/tools/schemas.js +3 -0
- package/dist/agent/types.d.ts +45 -0
- package/dist/agent/types.js +1 -0
- package/dist/ai/conversation/conversation-manager.js +8 -0
- package/dist/ai/conversation/url-fetcher.js +27 -0
- package/dist/ai/providers.js +5 -5
- package/dist/commands/agent.d.ts +17 -0
- package/dist/commands/agent.js +114 -0
- package/dist/commands/monitor.js +50 -183
- package/dist/commands/new-auto.d.ts +15 -0
- package/dist/commands/new-auto.js +237 -0
- package/dist/commands/run.js +20 -10
- package/dist/commands/sync.d.ts +15 -0
- package/dist/commands/sync.js +68 -0
- package/dist/generator/config.d.ts +1 -41
- package/dist/generator/config.js +7 -0
- package/dist/generator/index.d.ts +2 -2
- package/dist/generator/templates.d.ts +2 -0
- package/dist/generator/templates.js +9 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +115 -4
- package/dist/repl/command-parser.d.ts +5 -0
- package/dist/repl/command-parser.js +5 -0
- package/dist/templates/prompts/PROMPT.md.tmpl +13 -10
- package/dist/templates/prompts/PROMPT_e2e.md.tmpl +13 -7
- package/dist/templates/prompts/PROMPT_feature.md.tmpl +16 -3
- package/dist/templates/prompts/PROMPT_review_auto.md.tmpl +32 -12
- package/dist/templates/prompts/PROMPT_review_manual.md.tmpl +4 -1
- package/dist/templates/prompts/PROMPT_review_merge.md.tmpl +39 -14
- package/dist/templates/prompts/PROMPT_verify.md.tmpl +5 -2
- package/dist/templates/scripts/feature-loop.sh.tmpl +441 -69
- package/dist/tui/app.d.ts +19 -2
- package/dist/tui/app.js +22 -4
- package/dist/tui/components/IssuePicker.d.ts +27 -0
- package/dist/tui/components/IssuePicker.js +64 -0
- package/dist/tui/components/RunCompletionSummary.js +6 -3
- package/dist/tui/hooks/useAgentOrchestrator.d.ts +29 -0
- package/dist/tui/hooks/useAgentOrchestrator.js +453 -0
- package/dist/tui/orchestration/interview-orchestrator.d.ts +5 -1
- package/dist/tui/orchestration/interview-orchestrator.js +27 -6
- package/dist/tui/screens/AgentScreen.d.ts +21 -0
- package/dist/tui/screens/AgentScreen.js +159 -0
- package/dist/tui/screens/InitScreen.js +4 -0
- package/dist/tui/screens/InterviewScreen.d.ts +3 -1
- package/dist/tui/screens/InterviewScreen.js +146 -10
- package/dist/tui/screens/MainShell.d.ts +1 -1
- package/dist/tui/screens/MainShell.js +36 -1
- package/dist/tui/screens/RunScreen.js +38 -6
- package/dist/tui/utils/build-run-summary.d.ts +1 -1
- package/dist/tui/utils/build-run-summary.js +40 -84
- package/dist/tui/utils/clear-screen.d.ts +14 -0
- package/dist/tui/utils/clear-screen.js +16 -0
- package/dist/tui/utils/loop-status.d.ts +41 -1
- package/dist/tui/utils/loop-status.js +243 -35
- package/dist/tui/utils/pr-summary.d.ts +3 -2
- package/dist/tui/utils/pr-summary.js +41 -6
- package/dist/utils/config.d.ts +8 -0
- package/dist/utils/config.js +8 -0
- package/dist/utils/github.d.ts +32 -0
- package/dist/utils/github.js +106 -0
- package/package.json +4 -1
- package/src/templates/prompts/PROMPT.md.tmpl +13 -10
- package/src/templates/prompts/PROMPT_e2e.md.tmpl +13 -7
- package/src/templates/prompts/PROMPT_feature.md.tmpl +16 -3
- package/src/templates/prompts/PROMPT_review_auto.md.tmpl +32 -12
- package/src/templates/prompts/PROMPT_review_manual.md.tmpl +4 -1
- package/src/templates/prompts/PROMPT_review_merge.md.tmpl +39 -14
- package/src/templates/prompts/PROMPT_verify.md.tmpl +5 -2
- package/src/templates/scripts/feature-loop.sh.tmpl +441 -69
|
@@ -3,47 +3,7 @@
|
|
|
3
3
|
* Generates ralph.config.cjs file from scan results
|
|
4
4
|
*/
|
|
5
5
|
import type { ScanResult } from '../scanner/types.js';
|
|
6
|
-
|
|
7
|
-
* Ralph configuration structure
|
|
8
|
-
*/
|
|
9
|
-
export interface RalphConfig {
|
|
10
|
-
name: string;
|
|
11
|
-
stack: {
|
|
12
|
-
framework: {
|
|
13
|
-
name: string;
|
|
14
|
-
version: string;
|
|
15
|
-
variant: string;
|
|
16
|
-
};
|
|
17
|
-
packageManager: string;
|
|
18
|
-
testing: {
|
|
19
|
-
unit: string;
|
|
20
|
-
e2e: string;
|
|
21
|
-
};
|
|
22
|
-
styling: string;
|
|
23
|
-
};
|
|
24
|
-
commands: {
|
|
25
|
-
dev: string;
|
|
26
|
-
build: string;
|
|
27
|
-
test: string;
|
|
28
|
-
lint: string;
|
|
29
|
-
typecheck: string;
|
|
30
|
-
};
|
|
31
|
-
paths: {
|
|
32
|
-
root: string;
|
|
33
|
-
prompts: string;
|
|
34
|
-
guides: string;
|
|
35
|
-
specs: string;
|
|
36
|
-
scripts: string;
|
|
37
|
-
learnings: string;
|
|
38
|
-
agents: string;
|
|
39
|
-
};
|
|
40
|
-
loop: {
|
|
41
|
-
maxIterations: number;
|
|
42
|
-
maxE2eAttempts: number;
|
|
43
|
-
defaultModel: string;
|
|
44
|
-
planningModel: string;
|
|
45
|
-
};
|
|
46
|
-
}
|
|
6
|
+
import type { RalphConfig } from '../utils/config.js';
|
|
47
7
|
/**
|
|
48
8
|
* Generate ralph config object from scan result
|
|
49
9
|
*/
|
package/dist/generator/config.js
CHANGED
|
@@ -10,6 +10,8 @@ export function generateConfig(scanResult, customVars = {}) {
|
|
|
10
10
|
const vars = extractVariables(scanResult, customVars);
|
|
11
11
|
const defaultModel = customVars.defaultModel || 'sonnet';
|
|
12
12
|
const planningModel = customVars.planningModel || 'opus';
|
|
13
|
+
const agentProvider = customVars.agentProvider || 'anthropic';
|
|
14
|
+
const agentModel = customVars.agentModel || 'claude-sonnet-4-6';
|
|
13
15
|
return {
|
|
14
16
|
name: vars.projectName,
|
|
15
17
|
stack: {
|
|
@@ -46,6 +48,11 @@ export function generateConfig(scanResult, customVars = {}) {
|
|
|
46
48
|
maxE2eAttempts: 5,
|
|
47
49
|
defaultModel,
|
|
48
50
|
planningModel,
|
|
51
|
+
reviewMode: 'manual',
|
|
52
|
+
},
|
|
53
|
+
agent: {
|
|
54
|
+
defaultProvider: agentProvider,
|
|
55
|
+
defaultModel: agentModel,
|
|
49
56
|
},
|
|
50
57
|
};
|
|
51
58
|
}
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { ScanResult } from '../scanner/types.js';
|
|
6
6
|
import { type TemplateVariables } from './templates.js';
|
|
7
|
-
import {
|
|
7
|
+
import type { RalphConfig } from '../utils/config.js';
|
|
8
8
|
import { type WriteSummary } from './writer.js';
|
|
9
9
|
export type { TemplateVariables } from './templates.js';
|
|
10
|
-
export type { RalphConfig } from '
|
|
10
|
+
export type { RalphConfig } from '../utils/config.js';
|
|
11
11
|
export type { WriteOptions, WriteSummary, WriteResult } from './writer.js';
|
|
12
12
|
export { extractVariables, processTemplate, processTemplateFile, getTemplatesDir, } from './templates.js';
|
|
13
13
|
export { generateConfig, generateConfigFile } from './config.js';
|
|
@@ -150,8 +150,10 @@ export function extractVariables(scanResult, customVars = {}) {
|
|
|
150
150
|
existsSync(join(projectRoot, 'src', 'main.ts'))) {
|
|
151
151
|
appDir = 'src';
|
|
152
152
|
}
|
|
153
|
-
// Detect TUI (Ink) projects
|
|
153
|
+
// Detect TUI (Ink) projects and service dependencies
|
|
154
154
|
let isTui = '';
|
|
155
|
+
let hasSupabase = '';
|
|
156
|
+
let hasPosthog = '';
|
|
155
157
|
try {
|
|
156
158
|
const pkgPath = join(projectRoot, 'package.json');
|
|
157
159
|
if (existsSync(pkgPath)) {
|
|
@@ -159,6 +161,10 @@ export function extractVariables(scanResult, customVars = {}) {
|
|
|
159
161
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
160
162
|
if (allDeps['ink'])
|
|
161
163
|
isTui = 'true';
|
|
164
|
+
if (allDeps['@supabase/supabase-js'] || allDeps['@supabase/ssr'])
|
|
165
|
+
hasSupabase = 'true';
|
|
166
|
+
if (allDeps['posthog-js'] || allDeps['posthog-node'])
|
|
167
|
+
hasPosthog = 'true';
|
|
162
168
|
}
|
|
163
169
|
}
|
|
164
170
|
catch { /* ignore */ }
|
|
@@ -179,6 +185,8 @@ export function extractVariables(scanResult, customVars = {}) {
|
|
|
179
185
|
stylingVariant,
|
|
180
186
|
appDir,
|
|
181
187
|
isTui,
|
|
188
|
+
hasSupabase,
|
|
189
|
+
hasPosthog,
|
|
182
190
|
...commands,
|
|
183
191
|
...aiData,
|
|
184
192
|
...customVars,
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -43,7 +43,15 @@ export function parseCliArgs(argv) {
|
|
|
43
43
|
'--interval',
|
|
44
44
|
'--provider',
|
|
45
45
|
'--review-mode',
|
|
46
|
+
'--issue',
|
|
47
|
+
'--context',
|
|
48
|
+
'--goals',
|
|
49
|
+
'--max-items',
|
|
50
|
+
'--max-steps',
|
|
51
|
+
'--labels',
|
|
46
52
|
]);
|
|
53
|
+
// Flags that can be specified multiple times, accumulating into an array
|
|
54
|
+
const repeatableFlagSet = new Set(['--issue', '--context']);
|
|
47
55
|
let i = 0;
|
|
48
56
|
while (i < argv.length) {
|
|
49
57
|
const arg = argv[i];
|
|
@@ -63,7 +71,22 @@ export function parseCliArgs(argv) {
|
|
|
63
71
|
if (arg.startsWith('--')) {
|
|
64
72
|
const normalized = normalizeFlagName(arg);
|
|
65
73
|
if (valueFlagSet.has(arg) && i + 1 < argv.length && !argv[i + 1].startsWith('-')) {
|
|
66
|
-
|
|
74
|
+
const value = argv[i + 1];
|
|
75
|
+
if (repeatableFlagSet.has(arg)) {
|
|
76
|
+
const existing = flags[normalized];
|
|
77
|
+
if (Array.isArray(existing)) {
|
|
78
|
+
existing.push(value);
|
|
79
|
+
}
|
|
80
|
+
else if (typeof existing === 'string') {
|
|
81
|
+
flags[normalized] = [existing, value];
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
flags[normalized] = [value];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
flags[normalized] = value;
|
|
89
|
+
}
|
|
67
90
|
i += 2;
|
|
68
91
|
}
|
|
69
92
|
else {
|
|
@@ -155,6 +178,7 @@ async function startInkTui(initialScreen = 'shell', options) {
|
|
|
155
178
|
provider: initialState.provider,
|
|
156
179
|
model: initialState.model,
|
|
157
180
|
scanResult: initialState.scanResult,
|
|
181
|
+
initialReferences: options?.initialReferences,
|
|
158
182
|
}
|
|
159
183
|
: undefined;
|
|
160
184
|
// Build run props if starting on run/monitor screen
|
|
@@ -167,6 +191,7 @@ async function startInkTui(initialScreen = 'shell', options) {
|
|
|
167
191
|
version,
|
|
168
192
|
interviewProps,
|
|
169
193
|
runProps,
|
|
194
|
+
agentProps: options?.agentOptions,
|
|
170
195
|
onComplete: (specPath) => {
|
|
171
196
|
// Spec was saved to disk by app.tsx (avoid stdout noise during TUI)
|
|
172
197
|
logger.debug(`Created spec: ${specPath}`);
|
|
@@ -199,7 +224,9 @@ Usage:
|
|
|
199
224
|
wiggum new <name> Create new feature spec (TUI)
|
|
200
225
|
wiggum run <feature> Run feature development loop
|
|
201
226
|
wiggum monitor <feature> Monitor a running feature loop
|
|
227
|
+
wiggum sync Refresh project context (scan + AI analysis)
|
|
202
228
|
wiggum config [args...] Manage API keys and settings
|
|
229
|
+
wiggum agent Autonomous backlog executor
|
|
203
230
|
|
|
204
231
|
Options for run:
|
|
205
232
|
--worktree Use git worktree isolation
|
|
@@ -222,9 +249,22 @@ Options for init:
|
|
|
222
249
|
Options for new:
|
|
223
250
|
--provider <name> AI provider
|
|
224
251
|
--model <model> AI model
|
|
252
|
+
--issue <number|url> Add GitHub issue as context (repeatable)
|
|
253
|
+
--context <url|path> Add URL or file as context (repeatable)
|
|
254
|
+
--auto Headless mode (skip TUI, for scripting/agents)
|
|
255
|
+
--goals <description> Feature goals (used with --auto)
|
|
225
256
|
-e, --edit Open in editor after creation
|
|
226
257
|
-f, --force Overwrite existing spec
|
|
227
258
|
|
|
259
|
+
Options for agent:
|
|
260
|
+
--model <model> AI model (overrides ralph.config.cjs agent.defaultModel)
|
|
261
|
+
--max-items <n> Max issues to process before stopping
|
|
262
|
+
--max-steps <n> Max agent steps before stopping
|
|
263
|
+
--labels <l1,l2> Only work on issues with these labels (comma-separated)
|
|
264
|
+
--review-mode <mode> Review mode: 'manual', 'auto', or 'merge' (default: manual)
|
|
265
|
+
--dry-run Plan what would be done without executing
|
|
266
|
+
--stream Stream output in real-time (default: wait for completion)
|
|
267
|
+
|
|
228
268
|
In the TUI:
|
|
229
269
|
/init Initialize or reconfigure project
|
|
230
270
|
/new <name> Create a new feature specification
|
|
@@ -259,11 +299,37 @@ Press Esc to cancel any operation.
|
|
|
259
299
|
const featureName = parsed.positionalArgs[0];
|
|
260
300
|
if (!featureName) {
|
|
261
301
|
console.error('Error: <name> is required for "new"');
|
|
262
|
-
console.error('Usage: wiggum new <name> [--
|
|
302
|
+
console.error('Usage: wiggum new <name> [--issue <number|url>] [--context <url|path>] [--model <model>] [--auto] [--goals <desc>] [-e] [-f]');
|
|
263
303
|
process.exit(1);
|
|
264
304
|
}
|
|
265
|
-
|
|
266
|
-
|
|
305
|
+
const initialReferences = [];
|
|
306
|
+
const issueFlags = parsed.flags.issue;
|
|
307
|
+
if (Array.isArray(issueFlags))
|
|
308
|
+
initialReferences.push(...issueFlags.map(v => `issue:${v}`));
|
|
309
|
+
else if (typeof issueFlags === 'string')
|
|
310
|
+
initialReferences.push(`issue:${issueFlags}`);
|
|
311
|
+
const contextFlags = parsed.flags.context;
|
|
312
|
+
if (Array.isArray(contextFlags))
|
|
313
|
+
initialReferences.push(...contextFlags);
|
|
314
|
+
else if (typeof contextFlags === 'string')
|
|
315
|
+
initialReferences.push(contextFlags);
|
|
316
|
+
if (parsed.flags.auto === true) {
|
|
317
|
+
const { newAutoCommand } = await import('./commands/new-auto.js');
|
|
318
|
+
const providerFlag = typeof parsed.flags.provider === 'string' ? parsed.flags.provider : undefined;
|
|
319
|
+
const validProviders = new Set(['anthropic', 'openai', 'openrouter']);
|
|
320
|
+
await newAutoCommand(featureName, {
|
|
321
|
+
goals: typeof parsed.flags.goals === 'string' ? parsed.flags.goals : undefined,
|
|
322
|
+
initialReferences: initialReferences.length > 0 ? initialReferences : undefined,
|
|
323
|
+
model: typeof parsed.flags.model === 'string' ? parsed.flags.model : undefined,
|
|
324
|
+
provider: providerFlag && validProviders.has(providerFlag) ? providerFlag : undefined,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
await startInkTui('interview', {
|
|
329
|
+
interviewFeature: featureName,
|
|
330
|
+
initialReferences: initialReferences.length > 0 ? initialReferences : undefined,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
267
333
|
break;
|
|
268
334
|
}
|
|
269
335
|
case 'run': {
|
|
@@ -319,6 +385,11 @@ Press Esc to cancel any operation.
|
|
|
319
385
|
}
|
|
320
386
|
break;
|
|
321
387
|
}
|
|
388
|
+
case 'sync': {
|
|
389
|
+
const { syncCommand } = await import('./commands/sync.js');
|
|
390
|
+
await syncCommand();
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
322
393
|
case 'config': {
|
|
323
394
|
const provider = getAvailableProvider();
|
|
324
395
|
const model = provider
|
|
@@ -328,6 +399,46 @@ Press Esc to cancel any operation.
|
|
|
328
399
|
await handleConfigCommand(parsed.positionalArgs, state);
|
|
329
400
|
break;
|
|
330
401
|
}
|
|
402
|
+
case 'agent': {
|
|
403
|
+
const reviewModeFlag = typeof parsed.flags.reviewMode === 'string' ? parsed.flags.reviewMode : undefined;
|
|
404
|
+
if (reviewModeFlag && !['manual', 'auto', 'merge'].includes(reviewModeFlag)) {
|
|
405
|
+
console.error(`Error: Invalid --review-mode '${reviewModeFlag}'. Allowed values: manual, auto, merge`);
|
|
406
|
+
process.exit(1);
|
|
407
|
+
}
|
|
408
|
+
const agentOpts = {
|
|
409
|
+
model: typeof parsed.flags.model === 'string' ? parsed.flags.model : undefined,
|
|
410
|
+
maxItems: typeof parsed.flags.maxItems === 'string' ? parseIntFlag(parsed.flags.maxItems, '--max-items') : undefined,
|
|
411
|
+
maxSteps: typeof parsed.flags.maxSteps === 'string' ? parseIntFlag(parsed.flags.maxSteps, '--max-steps') : undefined,
|
|
412
|
+
labels: typeof parsed.flags.labels === 'string' ? parsed.flags.labels.split(',').map(l => l.trim()).filter(Boolean) : undefined,
|
|
413
|
+
reviewMode: reviewModeFlag,
|
|
414
|
+
dryRun: parsed.flags.dryRun === true,
|
|
415
|
+
stream: parsed.flags.stream === true,
|
|
416
|
+
};
|
|
417
|
+
if (agentOpts.stream === true) {
|
|
418
|
+
// Explicit --stream: always headless
|
|
419
|
+
const { agentCommand } = await import('./commands/agent.js');
|
|
420
|
+
await agentCommand(agentOpts);
|
|
421
|
+
}
|
|
422
|
+
else if (process.stdout.isTTY && !isCI()) {
|
|
423
|
+
// TTY: launch TUI
|
|
424
|
+
await startInkTui('agent', {
|
|
425
|
+
agentOptions: {
|
|
426
|
+
modelOverride: agentOpts.model,
|
|
427
|
+
maxItems: agentOpts.maxItems,
|
|
428
|
+
maxSteps: agentOpts.maxSteps,
|
|
429
|
+
labels: agentOpts.labels,
|
|
430
|
+
reviewMode: agentOpts.reviewMode,
|
|
431
|
+
dryRun: agentOpts.dryRun,
|
|
432
|
+
},
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
// Non-TTY / CI: headless
|
|
437
|
+
const { agentCommand } = await import('./commands/agent.js');
|
|
438
|
+
await agentCommand(agentOpts);
|
|
439
|
+
}
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
331
442
|
default:
|
|
332
443
|
// Unknown command - start TUI at shell
|
|
333
444
|
logger.warn(`Unknown command: ${parsed.command}. Starting TUI...`);
|
|
@@ -54,6 +54,11 @@ export declare const REPL_COMMANDS: {
|
|
|
54
54
|
readonly usage: "/monitor <feature-name>";
|
|
55
55
|
readonly aliases: readonly ["m"];
|
|
56
56
|
};
|
|
57
|
+
readonly agent: {
|
|
58
|
+
readonly description: "Start the autonomous backlog agent";
|
|
59
|
+
readonly usage: "/agent [--dry-run] [--max-items <n>]";
|
|
60
|
+
readonly aliases: readonly ["a"];
|
|
61
|
+
};
|
|
57
62
|
readonly config: {
|
|
58
63
|
readonly description: "Manage API keys and settings";
|
|
59
64
|
readonly usage: "/config [set <service> <key>]";
|
|
@@ -31,6 +31,11 @@ export const REPL_COMMANDS = {
|
|
|
31
31
|
usage: '/monitor <feature-name>',
|
|
32
32
|
aliases: ['m'],
|
|
33
33
|
},
|
|
34
|
+
agent: {
|
|
35
|
+
description: 'Start the autonomous backlog agent',
|
|
36
|
+
usage: '/agent [--dry-run] [--max-items <n>]',
|
|
37
|
+
aliases: ['a'],
|
|
38
|
+
},
|
|
34
39
|
config: {
|
|
35
40
|
description: 'Manage API keys and settings',
|
|
36
41
|
usage: '/config [set <service> <key>]',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
## Context
|
|
2
|
-
|
|
2
|
+
If @.ralph/guides/AGENTS.md exists, study it for commands and patterns.
|
|
3
3
|
Study @.ralph/specs/$FEATURE.md for feature specification.
|
|
4
4
|
Study @.ralph/specs/$FEATURE-implementation-plan.md for current tasks.
|
|
5
5
|
{{#if frameworkVariant}}For detailed architecture, see @{{appDir}}/.claude/CLAUDE.md{{/if}}
|
|
@@ -18,10 +18,10 @@ Key patterns: parallel fetches, direct imports, React.cache(), lazy loading.
|
|
|
18
18
|
- Search codebase before assuming something doesn't exist
|
|
19
19
|
|
|
20
20
|
## Task
|
|
21
|
-
|
|
21
|
+
Work through ALL incomplete tasks in the implementation plan in a single session.
|
|
22
22
|
**Skip E2E tasks** (tasks starting with `E2E:`) - those are handled in a separate phase.
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
For each task: implement it, write tests, validate, commit, then move to the next task.
|
|
24
|
+
Do not stop after one task — keep going until all non-E2E tasks are complete.
|
|
25
25
|
|
|
26
26
|
## Validation
|
|
27
27
|
After changes, ALL must pass:
|
|
@@ -36,7 +36,8 @@ If any validation fails, fix the issue before proceeding.
|
|
|
36
36
|
Before committing, review your changes against @.ralph/guides/SECURITY.md:
|
|
37
37
|
1. **Quick scan**: Input validation, injection prevention, auth checks, data exposure
|
|
38
38
|
2. **Run**: `cd {{appDir}} && {{packageManager}} audit` (check for vulnerable dependencies)
|
|
39
|
-
3. **Check**: `mcp__supabase__get_advisors` with type "security" (RLS policies)
|
|
39
|
+
{{#if hasSupabase}}3. **Check**: `mcp__supabase__get_advisors` with type "security" (RLS policies)
|
|
40
|
+
{{/if}}
|
|
40
41
|
4. **Red team**: Can auth be bypassed? Can other users' data be accessed?
|
|
41
42
|
|
|
42
43
|
Flag any security issues in the implementation plan and fix before committing.
|
|
@@ -54,7 +55,7 @@ If any check fails, fix before committing.
|
|
|
54
55
|
|
|
55
56
|
## Completion
|
|
56
57
|
When ALL validations pass:
|
|
57
|
-
1. Update @.ralph/specs/$FEATURE-implementation-plan.md
|
|
58
|
+
1. Update @.ralph/specs/$FEATURE-implementation-plan.md — change the task's `- [ ]` to `- [x]` and append the commit hash (e.g., `- [x] Task description - abc1234`). The harness tracks progress by counting checkboxes, so this step is mandatory.
|
|
58
59
|
2. `git -C {{appDir}} add -A`
|
|
59
60
|
3. `git -C {{appDir}} commit -m "type(scope): description"`
|
|
60
61
|
4. `git -C {{appDir}} push origin feat/$FEATURE`
|
|
@@ -69,9 +70,11 @@ If this iteration revealed something useful, append to @.ralph/LEARNINGS.md:
|
|
|
69
70
|
Format: `- [YYYY-MM-DD] [$FEATURE] Brief description`
|
|
70
71
|
|
|
71
72
|
## Rules
|
|
72
|
-
-
|
|
73
|
+
- Complete ALL remaining non-E2E tasks before ending the session
|
|
74
|
+
- Commit after each task so progress is preserved if the session is interrupted
|
|
73
75
|
- Tests are mandatory - no task is complete without tests
|
|
74
76
|
- Search codebase before assuming something doesn't exist
|
|
75
|
-
- If blocked, document in implementation plan and move to next task
|
|
76
|
-
- Use Supabase MCP for database operations
|
|
77
|
-
- Use PostHog MCP for analytics queries
|
|
77
|
+
- If blocked on a task, document in implementation plan and move to the next task
|
|
78
|
+
{{#if hasSupabase}}- Use Supabase MCP for database operations
|
|
79
|
+
{{/if}}{{#if hasPosthog}}- Use PostHog MCP for analytics queries
|
|
80
|
+
{{/if}}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
## Context
|
|
2
|
-
|
|
2
|
+
If @.ralph/guides/AGENTS.md exists, study it for commands and patterns.
|
|
3
3
|
Study @.ralph/specs/$FEATURE.md for feature specification.
|
|
4
4
|
Study @.ralph/specs/$FEATURE-implementation-plan.md for E2E test scenarios.
|
|
5
5
|
{{#if frameworkVariant}}For detailed architecture, see @{{appDir}}/.claude/CLAUDE.md{{/if}}
|
|
@@ -21,6 +21,7 @@ If either fails, fix issues before proceeding with E2E tests.
|
|
|
21
21
|
{{#if isTui}}
|
|
22
22
|
## Task
|
|
23
23
|
Execute automated E2E tests for the completed TUI feature using the xterm.js bridge and agent-browser.
|
|
24
|
+
Run ALL scenarios in a single session — do not end between scenarios.
|
|
24
25
|
|
|
25
26
|
### Step 1: Start Bridge
|
|
26
27
|
Check the bridge is running:
|
|
@@ -149,11 +150,11 @@ When all scenarios are executed:
|
|
|
149
150
|
2. Update the Implementation Summary status to `[PASSED]` if all passed
|
|
150
151
|
3. **Commit the updated implementation plan:**
|
|
151
152
|
```bash
|
|
152
|
-
git add -A && git commit -m "test($FEATURE): E2E tests passed via agent-browser"
|
|
153
|
+
git -C {{appDir}} add -A && git -C {{appDir}} commit -m "test($FEATURE): E2E tests passed via agent-browser"
|
|
153
154
|
```
|
|
154
155
|
4. **Push to remote:**
|
|
155
156
|
```bash
|
|
156
|
-
git push origin feat/$FEATURE
|
|
157
|
+
git -C {{appDir}} push origin feat/$FEATURE
|
|
157
158
|
```
|
|
158
159
|
5. If all passed: signal ready for PR phase
|
|
159
160
|
6. If any failed: failures documented, loop will retry after fix iteration
|
|
@@ -168,6 +169,7 @@ Format: `- [YYYY-MM-DD] [$FEATURE] Brief description`
|
|
|
168
169
|
{{else}}
|
|
169
170
|
## Task
|
|
170
171
|
Execute automated E2E tests for the completed feature using Playwright MCP tools.
|
|
172
|
+
Run ALL scenarios in a single session — do not end between scenarios.
|
|
171
173
|
|
|
172
174
|
### Step 1: Check Dev Server
|
|
173
175
|
Verify dev server is running at http://localhost:3000. If not accessible, start it:
|
|
@@ -176,7 +178,7 @@ cd {{appDir}} && {{devCommand}} &
|
|
|
176
178
|
```
|
|
177
179
|
Wait ~10 seconds for server startup, then verify with a simple browser_navigate.
|
|
178
180
|
|
|
179
|
-
### Step 1.5: Seed Test Data (if needed)
|
|
181
|
+
{{#if hasSupabase}}### Step 1.5: Seed Test Data (if needed)
|
|
180
182
|
|
|
181
183
|
Check if test scenarios require specific data volumes (e.g., pagination needs >10 rows).
|
|
182
184
|
|
|
@@ -199,6 +201,7 @@ query: "DELETE FROM table_name WHERE data->>'_test' = 'true';"
|
|
|
199
201
|
```
|
|
200
202
|
|
|
201
203
|
**If seeding is impractical:** Document in implementation plan that E2E was skipped but unit tests provide coverage.
|
|
204
|
+
{{/if}}
|
|
202
205
|
|
|
203
206
|
### Step 2: Parse E2E Test Scenarios
|
|
204
207
|
Read E2E test scenarios from @.ralph/specs/$FEATURE-implementation-plan.md.
|
|
@@ -246,7 +249,7 @@ For each E2E test scenario:
|
|
|
246
249
|
- Check console: `browser_console_messages` for JS errors
|
|
247
250
|
- Document failure details
|
|
248
251
|
|
|
249
|
-
### Step 4: Database Verification
|
|
252
|
+
{{#if hasSupabase}}### Step 4: Database Verification
|
|
250
253
|
For scenarios with database checks, use Supabase MCP:
|
|
251
254
|
```
|
|
252
255
|
mcp__plugin_supabase_supabase__execute_sql
|
|
@@ -255,6 +258,7 @@ query: "SELECT * FROM survey_responses WHERE ..."
|
|
|
255
258
|
```
|
|
256
259
|
|
|
257
260
|
Verify returned data matches expected state.
|
|
261
|
+
{{/if}}
|
|
258
262
|
|
|
259
263
|
### Unique Test Data (for Parallel Execution)
|
|
260
264
|
When creating test data, use unique identifiers to avoid conflicts with other loops:
|
|
@@ -315,11 +319,12 @@ Update @.ralph/specs/$FEATURE-implementation-plan.md for each scenario:
|
|
|
315
319
|
2. Verify URL contains expected path/params
|
|
316
320
|
```
|
|
317
321
|
|
|
318
|
-
### Database State
|
|
322
|
+
{{#if hasSupabase}}### Database State
|
|
319
323
|
```
|
|
320
324
|
1. mcp__plugin_supabase_supabase__execute_sql with SELECT query
|
|
321
325
|
2. Verify row count, column values match expectations
|
|
322
326
|
```
|
|
327
|
+
{{/if}}
|
|
323
328
|
|
|
324
329
|
## Browser State Management
|
|
325
330
|
|
|
@@ -364,8 +369,9 @@ If code changes don't appear in the browser:
|
|
|
364
369
|
|
|
365
370
|
### Stale Data
|
|
366
371
|
- Clear browser storage: Use `browser_close` between scenarios
|
|
367
|
-
- Check Supabase for stale test data from previous runs
|
|
372
|
+
{{#if hasSupabase}}- Check Supabase for stale test data from previous runs
|
|
368
373
|
- Delete test data: `DELETE FROM table WHERE data->>'_test' = 'true'`
|
|
374
|
+
{{/if}}
|
|
369
375
|
|
|
370
376
|
## Rules
|
|
371
377
|
- Always get a fresh `browser_snapshot` after actions before making assertions
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
## Context
|
|
2
|
-
|
|
2
|
+
If @.ralph/guides/AGENTS.md exists, study it for commands and patterns.
|
|
3
3
|
Study @.ralph/specs/README.md for spec structure.
|
|
4
4
|
Study @.ralph/specs/$FEATURE.md for feature specification.
|
|
5
5
|
{{#if frameworkVariant}}For detailed architecture, see @{{appDir}}/.claude/CLAUDE.md{{/if}}
|
|
@@ -96,9 +96,22 @@ Example E2E scenario:
|
|
|
96
96
|
- [x] E2E: Scenario name - PASSED
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
## CRITICAL CONSTRAINT — PLANNING ONLY
|
|
100
|
+
**You are in the PLANNING phase. Your ONLY job is to produce an implementation plan.**
|
|
101
|
+
- Do NOT write any source code, test code, or configuration files
|
|
102
|
+
- Do NOT create, modify, or touch any files outside `.ralph/specs/`
|
|
103
|
+
- Do NOT run build, test, or lint commands
|
|
104
|
+
- Do NOT make git commits
|
|
105
|
+
- If you feel the urge to "just implement a small piece", STOP — that is a phase violation
|
|
106
|
+
- The implementation phase runs AFTER this session ends, in a separate session
|
|
107
|
+
- Violation of this constraint wastes tokens and breaks the harness automation
|
|
108
|
+
|
|
99
109
|
## Rules
|
|
100
|
-
-
|
|
101
|
-
-
|
|
110
|
+
- You MUST use `- [ ]` checkbox syntax for every task in the plan
|
|
111
|
+
- Do NOT use heading-based task formats (e.g., `#### Task 1:`) for individual tasks
|
|
112
|
+
- The harness parses `- [ ]` lines to track progress — other formats will break automation
|
|
113
|
+
- Use `### Phase N:` headings only for phase grouping, not for individual tasks
|
|
114
|
+
- One task = one commit-sized unit of work (but tasks can be grouped into phases for batch implementation)
|
|
102
115
|
- Every implementation task needs a corresponding test task
|
|
103
116
|
- Use Supabase MCP to check existing schema
|
|
104
117
|
- Use PostHog MCP to check existing analytics setup
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
## Context
|
|
2
|
-
|
|
2
|
+
If @.ralph/guides/AGENTS.md exists, study it for commands and patterns.
|
|
3
3
|
Study @.ralph/specs/$FEATURE.md for feature specification.
|
|
4
4
|
Study @.ralph/specs/$FEATURE-implementation-plan.md for completed tasks.
|
|
5
5
|
|
|
@@ -9,6 +9,7 @@ Capture any review feedback patterns for future iterations.
|
|
|
9
9
|
|
|
10
10
|
## Task
|
|
11
11
|
All implementation and E2E tasks are complete. Create PR and request review.
|
|
12
|
+
Complete ALL steps in a single pass — do not end the session between steps.
|
|
12
13
|
|
|
13
14
|
### Step 1: Verify Ready State
|
|
14
15
|
1. Check all tasks are complete in implementation plan (no `- [ ]` items)
|
|
@@ -52,12 +53,14 @@ cd {{appDir}} && gh pr create --base main --head feat/$FEATURE \
|
|
|
52
53
|
[Read from implementation plan - list completed phases]
|
|
53
54
|
|
|
54
55
|
## Testing
|
|
55
|
-
- [x] Unit/integration tests:
|
|
56
|
-
- [x] E2E tests: All scenarios passed
|
|
56
|
+
- [x] Unit/integration tests: passing
|
|
57
|
+
- [x] E2E tests: All scenarios passed
|
|
57
58
|
- [x] Build succeeds
|
|
58
59
|
|
|
59
60
|
## E2E Test Results
|
|
60
|
-
[Copy from implementation plan
|
|
61
|
+
[Copy from implementation plan E2E section]
|
|
62
|
+
|
|
63
|
+
Closes #[Read the source issue number from the spec file metadata or context section]
|
|
61
64
|
|
|
62
65
|
Generated with Claude Code
|
|
63
66
|
EOF
|
|
@@ -88,17 +91,27 @@ Review the git diff against main and check:
|
|
|
88
91
|
|
|
89
92
|
Run: git diff main
|
|
90
93
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
This line is parsed by the automation — do not omit it."
|
|
94
|
+
Then:
|
|
95
|
+
1. Post your complete review as a comment on the PR using:
|
|
96
|
+
gh pr comment --body '<your review in markdown>'
|
|
97
|
+
Format the comment with: a summary, specific issues with file:line refs (if any), and the verdict.
|
|
98
|
+
2. Print your final verdict as the LAST line of stdout. Print exactly one of:
|
|
99
|
+
VERDICT: APPROVED
|
|
100
|
+
VERDICT: NOT APPROVED
|
|
101
|
+
This line is parsed by the automation — do not omit it."
|
|
99
102
|
fi
|
|
100
103
|
```
|
|
101
104
|
|
|
105
|
+
After the review completes, check its output:
|
|
106
|
+
- If it contains "VERDICT: APPROVED", echo that line so the automation detects it:
|
|
107
|
+
```bash
|
|
108
|
+
echo "VERDICT: APPROVED"
|
|
109
|
+
```
|
|
110
|
+
- If issues were found, echo:
|
|
111
|
+
```bash
|
|
112
|
+
echo "VERDICT: NOT APPROVED"
|
|
113
|
+
```
|
|
114
|
+
|
|
102
115
|
**Handle review feedback:**
|
|
103
116
|
- If Claude outputs "VERDICT: APPROVED" -> Done. The PR is ready for manual merge by the user.
|
|
104
117
|
- If Claude lists issues:
|
|
@@ -113,8 +126,15 @@ After review is complete (approved or max iterations reached):
|
|
|
113
126
|
1. Post a summary comment on the PR with the review outcome
|
|
114
127
|
2. Do NOT merge — the user will review and merge manually
|
|
115
128
|
|
|
129
|
+
## IMPORTANT: Review scope
|
|
130
|
+
If you discover that no implementation code exists (empty diff, no source files changed),
|
|
131
|
+
do NOT implement the feature yourself. Instead, report "VERDICT: NOT APPROVED —
|
|
132
|
+
no implementation found" so the harness can trigger a new implementation iteration.
|
|
133
|
+
|
|
116
134
|
## Rules
|
|
135
|
+
- **NEVER approve if any tests are failing.** Output "VERDICT: NOT APPROVED — test failures" if any tests fail.
|
|
117
136
|
- Do NOT merge the PR — auto mode only reviews, the user merges
|
|
137
|
+
- Do NOT implement missing features — only review and fix minor issues
|
|
118
138
|
- Address ALL review comments before marking as approved
|
|
119
139
|
- If gh CLI fails, check authentication: `gh auth status`
|
|
120
140
|
- Keep review conversation focused and professional
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
## Context
|
|
2
|
-
|
|
2
|
+
If @.ralph/guides/AGENTS.md exists, study it for commands and patterns.
|
|
3
3
|
Study @.ralph/specs/$FEATURE.md for feature specification.
|
|
4
4
|
Study @.ralph/specs/$FEATURE-implementation-plan.md for completed tasks.
|
|
5
5
|
|
|
@@ -9,6 +9,7 @@ Capture any review feedback patterns for future iterations.
|
|
|
9
9
|
|
|
10
10
|
## Task
|
|
11
11
|
All implementation and E2E tasks are complete. Create PR for manual review.
|
|
12
|
+
Complete ALL steps in a single pass — do not end the session between steps.
|
|
12
13
|
|
|
13
14
|
### Step 1: Verify Ready State
|
|
14
15
|
1. Check all tasks are complete in implementation plan (no `- [ ]` items)
|
|
@@ -59,6 +60,8 @@ cd {{appDir}} && gh pr create --base main --head feat/$FEATURE \
|
|
|
59
60
|
## E2E Test Results
|
|
60
61
|
[Copy from implementation plan if E2E phase exists]
|
|
61
62
|
|
|
63
|
+
Closes #[Read the source issue number from the spec file metadata or context section]
|
|
64
|
+
|
|
62
65
|
Generated with Claude Code
|
|
63
66
|
EOF
|
|
64
67
|
)"
|