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.
Files changed (97) hide show
  1. package/bin/ralph.js +0 -0
  2. package/dist/agent/memory/ingest.d.ts +14 -0
  3. package/dist/agent/memory/ingest.js +77 -0
  4. package/dist/agent/memory/store.d.ts +15 -0
  5. package/dist/agent/memory/store.js +98 -0
  6. package/dist/agent/memory/types.d.ts +16 -0
  7. package/dist/agent/memory/types.js +14 -0
  8. package/dist/agent/orchestrator.d.ts +7 -0
  9. package/dist/agent/orchestrator.js +266 -0
  10. package/dist/agent/resolve-config.d.ts +26 -0
  11. package/dist/agent/resolve-config.js +43 -0
  12. package/dist/agent/tools/backlog.d.ts +27 -0
  13. package/dist/agent/tools/backlog.js +51 -0
  14. package/dist/agent/tools/dry-run.d.ts +106 -0
  15. package/dist/agent/tools/dry-run.js +119 -0
  16. package/dist/agent/tools/execution.d.ts +51 -0
  17. package/dist/agent/tools/execution.js +256 -0
  18. package/dist/agent/tools/feature-state.d.ts +43 -0
  19. package/dist/agent/tools/feature-state.js +184 -0
  20. package/dist/agent/tools/introspection.d.ts +23 -0
  21. package/dist/agent/tools/introspection.js +40 -0
  22. package/dist/agent/tools/memory.d.ts +44 -0
  23. package/dist/agent/tools/memory.js +99 -0
  24. package/dist/agent/tools/preflight.d.ts +7 -0
  25. package/dist/agent/tools/preflight.js +137 -0
  26. package/dist/agent/tools/reporting.d.ts +58 -0
  27. package/dist/agent/tools/reporting.js +119 -0
  28. package/dist/agent/tools/schemas.d.ts +2 -0
  29. package/dist/agent/tools/schemas.js +3 -0
  30. package/dist/agent/types.d.ts +45 -0
  31. package/dist/agent/types.js +1 -0
  32. package/dist/ai/conversation/conversation-manager.js +8 -0
  33. package/dist/ai/conversation/url-fetcher.js +27 -0
  34. package/dist/ai/providers.js +5 -5
  35. package/dist/commands/agent.d.ts +17 -0
  36. package/dist/commands/agent.js +114 -0
  37. package/dist/commands/monitor.js +50 -183
  38. package/dist/commands/new-auto.d.ts +15 -0
  39. package/dist/commands/new-auto.js +237 -0
  40. package/dist/commands/run.js +20 -10
  41. package/dist/commands/sync.d.ts +15 -0
  42. package/dist/commands/sync.js +68 -0
  43. package/dist/generator/config.d.ts +1 -41
  44. package/dist/generator/config.js +7 -0
  45. package/dist/generator/index.d.ts +2 -2
  46. package/dist/generator/templates.d.ts +2 -0
  47. package/dist/generator/templates.js +9 -1
  48. package/dist/index.d.ts +1 -1
  49. package/dist/index.js +115 -4
  50. package/dist/repl/command-parser.d.ts +5 -0
  51. package/dist/repl/command-parser.js +5 -0
  52. package/dist/templates/prompts/PROMPT.md.tmpl +13 -10
  53. package/dist/templates/prompts/PROMPT_e2e.md.tmpl +13 -7
  54. package/dist/templates/prompts/PROMPT_feature.md.tmpl +16 -3
  55. package/dist/templates/prompts/PROMPT_review_auto.md.tmpl +32 -12
  56. package/dist/templates/prompts/PROMPT_review_manual.md.tmpl +4 -1
  57. package/dist/templates/prompts/PROMPT_review_merge.md.tmpl +39 -14
  58. package/dist/templates/prompts/PROMPT_verify.md.tmpl +5 -2
  59. package/dist/templates/scripts/feature-loop.sh.tmpl +441 -69
  60. package/dist/tui/app.d.ts +19 -2
  61. package/dist/tui/app.js +22 -4
  62. package/dist/tui/components/IssuePicker.d.ts +27 -0
  63. package/dist/tui/components/IssuePicker.js +64 -0
  64. package/dist/tui/components/RunCompletionSummary.js +6 -3
  65. package/dist/tui/hooks/useAgentOrchestrator.d.ts +29 -0
  66. package/dist/tui/hooks/useAgentOrchestrator.js +453 -0
  67. package/dist/tui/orchestration/interview-orchestrator.d.ts +5 -1
  68. package/dist/tui/orchestration/interview-orchestrator.js +27 -6
  69. package/dist/tui/screens/AgentScreen.d.ts +21 -0
  70. package/dist/tui/screens/AgentScreen.js +159 -0
  71. package/dist/tui/screens/InitScreen.js +4 -0
  72. package/dist/tui/screens/InterviewScreen.d.ts +3 -1
  73. package/dist/tui/screens/InterviewScreen.js +146 -10
  74. package/dist/tui/screens/MainShell.d.ts +1 -1
  75. package/dist/tui/screens/MainShell.js +36 -1
  76. package/dist/tui/screens/RunScreen.js +38 -6
  77. package/dist/tui/utils/build-run-summary.d.ts +1 -1
  78. package/dist/tui/utils/build-run-summary.js +40 -84
  79. package/dist/tui/utils/clear-screen.d.ts +14 -0
  80. package/dist/tui/utils/clear-screen.js +16 -0
  81. package/dist/tui/utils/loop-status.d.ts +41 -1
  82. package/dist/tui/utils/loop-status.js +243 -35
  83. package/dist/tui/utils/pr-summary.d.ts +3 -2
  84. package/dist/tui/utils/pr-summary.js +41 -6
  85. package/dist/utils/config.d.ts +8 -0
  86. package/dist/utils/config.js +8 -0
  87. package/dist/utils/github.d.ts +32 -0
  88. package/dist/utils/github.js +106 -0
  89. package/package.json +4 -1
  90. package/src/templates/prompts/PROMPT.md.tmpl +13 -10
  91. package/src/templates/prompts/PROMPT_e2e.md.tmpl +13 -7
  92. package/src/templates/prompts/PROMPT_feature.md.tmpl +16 -3
  93. package/src/templates/prompts/PROMPT_review_auto.md.tmpl +32 -12
  94. package/src/templates/prompts/PROMPT_review_manual.md.tmpl +4 -1
  95. package/src/templates/prompts/PROMPT_review_merge.md.tmpl +39 -14
  96. package/src/templates/prompts/PROMPT_verify.md.tmpl +5 -2
  97. package/src/templates/scripts/feature-loop.sh.tmpl +441 -69
