From 176b9855bfaf0c7465dea8d683016b8ef3fcc5d1 Mon Sep 17 00:00:00 2001 From: mika kuns Date: Thu, 4 Jun 2026 16:53:41 +0200 Subject: [PATCH] feat(prompt): focused custom prompt for improvement children so they stay narrow --- src/ClaudeDo.Data/PromptFiles.cs | 19 ++++++++++++++++++- src/ClaudeDo.Worker/Runner/TaskRunner.cs | 7 ++++++- .../ClaudeDo.Data.Tests/SystemPromptTests.cs | 9 +++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/ClaudeDo.Data/PromptFiles.cs b/src/ClaudeDo.Data/PromptFiles.cs index 005de07..060bb1f 100644 --- a/src/ClaudeDo.Data/PromptFiles.cs +++ b/src/ClaudeDo.Data/PromptFiles.cs @@ -2,7 +2,7 @@ using System.Text; namespace ClaudeDo.Data; -public enum PromptKind { System, Planning, PlanningInitial, Retry, DailyPrep, WeeklyReport } +public enum PromptKind { System, Planning, PlanningInitial, Retry, DailyPrep, WeeklyReport, ImprovementChild } public static class PromptFiles { @@ -16,6 +16,7 @@ public static class PromptFiles PromptKind.Retry => Path.Combine(Root, "retry.md"), PromptKind.DailyPrep => Path.Combine(Root, "daily-prep.md"), PromptKind.WeeklyReport => Path.Combine(Root, "weekly-report.md"), + PromptKind.ImprovementChild => Path.Combine(Root, "improvement-child.md"), _ => throw new ArgumentOutOfRangeException(nameof(kind)) }; @@ -59,6 +60,7 @@ public static class PromptFiles PromptKind.Retry => RetryDefault, PromptKind.DailyPrep => DailyPrepDefault, PromptKind.WeeklyReport => WeeklyReportDefault, + PromptKind.ImprovementChild => ImprovementChildDefault, _ => "" }; @@ -114,6 +116,21 @@ public static class PromptFiles blockers, not for routine decisions you can make yourself. """; + private const string ImprovementChildDefault = """ + # Out-of-scope follow-up + + You are an improvement follow-up that another task filed via SuggestImprovement. + It was deliberately scoped narrow. Do EXACTLY what this task's title and + description ask — nothing more. + + - Make the smallest change that satisfies the task. No opportunistic refactors, + renames, reformatting, or "while I'm here" cleanup beyond what is asked. + - Touch as few files as possible. Do not restructure unrelated code. + - Do NOT file further improvements — improvements are one layer deep. + - Verify the build and relevant tests before finishing, and report what you ran. + - Make one focused commit using the repository's commit-message convention. + """; + private const string PlanningSystemDefault = """ You are the planning assistant for ClaudeDo. Your job is to break a task into smaller, independently executable subtasks — the session ends by creating those diff --git a/src/ClaudeDo.Worker/Runner/TaskRunner.cs b/src/ClaudeDo.Worker/Runner/TaskRunner.cs index b0f62b6..53fda84 100644 --- a/src/ClaudeDo.Worker/Runner/TaskRunner.cs +++ b/src/ClaudeDo.Worker/Runner/TaskRunner.cs @@ -459,8 +459,13 @@ public sealed class TaskRunner var systemFile = PromptFiles.ReadOrDefault(PromptKind.System); + // Improvement children (filed via SuggestImprovement; CreatedBy == ParentTaskId) get a + // narrow follow-up prompt so they stay tightly scoped instead of doing "too much". + var isImprovementChild = task.ParentTaskId is not null && task.CreatedBy == task.ParentTaskId; + var improvementPrompt = isImprovementChild ? PromptFiles.ReadOrDefault(PromptKind.ImprovementChild) : null; + var instructions = MergeInstructions( - systemFile, global.DefaultClaudeInstructions, listConfig?.SystemPrompt, task.SystemPrompt); + systemFile, improvementPrompt, global.DefaultClaudeInstructions, listConfig?.SystemPrompt, task.SystemPrompt); return new ClaudeRunConfig( Model: task.Model ?? listConfig?.Model ?? global.DefaultModel, diff --git a/tests/ClaudeDo.Data.Tests/SystemPromptTests.cs b/tests/ClaudeDo.Data.Tests/SystemPromptTests.cs index 32cad1d..7ebacd4 100644 --- a/tests/ClaudeDo.Data.Tests/SystemPromptTests.cs +++ b/tests/ClaudeDo.Data.Tests/SystemPromptTests.cs @@ -12,4 +12,13 @@ public class SystemPromptTests Assert.Contains("Out-of-scope improvements", prompt); Assert.Contains("SuggestImprovement", prompt); } + + [Fact] + public void ImprovementChildDefault_is_present_and_scopes_narrow() + { + var prompt = PromptFiles.DefaultFor(PromptKind.ImprovementChild); + Assert.False(string.IsNullOrWhiteSpace(prompt)); + Assert.Contains("follow-up", prompt, StringComparison.OrdinalIgnoreCase); + Assert.Contains("nothing more", prompt, StringComparison.OrdinalIgnoreCase); + } }