-
Notifications
You must be signed in to change notification settings - Fork 489
Description
Bug: Spec Regeneration Produces Incorrect Output and Creates Duplicate Files
Summary
When using the "Regenerate" button in the Spec Editor, two issues occur:
- The
.automaker/app_spec.txtfile contains only Claude's conversational summary (~37 lines) instead of the comprehensive XML specification (~593 lines) - A second file
app_spec.txtis created in the project root (not in.automaker/) with the correct XML content
Steps to Reproduce
- Open a project that already has an
app_spec.txtfile - Navigate to the Spec Editor
- Click the "Regenerate" button in the header
- Fill in the project definition and click "Regenerate Spec"
- Wait for generation to complete
- Check both locations:
.automaker/app_spec.txt- Contains summary (wrong){project}/app_spec.txt- Contains XML (correct but wrong location)
Expected Behavior
- Only ONE file should be created:
.automaker/app_spec.txt - That file should contain the comprehensive XML specification
Actual Behavior
.automaker/app_spec.txtcontains Claude's conversational summary:Perfect! I have successfully created a comprehensive project specification...{project}/app_spec.txt(root) contains the actual XML specification
Root Cause Analysis
Bug #1: XML Content Overwritten by Summary Message
File: apps/server/src/routes/app-spec/generate-spec.ts
Lines: 164-176
The stream processing code correctly accumulates the XML specification from Claude's text blocks into responseText. However, when the SDK emits a final result message with subtype: "success", the code overwrites the accumulated XML:
// Lines 164-176 - BUG #1
} else if (msg.type === "result" && (msg as any).subtype === "success") {
// Only use result if it has content, otherwise keep accumulated text
if ((msg as any).result && (msg as any).result.length > 0) {
logger.info("Using result value as responseText");
responseText = (msg as any).result; // <-- OVERWRITES the good XML!
}
}What happens:
- Claude streams the XML spec as multiple
textblocks (accumulated correctly) - At the end, SDK emits a
resultmessage with Claude's conversational summary - Line 173 overwrites the XML with this summary
- The summary is saved to
.automaker/app_spec.txt(line 220)
Bug #2: SDK Permission Mode Creates File in Project Root
File: apps/server/src/lib/sdk-options.ts
Lines: 122-126
function getBaseOptions(): Partial<Options> {
return {
permissionMode: "acceptEdits", // <-- BUG #2: Auto-accepts file writes!
};
}This permissionMode: "acceptEdits" is inherited by createSpecGenerationOptions(), causing the Claude Agent SDK to auto-accept file write operations.
Why this creates a file in project root:
- Spec generation calls SDK with
cwd: projectPath(the project root) permissionMode: "acceptEdits"auto-approves file operations- Even though
allowedToolsonly includes["Read", "Glob", "Grep"], the SDK may execute write operations based on Claude's response content - Claude's response mentions saving to
app_spec.txt(without.automaker/path) - SDK writes the file to
cwd(project root) based on Claude's implicit instruction
The contradiction: Spec generation should be read-only (TOOL_PRESETS.specGeneration is ["Read", "Glob", "Grep"]), but permissionMode: "acceptEdits" overrides this restriction.
Suggested Fixes
Fix #1: Don't Overwrite Accumulated XML Content
In apps/server/src/routes/app-spec/generate-spec.ts, replace lines 164-176:
Option A: Validate XML Before Using Result (Recommended)
} else if (msg.type === "result" && (msg as any).subtype === "success") {
const result = (msg as any).result;
// Only use result if responseText is empty AND result contains valid XML
if ((!responseText || responseText.trim().length === 0) &&
result && result.trim().startsWith("<project_specification>")) {
responseText = result;
}
// Otherwise keep the accumulated responseText which has the XML
}Option B: Never Overwrite Accumulated Content
} else if (msg.type === "result" && (msg as any).subtype === "success") {
logger.info("Received success result");
// Don't overwrite - responseText already has the accumulated XML
logger.info(`Final responseText length: ${responseText.length}`);
}Fix #2: Override Permission Mode for Spec Generation
In apps/server/src/lib/sdk-options.ts, modify createSpecGenerationOptions():
export function createSpecGenerationOptions(
config: CreateSdkOptionsConfig
): Options {
return {
...getBaseOptions(),
model: getModelForUseCase("spec", config.model),
maxTurns: MAX_TURNS.maximum,
cwd: config.cwd,
allowedTools: [...TOOL_PRESETS.specGeneration],
permissionMode: "default", // <-- FIX: Override to prevent auto-writes
...(config.systemPrompt && { systemPrompt: config.systemPrompt }),
...(config.abortController && { abortController: config.abortController }),
};
}Or alternatively, use permissionMode: "bypassPermissions" if the SDK supports it for read-only operations.
Files to Modify
| File | Bug | Change |
|---|---|---|
apps/server/src/routes/app-spec/generate-spec.ts |
#1 | Fix lines 164-176 to preserve accumulated XML |
apps/server/src/lib/sdk-options.ts |
#2 | Override permissionMode in createSpecGenerationOptions() |
Testing Checklist
- Test "Create" flow for new projects
- Test "Regenerate" flow for existing projects
- Verify only ONE file is created:
.automaker/app_spec.txt - Verify the file contains valid XML starting with
<project_specification> - Verify NO file is created in project root
- Check server logs to confirm correct content is being saved
Priority
High - This bug makes the Regenerate feature non-functional and creates unexpected files in user projects.
Labels
bug, spec-editor, high-priority, claude-sdk, file-permissions