feat: add seo category to template filters#142
Conversation
Read version dynamically from package.json instead of hardcoding '0.1.0'. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add ralph_list_presets tool to discover all 19 workflow presets by category - Add ralph_fetch_spec tool to preview specs from GitHub, Linear, Notion, and Figma without running the full coding loop - Improve all existing tool descriptions with detailed context for LLM clients - ralph_fetch_spec supports Figma modes (spec, tokens, components, content, assets) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add figma_to_code prompt for Figma design-to-code workflow with framework and mode selection (spec, tokens, components, content) - Add batch_issues prompt for processing multiple GitHub/Linear issues automatically with auto mode - Update fetch_and_build prompt to include Figma as a source option - Update fetch_and_build to use ralph_fetch_spec for preview before building Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add .ralph/activity.md as a readable MCP resource so Claude Desktop and other MCP clients can access loop execution history, timing data, and cost information. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 'seo' to the category filter options in CLI help text and docs, matching the new SEO & AEO templates added to ralph-templates. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds "seo" to template categories and CLI help; introduces new MCP tools (ralph_list_presets, ralph_fetch_spec), two prompts (figma_to_code, batch_issues), expands fetch_and_build to accept Figma, adds Activity Log resource mapping, and replaces hard-coded version with a getPackageVersion() util. Changes
Sequence Diagram(s)mermaid CLI->>MCP: invoke tool (e.g., ralph_fetch_spec / ralph_list_presets) Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
✔️ Bundle Size Analysis
Bundle breakdown |
Deploying ralph-starter with
|
| Latest commit: |
66f3748
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://6d13c497.ralph-starter.pages.dev |
| Branch Preview URL: | https://feat-seo-aeo-category.ralph-starter.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/mcp/resources.ts (1)
126-128:⚠️ Potential issue | 🟠 MajorPath traversal vulnerability in specs resource handler — sanitize resolved path
The specs handler allows directory traversal attacks. A crafted URI like
ralph://project/specs/../../IMPLEMENTATION_PLANbypasses the intended specs directory boundary, enabling unauthorized access to any.mdfile in the project. This is a genuine OWASP A01:2021 control failure.The issue occurs because
resourcePath.replace('specs/', '')performs simple string replacement without path normalization, andpath.join()resolves..sequences. TheexistsSync()check doesn't prevent traversal — it only blocks reading non-existent files.Implement the suggested guard to validate the resolved path stays within the specs directory:
🛡️ Suggested guard
if (resourcePath.startsWith('specs/')) { const specName = resourcePath.replace('specs/', ''); filePath = join(cwd, 'specs', `${specName}.md`); + const specsDir = join(cwd, 'specs'); + if (!filePath.startsWith(specsDir)) { + throw new Error(`Invalid spec path: ${resourcePath}`); + } } else {
🤖 Fix all issues with AI agents
In `@src/mcp/prompts.ts`:
- Around line 252-281: The 'batch_issues' prompt incorrectly instructs the LLM
to "use ralph_fetch_spec to preview the available issues" but ralph_fetch_spec
returns a single spec by identifier; update the prompt text in the batch_issues
case in src/mcp/prompts.ts to either (a) reference an existing issue-listing
tool (if one exists) or (b) instruct the model to call a new issue-listing tool
(e.g., ralph_list_issues) instead of ralph_fetch_spec; ensure the prompt still
directs the model to provide identifiers for each issue before calling
ralph_fetch_spec and keep ralph_run/auto mode instructions (ralph_run)
unchanged.
In `@src/mcp/server.ts`:
- Around line 18-27: The getPackageVersion implementation in getPackageVersion
(src/mcp/server.ts) duplicates fragile path logic that differs from src/cli.ts;
extract a single shared resolver (e.g., create src/utils/version.ts with a
robust getPackageVersion that walks up parent directories from
dirname(fileURLToPath(import.meta.url)), attempts to read package.json
candidates, caches the found version, and returns a sensible default), then
replace the local getPackageVersion implementations in both server.ts and cli.ts
to import and use this shared function (or alternatively replace both usages
with a build-time/version constant), ensuring the new resolver handles multiple
dist-depths and avoids silent mismatches.
In `@src/mcp/tools.ts`:
- Around line 454-457: The category filter currently uses a substring match
(category.toLowerCase().includes(filterCategory)), which can produce unintended
matches; update the check in the loop over allCategories to perform a normalized
strict equality (e.g., compare category.toLowerCase() === filterCategory) or, if
fuzzy matching is intentional for MCP ergonomics, add a clear inline comment
above the condition documenting that deliberate substring matching is desired;
locate the check in the loop that iterates over Object.entries(allCategories)
where filterCategory is tested and change the logic or add the explanatory
comment accordingly.
- Around line 477-499: The ralph_fetch_spec schema requires parsed.path but
handleFetchSpec never uses it; update handleFetchSpec to include parsed.path in
the options passed to fetchFromIntegration (same pattern as
handleInit/handlePlan/handleRun/handleStatus) so working-directory context is
preserved: add options.path = parsed.path when present before calling
fetchFromIntegration(parsed.source, parsed.identifier, options) (or if you
decide path is truly unused, remove path from ralph_fetch_spec instead—choose
one consistent fix).
- Create src/utils/version.ts with a robust version resolver that walks up parent directories, handles multiple dist depths, and caches the result - Replace duplicate getPackageVersion in cli.ts and mcp/server.ts with the shared import - Fix handleFetchSpec not passing parsed.path to fetchFromIntegration, preserving working-directory context Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@src/cli.ts`:
- Around line 261-264: The --category option currently accepts any string (only
documented in the description) so typos silently pass; replace the
.option('--category <name>', ...) usage with Commander’s Option-based API: call
.addOption(new Option('--category <name>', 'Filter by category
(...)').choices(['web-dev','blockchain','devops','mobile','tools','seo'])) so
valid values are centralized and validated automatically; use the Option class,
.addOption, and .choices() for this change.
In `@src/mcp/tools.ts`:
- Around line 189-241: getTools() currently returns raw JSON Schema objects for
ralph_list_presets and ralph_fetch_spec that duplicate the shape defined in
toolSchemas (Zod), creating a maintenance risk; change getTools() to
derive/serialize the JSON Schema from the corresponding Zod schemas in
toolSchemas (e.g., using zod-to-json-schema or Zod's z.toJSONSchema()), so
ralph_list_presets and ralph_fetch_spec JSON schemas are generated from their
Zod definitions rather than kept inline.
In `@src/utils/version.ts`:
- Around line 26-36: The loop currently accepts the first package.json with any
version; change it to also validate pkg.name against the expected package name
before setting cachedVersion. Modify the candidates loop in the function that
uses variables candidates, pkg and cachedVersion so it checks both pkg.version
and pkg.name === expectedPackageName (where expectedPackageName is obtained from
a stable source — e.g., an imported project package.json constant or a
configured constant) and only then return cachedVersion; otherwise continue to
the next candidate.
- Fix batch_issues prompt: use ralph_run with auto mode instead of incorrectly referencing ralph_fetch_spec for listing issues - Fix handleListPresets category filter: use strict equality instead of substring match to prevent unintended matches - handleFetchSpec already passes path to fetchFromIntegration (linter fix) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@src/mcp/prompts.ts`:
- Around line 233-244: The prompt template uses args?.framework in two places
with inconsistent casing (lowercase 'react' at args?.framework || 'react' and
capitalized 'React' in the prose), so add a small normalization step (e.g.,
compute a variable like normalizedFramework and displayFramework) near where the
prompt is built that derives a default and a nicely capitalized display string
from args?.framework; then replace occurrences of args?.framework in the
template with normalizedFramework for technical identifiers and displayFramework
for prose (references: args?.framework, the prompt text string that includes
"Framework: ${...}" and "build the ${...} implementation", and the ralph_run
mention).
In `@src/mcp/tools.ts`:
- Around line 433-436: handleListPresets currently calls
toolSchemas.ralph_list_presets.parse(args) but args can be undefined per MCP
spec; guard for undefined and pass an empty object to the Zod parser instead of
undefined so optional fields validate correctly. Update handleListPresets to
treat undefined args as {} before calling toolSchemas.ralph_list_presets.parse,
keeping the rest of the function and return shape intact; reference the
ralph_list_presets.parse call in handleListPresets to locate the change.
- Around line 484-488: The runtime truthiness check on parsed.path is dropping
valid empty-string values and is inconsistent with sibling handlers; either
remove the guard and always assign options.path = parsed.path to match
handleInit/handlePlan/handleRun, or enforce non-empty at the schema
(toolSchemas.ralph_fetch_spec) by adding a .min(1) (or equivalent) so
parsed.path can safely be assumed non-empty—update the code around the options
construction (the parsed.path check) and/or the ralph_fetch_spec schema
accordingly.
- Normalize framework casing in figma_to_code prompt (consistent display name) - Guard undefined args in handleListPresets with fallback to empty object - Enforce non-empty path in ralph_fetch_spec schema (.min(1)) and always assign path to options instead of truthiness check Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Fix all issues with AI agents
In `@src/mcp/prompts.ts`:
- Around line 255-284: The batch_issues prompt interpolates user-controlled args
(source, project, label) directly into the LLM prompt in the case 'batch_issues'
return object, creating a prompt-injection surface; sanitize these values before
interpolation (e.g., strip newlines and control characters, enforce a safe
whitelist/regex such as alphanumerics, dashes, underscores, or truncate to a max
length) or escape them so injected newlines/instructions cannot be injected into
the prompt, and then use the sanitized variables instead of args.* when building
the prompt content (references: the 'batch_issues' case and the args variables
used in the template).
- Around line 225-253: The framework display logic inside the 'figma_to_code'
case normalizes by capitalizing the first char but misformats acronyms/compound
names (e.g., 'nextjs' -> 'Nextjs', 'html' -> 'Html'); replace the current
displayFramework calculation (based on framework.charAt...) with a small
display-name map keyed by framework (e.g., 'nextjs' -> 'Next.js', 'html' ->
'HTML', 'react' -> 'React') and fall back to a sensible default capitalization;
also replace the nested ternary used to produce the human-readable mode text
(the string built from args?.mode in the user content) with a lookup object
(modeLabel or similar) mapping modes like 'tokens' -> 'design tokens',
'components' -> 'component structure', 'content' -> 'text content and IA',
default -> 'the full design specification' to improve readability and make
future additions easy; update the template to reference these new display
variables (displayFramework and modeLabel) where currently framework.charAt...
and the nested ternary are used.
In `@src/mcp/tools.ts`:
- Around line 477-499: handleFetchSpec passes parsed.identifier directly into
fetchFromIntegration (with parsed.source) which may be used to perform outbound
requests; update the integration implementations called by fetchFromIntegration
to validate and restrict identifiers: normalize and parse the identifier,
enforce allowed schemes/hosts or an integration-specific allowlist, block
private/internal IP ranges and localhost, reject data/file URIs, and apply
per-source domain/path constraints based on parsed.source to prevent SSRF and
unintended internal access. Ensure each integration returns a clear error on
invalid identifiers and add unit tests covering malicious host/scheme cases.
- Around line 57-61: The Zod schema for the `identifier` field currently lacks a
minimum-length guard so empty strings pass validation; update the `identifier`
schema (the symbol `identifier` in the same schema block as `path`) to include
`.min(1)` like `path` does, so empty identifiers are rejected early and won’t be
forwarded to `fetchFromIntegration` causing downstream integration errors.
- Around line 208-241: The JSON Schema for inputSchema.properties.path (used by
ralph_fetch_spec) is missing minLength: 1 and therefore diverges from the Zod
schema that enforces .min(1); update inputSchema.properties.path to include
"minLength": 1 so the JSON Schema and the Zod validation in ralph_fetch_spec
stay consistent and prevent empty-string submissions.
|
@coderabbitai resolve |
✅ Actions performedComments resolved and changes approved. |
Summary
seoto the--categoryfilter option in thetemplatecommandTest plan
ralph-starter template list --category seoshould show templates once ralph-templates PR is mergedralph-starter template --helpshowsseoin category list🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation