Skip to content

Commit f0fef72

Browse files
fix: include review context when custom fix instructions are provided (#395)
## Summary - When a user provides custom instructions via Shift+F in the TUI fix modal, the custom prompt was completely replacing the review context instead of being appended to it - The fix agent received only the user's short instructions with no knowledge of what the review actually found, causing it to search aimlessly and eventually give up - Custom instructions are now combined with the review findings via `buildFixPromptWithInstructions`, so the agent sees both the original review output and the user's additional guidance Closes #387 ## Test plan - [x] New test: `"custom prompt includes review context"` verifies stored prompt contains both review output and custom instructions - [x] All 3521 existing tests pass - [ ] Manual: Shift+F on a review, enter custom instructions, verify agent log shows review findings in the prompt 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7fa5c85 commit f0fef72

File tree

2 files changed

+62
-6
lines changed

2 files changed

+62
-6
lines changed

internal/daemon/server.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,8 +1901,8 @@ func (s *Server) handleFixJob(w http.ResponseWriter, r *http.Request) {
19011901
}
19021902

19031903
// Build the fix prompt
1904-
fixPrompt := req.Prompt
1905-
if fixPrompt == "" && req.StaleJobID > 0 {
1904+
fixPrompt := ""
1905+
if req.StaleJobID > 0 {
19061906
// Server-side rebase: look up stale patch from DB and build rebase prompt
19071907
staleJob, err := s.db.GetJobByID(req.StaleJobID)
19081908
if err != nil {
@@ -1943,7 +1943,11 @@ func (s *Server) handleFixJob(w http.ResponseWriter, r *http.Request) {
19431943
writeError(w, http.StatusBadRequest, "parent job has no review to fix")
19441944
return
19451945
}
1946-
fixPrompt = buildFixPrompt(review.Output)
1946+
if req.Prompt != "" {
1947+
fixPrompt = buildFixPromptWithInstructions(review.Output, req.Prompt)
1948+
} else {
1949+
fixPrompt = buildFixPrompt(review.Output)
1950+
}
19471951
}
19481952

19491953
// Resolve agent for fix workflow
@@ -2154,18 +2158,29 @@ func (s *Server) handleActivity(w http.ResponseWriter, r *http.Request) {
21542158

21552159
// buildFixPrompt constructs a prompt for fixing review findings.
21562160
func buildFixPrompt(reviewOutput string) string {
2157-
return "# Fix Request\n\n" +
2161+
return buildFixPromptWithInstructions(reviewOutput, "")
2162+
}
2163+
2164+
// buildFixPromptWithInstructions constructs a fix prompt that includes the review
2165+
// findings and optional user-provided instructions.
2166+
func buildFixPromptWithInstructions(reviewOutput, userInstructions string) string {
2167+
prompt := "# Fix Request\n\n" +
21582168
"An analysis was performed and produced the following findings:\n\n" +
21592169
"## Analysis Findings\n\n" +
2160-
reviewOutput +
2161-
"\n\n## Instructions\n\n" +
2170+
reviewOutput + "\n\n"
2171+
if userInstructions != "" {
2172+
prompt += "## Additional Instructions\n\n" +
2173+
userInstructions + "\n\n"
2174+
}
2175+
prompt += "## Instructions\n\n" +
21622176
"Please apply the suggested changes from the analysis above. " +
21632177
"Make the necessary edits to address each finding. " +
21642178
"Focus on the highest priority items first.\n\n" +
21652179
"After making changes:\n" +
21662180
"1. Verify the code still compiles/passes linting\n" +
21672181
"2. Run any relevant tests to ensure nothing is broken\n" +
21682182
"3. Stage the changes with git add but do NOT commit — the changes will be captured as a patch\n"
2183+
return prompt
21692184
}
21702185

21712186
// buildRebasePrompt constructs a prompt for re-applying a stale patch to current HEAD.

internal/daemon/server_ops_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,47 @@ func TestHandleFixJobStaleValidation(t *testing.T) {
505505
}
506506
})
507507

508+
t.Run("custom prompt includes review context", func(t *testing.T) {
509+
req := testutil.MakeJSONRequest(
510+
t, http.MethodPost, "/api/job/fix",
511+
fixJobRequest{
512+
ParentJobID: reviewJob.ID,
513+
Prompt: "Ignore the security concern, it's only a testing binary.",
514+
},
515+
)
516+
w := httptest.NewRecorder()
517+
server.handleFixJob(w, req)
518+
519+
if w.Code != http.StatusCreated {
520+
t.Fatalf(
521+
"Expected 201 for fix enqueue with custom prompt, got %d: %s",
522+
w.Code, w.Body.String(),
523+
)
524+
}
525+
526+
var fixJob storage.ReviewJob
527+
testutil.DecodeJSON(t, w, &fixJob)
528+
529+
stored, err := db.GetJobByID(fixJob.ID)
530+
if err != nil {
531+
t.Fatalf("GetJobByID(%d): %v", fixJob.ID, err)
532+
}
533+
534+
// The stored prompt must contain both the review output AND the custom instructions
535+
if !strings.Contains(stored.Prompt, "FAIL: issues found") {
536+
t.Fatalf(
537+
"Expected fix prompt to contain review output, got:\n%s",
538+
stored.Prompt,
539+
)
540+
}
541+
if !strings.Contains(stored.Prompt, "Ignore the security concern") {
542+
t.Fatalf(
543+
"Expected fix prompt to contain custom instructions, got:\n%s",
544+
stored.Prompt,
545+
)
546+
}
547+
})
548+
508549
t.Run("fix job as parent is rejected", func(t *testing.T) {
509550
// Create a fix job and try to use it as a parent
510551
fixJob, _ := db.EnqueueJob(storage.EnqueueOpts{

0 commit comments

Comments
 (0)