feat(create-prd): add --from flag to convert existing PRD documents#147
feat(create-prd): add --from flag to convert existing PRD documents#147KilimcininKorOglu wants to merge 3 commits intosubsy:mainfrom
Conversation
|
@KilimcininKorOglu is attempting to deploy a commit to the plgeek Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughThis PR introduces PRD conversion functionality via a new Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant CLI as create-prd Command
participant PrdChatApp
participant AIEngine as AI Engine
User->>CLI: Run with --from flag
CLI->>CLI: Read PRD file content
CLI->>CLI: Load convert-prd skill
CLI->>PrdChatApp: Pass fromFileContent prop
PrdChatApp->>PrdChatApp: Mount component
PrdChatApp->>PrdChatApp: Display CONVERSION_WELCOME_MESSAGE
Note over PrdChatApp: useEffect triggered (fromFileContent present)
PrdChatApp->>AIEngine: Send conversion prompt with PRD content
AIEngine-->>PrdChatApp: Stream converted user stories
PrdChatApp->>PrdChatApp: Collect streamed segments
PrdChatApp->>PrdChatApp: Update loading state
PrdChatApp->>PrdChatApp: Append result to chat
PrdChatApp-->>User: Display converted PRD in chat UI
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly Related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 markdownlint-cli2 (0.18.1)skills/ralph-tui-convert-prd/SKILL.mdmarkdownlint-cli2 v0.18.1 (markdownlint v0.38.0) Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@skills/ralph-tui-convert-prd/SKILL.md`:
- Around line 155-197: The SKILL.md interactive Steps 1–3 conflict with the
auto-conversion prompt in PrdChatApp.tsx that demands a single [PRD]...[/PRD]
output; update either the skill or the app: either (A) modify SKILL.md (steps or
top-level instructions) to include a non-interactive "auto-conversion" mode that
skips Step 1/2 when the incoming prompt equals the explicit string used in
PrdChatApp.tsx (match the prompt text "Output the converted PRD wrapped in
[PRD]...[/PRD]") and produce the full converted PRD directly, or (B) change the
PrdChatApp.tsx prompt to allow the multi-step interactive flow (e.g., request
clarifying questions first) so the skill can ask Steps 1–2; adjust the control
logic that dispatches the prompt so it signals either interactive or auto mode
accordingly (refer to SKILL.md steps and the prompt text in PrdChatApp.tsx to
locate the code to change).
In `@src/commands/create-prd.tsx`:
- Around line 368-400: Detected conflicting flags: when parsedArgs.fromFile is
used we set parsedArgs.prdSkillSource via loadConvertPrdSkill(), but a later
block that reads parsedArgs.prdSkill can overwrite it. Add mutual-exclusivity
validation early (before loading the convert skill) that checks if
parsedArgs.fromFile && parsedArgs.prdSkill and if so prints an error and exits;
reference parsedArgs.fromFile, parsedArgs.prdSkill, parsedArgs.prdSkillSource
and loadConvertPrdSkill to locate the relevant logic to change.
🧹 Nitpick comments (1)
src/tui/components/PrdChatApp.tsx (1)
330-397: Consider adding error recovery for the auto-conversion flow.The auto-conversion implementation is solid with proper guards and cleanup. However, if conversion fails, users are left with an error state and no clear recovery path since the guard prevents re-triggering.
A few observations:
Line 356: The non-null assertion
engineRef.current!is safe here due to the guard at line 332, but could be cleaner with an early return pattern.No retry mechanism: If the AI agent fails transiently, users must restart the entire command.
Dependency array: The effect depends only on
fromFileContent, but internally usesengineRef. SinceengineRefis stable (created once), this is fine, but worth noting.Minor improvement for null safety
const triggerConversion = async () => { + const engine = engineRef.current; + if (!engine) return; + setIsLoading(true); setLoadingStatus('Analysing PRD document...'); // ... try { - const result = await engineRef.current!.sendMessage(conversionPrompt, { + const result = await engine.sendMessage(conversionPrompt, {
| ## Conversion Process | ||
|
|
||
| ### Step 1: Document Analysis | ||
|
|
||
| First, scan the document and identify: | ||
| - Document title/name | ||
| - Main sections and structure | ||
| - Number of potential user stories | ||
| - Technology stack mentioned | ||
|
|
||
| Report to user: | ||
| ``` | ||
| I've analyzed your PRD. Here's what I found: | ||
|
|
||
| - **Title:** [extracted title] | ||
| - **Sections:** [count] main feature areas | ||
| - **Estimated Stories:** [count] user stories | ||
| - **Tech Stack:** [if mentioned] | ||
|
|
||
| I'll now convert this to ralph-tui format. Do you want me to: | ||
| A. Proceed with conversion (recommended) | ||
| B. Ask clarifying questions first | ||
| C. Focus on specific sections only | ||
| ``` | ||
|
|
||
| ### Step 2: Quality Gates Question | ||
|
|
||
| Ask about quality gates: | ||
| ``` | ||
| What quality commands should pass for each story? | ||
| A. bun run typecheck && bun run build | ||
| B. npm run typecheck && npm run lint | ||
| C. pnpm typecheck && pnpm lint | ||
| D. Other: [specify] | ||
| ``` | ||
|
|
||
| ### Step 3: Conversion | ||
|
|
||
| - Extract features → user stories | ||
| - Generate acceptance criteria | ||
| - Assign priorities and dependencies | ||
| - Output wrapped in `[PRD]...[/PRD]` | ||
|
|
There was a problem hiding this comment.
Interactive steps may conflict with auto-conversion flow.
The skill defines a multi-step interactive process (Steps 1-3) where the AI asks for user input before proceeding. However, the auto-conversion flow in PrdChatApp.tsx sends a single prompt and expects the converted PRD in the response.
The prompt at lines 342-353 in PrdChatApp.tsx instructs:
"Output the converted PRD wrapped in [PRD]...[/PRD] markers."
This may conflict with Step 1 and Step 2 here which expect the AI to ask clarifying questions first. Consider either:
- Adding guidance to skip interactive steps when the prompt explicitly requests direct conversion
- Updating the auto-conversion prompt to align with the interactive flow
🤖 Prompt for AI Agents
In `@skills/ralph-tui-convert-prd/SKILL.md` around lines 155 - 197, The SKILL.md
interactive Steps 1–3 conflict with the auto-conversion prompt in PrdChatApp.tsx
that demands a single [PRD]...[/PRD] output; update either the skill or the app:
either (A) modify SKILL.md (steps or top-level instructions) to include a
non-interactive "auto-conversion" mode that skips Step 1/2 when the incoming
prompt equals the explicit string used in PrdChatApp.tsx (match the prompt text
"Output the converted PRD wrapped in [PRD]...[/PRD]") and produce the full
converted PRD directly, or (B) change the PrdChatApp.tsx prompt to allow the
multi-step interactive flow (e.g., request clarifying questions first) so the
skill can ask Steps 1–2; adjust the control logic that dispatches the prompt so
it signals either interactive or auto mode accordingly (refer to SKILL.md steps
and the prompt text in PrdChatApp.tsx to locate the code to change).
| // Handle --from flag: load file content and use convert skill | ||
| if (parsedArgs.fromFile) { | ||
| const fromPath = resolve(cwd, parsedArgs.fromFile); | ||
|
|
||
| try { | ||
| await access(fromPath, constants.R_OK); | ||
| } catch { | ||
| console.error(`Error: Input file not found: ${fromPath}`); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| try { | ||
| parsedArgs.fromFileContent = await readFile(fromPath, 'utf-8'); | ||
| console.log(`Converting PRD from: ${fromPath}`); | ||
| console.log(`File size: ${parsedArgs.fromFileContent.length} characters`); | ||
| console.log(''); | ||
| } catch (error) { | ||
| console.error( | ||
| `Error: Failed to read input file: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| // Use the convert skill instead of the regular prd skill | ||
| try { | ||
| parsedArgs.prdSkillSource = await loadConvertPrdSkill(); | ||
| } catch (error) { | ||
| console.error( | ||
| `Error: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| process.exit(1); | ||
| } | ||
| } |
There was a problem hiding this comment.
Potential overwrite of prdSkillSource when both --from and --prd-skill are specified.
If a user specifies both --from ./file.md and --prd-skill custom-skill, the code at lines 391-399 sets prdSkillSource from the convert skill, but the subsequent block at lines 402-414 will overwrite it with the custom skill. This may be intentional (custom skill takes precedence), but could lead to unexpected behaviour where the conversion skill is ignored.
Consider either:
- Adding mutual exclusivity validation between
--fromand--prd-skill - Documenting the precedence behaviour in the help text
Suggested validation
+ // Validate mutually exclusive options
+ if (parsedArgs.fromFile && parsedArgs.prdSkill) {
+ console.error('Error: --from and --prd-skill cannot be used together.');
+ process.exit(1);
+ }
+
// Handle --from flag: load file content and use convert skill
if (parsedArgs.fromFile) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Handle --from flag: load file content and use convert skill | |
| if (parsedArgs.fromFile) { | |
| const fromPath = resolve(cwd, parsedArgs.fromFile); | |
| try { | |
| await access(fromPath, constants.R_OK); | |
| } catch { | |
| console.error(`Error: Input file not found: ${fromPath}`); | |
| process.exit(1); | |
| } | |
| try { | |
| parsedArgs.fromFileContent = await readFile(fromPath, 'utf-8'); | |
| console.log(`Converting PRD from: ${fromPath}`); | |
| console.log(`File size: ${parsedArgs.fromFileContent.length} characters`); | |
| console.log(''); | |
| } catch (error) { | |
| console.error( | |
| `Error: Failed to read input file: ${error instanceof Error ? error.message : String(error)}` | |
| ); | |
| process.exit(1); | |
| } | |
| // Use the convert skill instead of the regular prd skill | |
| try { | |
| parsedArgs.prdSkillSource = await loadConvertPrdSkill(); | |
| } catch (error) { | |
| console.error( | |
| `Error: ${error instanceof Error ? error.message : String(error)}` | |
| ); | |
| process.exit(1); | |
| } | |
| } | |
| // Validate mutually exclusive options | |
| if (parsedArgs.fromFile && parsedArgs.prdSkill) { | |
| console.error('Error: --from and --prd-skill cannot be used together.'); | |
| process.exit(1); | |
| } | |
| // Handle --from flag: load file content and use convert skill | |
| if (parsedArgs.fromFile) { | |
| const fromPath = resolve(cwd, parsedArgs.fromFile); | |
| try { | |
| await access(fromPath, constants.R_OK); | |
| } catch { | |
| console.error(`Error: Input file not found: ${fromPath}`); | |
| process.exit(1); | |
| } | |
| try { | |
| parsedArgs.fromFileContent = await readFile(fromPath, 'utf-8'); | |
| console.log(`Converting PRD from: ${fromPath}`); | |
| console.log(`File size: ${parsedArgs.fromFileContent.length} characters`); | |
| console.log(''); | |
| } catch (error) { | |
| console.error( | |
| `Error: Failed to read input file: ${error instanceof Error ? error.message : String(error)}` | |
| ); | |
| process.exit(1); | |
| } | |
| // Use the convert skill instead of the regular prd skill | |
| try { | |
| parsedArgs.prdSkillSource = await loadConvertPrdSkill(); | |
| } catch (error) { | |
| console.error( | |
| `Error: ${error instanceof Error ? error.message : String(error)}` | |
| ); | |
| process.exit(1); | |
| } | |
| } |
🤖 Prompt for AI Agents
In `@src/commands/create-prd.tsx` around lines 368 - 400, Detected conflicting
flags: when parsedArgs.fromFile is used we set parsedArgs.prdSkillSource via
loadConvertPrdSkill(), but a later block that reads parsedArgs.prdSkill can
overwrite it. Add mutual-exclusivity validation early (before loading the
convert skill) that checks if parsedArgs.fromFile && parsedArgs.prdSkill and if
so prints an error and exits; reference parsedArgs.fromFile,
parsedArgs.prdSkill, parsedArgs.prdSkillSource and loadConvertPrdSkill to locate
the relevant logic to change.
Summary
Adds the ability to convert existing PRD documents to ralph-tui format using the
--fromflag.Why
I have pre-made PRD.md files for different ideas. Instead of recreating them, it's more practical to convert them to ralph-tui format. And there might be other people like me too (:
Changes
New Skill
skills/ralph-tui-convert-prd/SKILL.md- AI skill for analyzing and converting external PRD documents to ralph-tui format with structured user storiesCommand Updates
--from <file>/-i <file>flag tocreate-prdcommand--fromis specifiedUI Updates
PrdChatAppnow acceptsfromFileContentprop--frommodeUsage
How It Works
[PRD]...[/PRD]markerstasks/prd-<feature-name>.mdSummary by CodeRabbit
Release Notes
New Features
✏️ Tip: You can customize this high-level summary in your review settings.