@@ -24,11 +24,12 @@ export interface IssueInfo {
24
24
  export declare function getPrForBranch(projectRoot: string, branchName: string): PrInfo | null;
25
25
  /**
26
26
  * Get linked issue for a branch by parsing the PR body for closing keywords
27
- * (Closes/Fixes/Resolves #N).
27
+ * (Closes/Fixes/Resolves #N), with fallbacks for spec file and feature name search.
28
28
  *
29
29
  * @param projectRoot - Root directory of the git repository
30
30
  * @param branchName - Branch name to look up
31
31
  * @param prInfo - Optional pre-fetched PR info to avoid redundant gh call
32
+ * @param featureName - Optional feature name for fallback issue detection
32
33
  * @returns Issue info object, or null if not found or gh not available
33
34
  */
34
- export declare function getLinkedIssue(projectRoot: string, branchName: string, prInfo?: PrInfo | null): IssueInfo | null;
35
+ export declare function getLinkedIssue(projectRoot: string, branchName: string, prInfo?: PrInfo | null, featureName?: string): IssueInfo | null;
@@ -2,6 +2,8 @@
2
2
  * PR and Issue utilities for enhanced run summary.
3
3
  */
4
4
  import { execFileSync } from 'node:child_process';
5
+ import { existsSync, readFileSync } from 'node:fs';
6
+ import { join } from 'node:path';
5
7
  import { logger } from '../../utils/logger.js';
6
8
  /**
7
9
  * Get PR information for a branch.
@@ -33,16 +35,51 @@ export function getPrForBranch(projectRoot, branchName) {
33
35
  title: pr.title,
34
36
  };
35
37
  }
38
+ /**
39
+ * Extract issue number from PR body closing keywords or fallback strategies.
40
+ */
41
+ function findIssueNumber(body, featureName, projectRoot) {
42
+ // Strategy 1: Closing keywords in PR body (Closes/Fixes/Resolves #N)
43
+ const issueMatch = body.match(/(?:closes|fixes|resolves)\s+#(\d+)/i);
44
+ if (issueMatch) {
45
+ return parseInt(issueMatch[1], 10);
46
+ }
47
+ // Strategy 2: Bare "#N" references in the body (e.g., "Closes #7" without keyword before it)
48
+ // Look for "# N" patterns that are likely issue references (not markdown headers)
49
+ const hashRefMatch = body.match(/(?:^|\s)#(\d+)\b/m);
50
+ if (hashRefMatch) {
51
+ return parseInt(hashRefMatch[1], 10);
52
+ }
53
+ // Strategy 3: Read spec file for issue reference
54
+ if (featureName && projectRoot) {
55
+ try {
56
+ const specPath = join(projectRoot, '.ralph', 'specs', `${featureName}.md`);
57
+ if (existsSync(specPath)) {
58
+ const specContent = readFileSync(specPath, 'utf-8');
59
+ // Look for "Issue: #N", "Source Issue: #N", "GitHub Issue: #N", or issue URLs
60
+ const specIssueMatch = specContent.match(/(?:issue|source|github)[:\s]*#(\d+)/i) || specContent.match(/github\.com\/[^/]+\/[^/]+\/issues\/(\d+)/i);
61
+ if (specIssueMatch) {
62
+ return parseInt(specIssueMatch[1], 10);
63
+ }
64
+ }
65
+ }
66
+ catch {
67
+ // spec read failure is non-fatal
68
+ }
69
+ }
70
+ return null;
71
+ }
36
72
  /**
37
73
  * Get linked issue for a branch by parsing the PR body for closing keywords
38
- * (Closes/Fixes/Resolves #N).
74
+ * (Closes/Fixes/Resolves #N), with fallbacks for spec file and feature name search.
39
75
  *
40
76
  * @param projectRoot - Root directory of the git repository
41
77
  * @param branchName - Branch name to look up
42
78
  * @param prInfo - Optional pre-fetched PR info to avoid redundant gh call
79
+ * @param featureName - Optional feature name for fallback issue detection
43
80
  * @returns Issue info object, or null if not found or gh not available
44
81
  */
45
- export function getLinkedIssue(projectRoot, branchName, prInfo) {
82
+ export function getLinkedIssue(projectRoot, branchName, prInfo, featureName) {
46
83
  try {
47
84
  // Use provided PR info or fetch it
48
85
  const pr = prInfo !== undefined ? prInfo : getPrForBranch(projectRoot, branchName);
@@ -57,12 +94,10 @@ export function getLinkedIssue(projectRoot, branchName, prInfo) {
57
94
  }).trim();
58
95
  const prData = JSON.parse(prBody);
59
96
  const body = prData.body || '';
60
- // Look for issue references in PR body (e.g., "Closes #123", "Fixes #456")
61
- const issueMatch = body.match(/(?:closes|fixes|resolves)\s+#(\d+)/i);
62
- if (!issueMatch) {
97
+ const issueNumber = findIssueNumber(body, featureName, projectRoot);
98
+ if (!issueNumber) {
63
99
  return null;
64
100
  }
65
- const issueNumber = parseInt(issueMatch[1], 10);
66
101
  // Fetch the issue details
67
102
  const issueOutput = execFileSync('gh', ['issue', 'view', String(issueNumber), '--json', 'number,url,state,title'], {
68
103
  cwd: projectRoot,
@@ -50,6 +50,13 @@ export interface LoopConfig {
50
50
  planningModel: string;
51
51
  reviewMode: 'manual' | 'auto' | 'merge';
52
52
  }
53
+ /**
54
+ * Agent configuration in ralph.config.cjs
55
+ */
56
+ export interface AgentSectionConfig {
57
+ defaultProvider: string;
58
+ defaultModel: string;
59
+ }
53
60
  /**
54
61
  * Full ralph.config.cjs structure
55
62
  */
@@ -59,6 +66,7 @@ export interface RalphConfig {
59
66
  commands: CommandsConfig;
60
67
  paths: PathsConfig;
61
68
  loop: LoopConfig;
69
+ agent: AgentSectionConfig;
62
70
  }
63
71
  /**
64
72
  * Default configuration values
@@ -47,6 +47,10 @@ export const DEFAULT_CONFIG = {
47
47
  planningModel: 'opus',
48
48
  reviewMode: 'manual',
49
49
  },
50
+ agent: {
51
+ defaultProvider: '',
52
+ defaultModel: '',
53
+ },
50
54
  };
51
55
  /**
52
56
  * Load ralph.config.cjs from a project directory
@@ -104,6 +108,10 @@ export async function loadConfigWithDefaults(projectRoot) {
104
108
  ...DEFAULT_CONFIG.loop,
105
109
  ...config.loop,
106
110
  },
111
+ agent: {
112
+ ...DEFAULT_CONFIG.agent,
113
+ ...config?.agent,
114
+ },
107
115
  };
108
116
  }
109
117
  /**
@@ -0,0 +1,32 @@
1
+ export declare function isGhInstalled(): Promise<boolean>;
2
+ export declare function _resetGhCache(): void;
3
+ export interface GitHubIssueDetail {
4
+ title: string;
5
+ body: string;
6
+ labels: string[];
7
+ }
8
+ export declare function fetchGitHubIssue(owner: string, repo: string, number: number): Promise<GitHubIssueDetail | null>;
9
+ export interface GitHubIssueListItem {
10
+ number: number;
11
+ title: string;
12
+ state: 'open' | 'closed';
13
+ labels: string[];
14
+ createdAt: string;
15
+ }
16
+ export interface ListIssuesResult {
17
+ issues: GitHubIssueListItem[];
18
+ error?: string;
19
+ }
20
+ export declare function listRepoIssues(owner: string, repo: string, search?: string, limit?: number): Promise<ListIssuesResult>;
21
+ export declare function detectGitHubRemote(projectRoot: string): Promise<GitHubRepo | null>;
22
+ export interface ParsedGitHubIssue {
23
+ owner: string;
24
+ repo: string;
25
+ number: number;
26
+ }
27
+ export declare function isGitHubIssueUrl(input: string): ParsedGitHubIssue | null;
28
+ export interface GitHubRepo {
29
+ owner: string;
30
+ repo: string;
31
+ }
32
+ export declare function parseGitHubRemote(remoteUrl: string): GitHubRepo | null;
@@ -0,0 +1,106 @@
1
+ import { execFile as execFileCb } from 'node:child_process';
2
+ /**
3
+ * Safe command execution using execFile (no shell, array-based args).
4
+ */
5
+ function safeExec(cmd, args, cwd) {
6
+ return new Promise((resolve, reject) => {
7
+ execFileCb(cmd, args, { cwd, timeout: 10000 }, (error, stdout) => {
8
+ if (error)
9
+ reject(error);
10
+ else
11
+ resolve(String(stdout));
12
+ });
13
+ });
14
+ }
15
+ let ghInstalledCache = null;
16
+ export async function isGhInstalled() {
17
+ if (ghInstalledCache !== null)
18
+ return ghInstalledCache;
19
+ try {
20
+ await safeExec('gh', ['--version']);
21
+ ghInstalledCache = true;
22
+ }
23
+ catch {
24
+ ghInstalledCache = false;
25
+ }
26
+ return ghInstalledCache;
27
+ }
28
+ export function _resetGhCache() {
29
+ ghInstalledCache = null;
30
+ }
31
+ export async function fetchGitHubIssue(owner, repo, number) {
32
+ try {
33
+ const stdout = await safeExec('gh', [
34
+ 'issue', 'view', String(number),
35
+ '--repo', `${owner}/${repo}`,
36
+ '--json', 'title,body,labels',
37
+ ]);
38
+ const data = JSON.parse(stdout);
39
+ return {
40
+ title: data.title ?? '',
41
+ body: data.body ?? '',
42
+ labels: (data.labels ?? []).map((l) => l.name),
43
+ };
44
+ }
45
+ catch {
46
+ return null;
47
+ }
48
+ }
49
+ export async function listRepoIssues(owner, repo, search, limit = 20) {
50
+ try {
51
+ const args = [
52
+ 'issue', 'list',
53
+ '--repo', `${owner}/${repo}`,
54
+ '--limit', String(limit),
55
+ '--json', 'number,title,state,labels,createdAt',
56
+ '--state', 'open',
57
+ ];
58
+ if (search) {
59
+ args.push('--search', search);
60
+ }
61
+ const stdout = await safeExec('gh', args);
62
+ const data = JSON.parse(stdout);
63
+ const issues = data.map((item) => ({
64
+ number: item.number,
65
+ title: item.title,
66
+ state: item.state.toLowerCase(),
67
+ labels: (item.labels ?? []).map((l) => l.name),
68
+ createdAt: item.createdAt ?? '',
69
+ }));
70
+ return { issues };
71
+ }
72
+ catch (err) {
73
+ const msg = err instanceof Error ? err.message : String(err);
74
+ if (msg.includes('auth') || msg.includes('login') || msg.includes('not logged')) {
75
+ return { issues: [], error: 'Run "gh auth login" to enable issue browsing' };
76
+ }
77
+ return { issues: [] };
78
+ }
79
+ }
80
+ export async function detectGitHubRemote(projectRoot) {
81
+ try {
82
+ const stdout = await safeExec('git', ['remote', 'get-url', 'origin'], projectRoot);
83
+ return parseGitHubRemote(stdout.trim());
84
+ }
85
+ catch {
86
+ return null;
87
+ }
88
+ }
89
+ const GITHUB_ISSUE_RE = /^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/(issues|pull)\/(\d+)\/?/;
90
+ export function isGitHubIssueUrl(input) {
91
+ const match = input.match(GITHUB_ISSUE_RE);
92
+ if (!match)
93
+ return null;
94
+ return { owner: match[1], repo: match[2], number: parseInt(match[4], 10) };
95
+ }
96
+ const SSH_REMOTE_RE = /^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/;
97
+ const HTTPS_REMOTE_RE = /^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/;
98
+ export function parseGitHubRemote(remoteUrl) {
99
+ const ssh = remoteUrl.match(SSH_REMOTE_RE);
100
+ if (ssh)
101
+ return { owner: ssh[1], repo: ssh[2] };
102
+ const https = remoteUrl.match(HTTPS_REMOTE_RE);
103
+ if (https)
104
+ return { owner: https[1], repo: https[2] };
105
+ return null;
106
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wiggum-cli",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "description": "AI-powered feature development loop CLI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -61,6 +61,9 @@
61
61
  "react": "^18.3.1",
62
62
  "zod": "^4.3.5"
63
63
  },
64
+ "overrides": {
65
+ "minimatch": ">=10.2.1"
66
+ },
64
67
  "devDependencies": {
65
68
  "@types/node": "^20.10.0",
66
69
  "@types/react": "^19.2.9",
@@ -1,5 +1,5 @@
1
1
  ## Context
2
- Study @.ralph/AGENTS.md for commands and patterns.
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
- Pick the next incomplete task from the implementation plan.
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
- Implement it following the patterns in AGENTS.md.
24
- Write tests for the implementation.
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 - mark task done with commit hash
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
- - One task per iteration
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
- Study @.ralph/AGENTS.md for commands and patterns.
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
- Study @.ralph/AGENTS.md for commands and patterns.
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
- - Plan only in this phase, do NOT implement
101
- - One task = one commit-sized unit of work
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
- Study @.ralph/AGENTS.md for commands and patterns.
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: 97 passing
56
- - [x] E2E tests: All scenarios passed via Playwright MCP
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 Phase 9]
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
- Respond with:
92
- - APPROVED if everything looks good
93
- - Or list specific issues with file:line references that need to be fixed
94
-
95
- IMPORTANT: After posting any PR review comment, you MUST print your final verdict as the LAST line of your output. Print exactly one of:
96
- VERDICT: APPROVED
97
- VERDICT: NOT APPROVED
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
- Study @.ralph/AGENTS.md for commands and patterns.
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
  )"