ralph-mcp 1.0.11 → 1.0.13

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.
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import notifier from "node-notifier";
3
- import { appendFile, mkdir } from "fs/promises";
3
+ import { appendFile, mkdir, readFile, writeFile } from "fs/promises";
4
4
  import { existsSync } from "fs";
5
5
  import { join, dirname } from "path";
6
6
  import { areDependenciesSatisfied, findExecutionByBranch, findExecutionsDependingOn, findMergeQueueItemByExecutionId, findUserStoryById, insertMergeQueueItem, listMergeQueue, listUserStoriesByExecutionId, updateExecution, updateUserStory, } from "../store/state.js";
@@ -21,6 +21,54 @@ function formatDate(date) {
21
21
  const mm = pad(date.getMinutes());
22
22
  return `${yyyy}-${MM}-${dd} ${HH}:${mm}`;
23
23
  }
24
+ /**
25
+ * Extract Codebase Pattern from notes if present.
26
+ * Looks for "**Codebase Pattern:**" section in the notes.
27
+ */
28
+ function extractCodebasePattern(notes) {
29
+ const match = notes.match(/\*\*Codebase Pattern:\*\*\s*(.+?)(?=\n\*\*|\n##|$)/is);
30
+ if (match && match[1].trim()) {
31
+ return match[1].trim();
32
+ }
33
+ return null;
34
+ }
35
+ /**
36
+ * Update the Codebase Patterns section at the top of ralph-progress.md.
37
+ * Creates the section if it doesn't exist.
38
+ */
39
+ async function updateCodebasePatterns(progressPath, newPattern) {
40
+ let content = "";
41
+ if (existsSync(progressPath)) {
42
+ content = await readFile(progressPath, "utf-8");
43
+ }
44
+ const patternsSectionHeader = "## Codebase Patterns\n";
45
+ const patternLine = `- ${newPattern}\n`;
46
+ if (content.includes(patternsSectionHeader)) {
47
+ // Find the end of the Codebase Patterns section (next ## or end of patterns)
48
+ const sectionStart = content.indexOf(patternsSectionHeader);
49
+ const sectionContentStart = sectionStart + patternsSectionHeader.length;
50
+ // Find next section (## that's not Codebase Patterns)
51
+ const nextSectionMatch = content.slice(sectionContentStart).match(/\n## /);
52
+ const sectionEnd = nextSectionMatch
53
+ ? sectionContentStart + nextSectionMatch.index
54
+ : content.length;
55
+ // Check if pattern already exists (avoid duplicates)
56
+ const existingPatterns = content.slice(sectionContentStart, sectionEnd);
57
+ if (!existingPatterns.includes(newPattern)) {
58
+ // Insert new pattern at the end of the patterns section
59
+ const before = content.slice(0, sectionEnd);
60
+ const after = content.slice(sectionEnd);
61
+ content = before + patternLine + after;
62
+ await writeFile(progressPath, content, "utf-8");
63
+ }
64
+ }
65
+ else {
66
+ // Create new Codebase Patterns section at the top
67
+ const newSection = patternsSectionHeader + patternLine + "\n";
68
+ content = newSection + content;
69
+ await writeFile(progressPath, content, "utf-8");
70
+ }
71
+ }
24
72
  export async function update(input) {
25
73
  // Find execution by branch
26
74
  const exec = await findExecutionByBranch(input.branch);
@@ -49,6 +97,11 @@ export async function update(input) {
49
97
  const timestamp = formatDate(new Date());
50
98
  const notesContent = input.notes || story.notes || "No notes provided.";
51
99
  const entry = `## [${timestamp}] ${story.storyId}: ${story.title}\n${notesContent}\n\n`;
100
+ // Extract and consolidate Codebase Pattern if present
101
+ const pattern = extractCodebasePattern(notesContent);
102
+ if (pattern) {
103
+ await updateCodebasePatterns(progressPath, pattern);
104
+ }
52
105
  await appendFile(progressPath, entry, "utf-8");
53
106
  }
54
107
  catch (e) {
@@ -57,21 +57,55 @@ ${progressLog ? `## Progress & Learnings\n${progressLog}\n` : ""}
57
57
  ## Pending User Stories
58
58
  ${storiesText}
59
59
 
60
+ ## Story Size Check (CRITICAL)
61
+
62
+ Before implementing, verify the story is small enough to complete in ONE context window.
63
+
64
+ **Right-sized stories:**
65
+ - Add a database column and migration
66
+ - Add a UI component to an existing page
67
+ - Update a server action with new logic
68
+ - Add a filter dropdown to a list
69
+
70
+ **Too big (should have been split):**
71
+ - "Build the entire dashboard" → schema, queries, UI components, filters
72
+ - "Add authentication" → schema, middleware, login UI, session handling
73
+ - "Refactor the API" → one story per endpoint
74
+
75
+ **If a story seems too big:** Complete what you can, commit it, then call \`ralph_update\` with \`passes: false\` and notes explaining what remains. Do NOT produce broken code trying to finish everything.
76
+
60
77
  ## Instructions
61
78
 
62
79
  1. Work on ONE user story at a time, starting with the highest priority.
63
- 2. ${progressLog ? "Review the 'Progress & Learnings' section above to understand previous decisions and context." : "Check if 'ralph-progress.md' exists and review it for context."}
80
+ 2. ${progressLog ? "Review the 'Progress & Learnings' section above - especially the 'Codebase Patterns' section at the top." : "Check if 'ralph-progress.md' exists and review it for context."}
64
81
  3. Implement the feature to satisfy all acceptance criteria.
65
- 4. Run quality checks: \`pnpm check-types\` and \`pnpm --filter api build\` (adjust command for the specific repo structure if needed).
66
- 5. Commit changes with message: \`feat: [${pendingStories[0].storyId}] - ${pendingStories[0].title}\`
67
- 6. After completing a story, call \`ralph_update\` to mark it as passed:
68
- \`ralph_update({ branch: "${branch}", storyId: "${pendingStories[0].storyId}", passes: true, notes: "Brief summary of implementation, key decisions, and any learnings." })\`
69
- 7. Continue to the next story until all are complete.
70
-
71
- ## Quality Requirements
72
- - ALL commits must pass typecheck and build
82
+ 4. Run quality checks: \`pnpm check-types\` and \`pnpm --filter api build\` (adjust for repo structure).
83
+ 5. **Browser Testing (UI stories)**: If the story changes UI, verify in browser using Chrome DevTools MCP or similar tools. A frontend story is NOT complete until visually verified.
84
+ 6. Commit changes with message: \`feat: [${pendingStories[0].storyId}] - ${pendingStories[0].title}\`
85
+ 7. **Update Directory CLAUDE.md**: If you discovered reusable patterns, add them to the CLAUDE.md in the directory you modified (create if needed). Only add genuinely reusable knowledge, not story-specific details.
86
+ 8. Call \`ralph_update\` to mark the story as passed. Include detailed notes:
87
+ \`ralph_update({ branch: "${branch}", storyId: "${pendingStories[0].storyId}", passes: true, notes: "..." })\`
88
+ 9. Continue to the next story until all are complete.
89
+
90
+ ## Notes Format for ralph_update
91
+
92
+ Provide structured learnings in the \`notes\` field:
93
+ \`\`\`
94
+ **Implemented:** Brief summary of what was done
95
+ **Files changed:** List key files
96
+ **Learnings:**
97
+ - Patterns discovered (e.g., "this codebase uses X for Y")
98
+ - Gotchas encountered (e.g., "don't forget to update Z when changing W")
99
+ - Useful context for future iterations
100
+ **Codebase Pattern:** (if discovered a general pattern worth consolidating)
101
+ \`\`\`
102
+
103
+ ## Quality Requirements (Feedback Loops)
104
+ - ALL commits must pass typecheck and build - broken code compounds across iterations
73
105
  - Keep changes focused and minimal
74
106
  - Follow existing code patterns
107
+ - UI changes must be browser-verified
108
+ - Do NOT commit broken code - if checks fail, fix before committing
75
109
 
76
110
  ## Stop Condition
77
111
  When all stories are complete, report completion.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ralph-mcp",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "MCP server for autonomous PRD execution with Claude Code. Git worktree isolation, progress tracking, auto-merge.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",