fix(prompts): correct five prompt claims that contradicted the tool allowlists
Audited all 12 prompt kinds against the code they drive. Every real defect sat on the boundary between prompt text and the --allowedTools the launcher passes. - Planning: "Use nothing else" after a six-tool list forbade the brainstorming Skill the same prompt demands two paragraphs earlier. WindowsTerminalLauncher allowlists mcp__claudedo__*,Read,Grep,Glob,WebFetch,WebSearch,Skill -- name them, and tell the planner to ground subtasks in the repo with Read/Grep/Glob. - System: SuggestImprovement is only allowlisted when ParentTaskId is null and PlanningPhase is None, and TaskRunMcpService throws for any child, but this prompt reaches every run. Planning children were told to use a tool they lack. - MergeHelperExecute: derived "effective max-turns" from task/list/preset by hand, which misses TaskRunner's MaxTurnsCeiling clamp. Call get_effective_run_config instead -- built for exactly this and reports the clamp. - MergeHelperExecute: quoted the override-slot error as the raw lowercase throw rather than the string ExternalMcpService actually surfaces. - Refine: listed Read/Grep/Glob unconditionally though RefinePrompt.BuildArgs only appends them when a repo is available. Two findings deliberately left open, both needing a code decision rather than a prompt edit: the System prompt's worktree claim is false for a list without a WorkingDir (task runs in a plain sandbox dir), and 'fable' is missing from both the prompt's cost ordering and ModelRegistry.ByCostAscending.
This commit is contained in:
@@ -243,6 +243,10 @@ public static class PromptFiles
|
||||
trivial/mechanical work, 'sonnet' for normal coding, 'opus' only for genuinely
|
||||
complex work (cheapest to most capable: haiku < sonnet < opus).
|
||||
|
||||
This tool only exists for a standalone top-level task. A child task or a task in a
|
||||
planning chain does not have it — improvements are one layer deep. If you don't have
|
||||
it, name the follow-up in your final report instead of trying to file it.
|
||||
|
||||
## Working in the repo
|
||||
- Read a file before editing it. Match the conventions already in this codebase —
|
||||
they override generic defaults.
|
||||
@@ -329,8 +333,13 @@ public static class PromptFiles
|
||||
until the user has approved the design.
|
||||
|
||||
You can ONLY shape this task's plan — you cannot edit files or touch other tasks.
|
||||
The tools available to you are: CreateChildTask, ListChildTasks, UpdateChildTask,
|
||||
DeleteChildTask, UpdatePlanningTask, and Finalize. Use nothing else.
|
||||
To shape it you have the ClaudeDo planning tools: CreateChildTask, ListChildTasks,
|
||||
UpdateChildTask, DeleteChildTask, UpdatePlanningTask and Finalize. You also have
|
||||
Skill (needed for the brainstorming skill above), Read, Grep, Glob, WebFetch and
|
||||
WebSearch. You do NOT have Write, Edit or Bash.
|
||||
|
||||
Use Read/Grep/Glob to ground the plan in the actual repo — a subtask that names the
|
||||
real files and symbols involved runs far better than one written from guesswork.
|
||||
|
||||
Once the design is approved, create the child tasks with CreateChildTask, then
|
||||
call Finalize. Keep each subtask concrete and self-contained with a clear
|
||||
@@ -405,8 +414,8 @@ public static class PromptFiles
|
||||
not already present in the current subtasks above.
|
||||
|
||||
Use ONLY these tools: mcp__claudedo__get_task, mcp__claudedo__update_task,
|
||||
mcp__claudedo__add_subtask, and read-only Read/Grep/Glob. When you have updated the
|
||||
task, stop.
|
||||
mcp__claudedo__add_subtask, and — only when a repository is available — read-only
|
||||
Read/Grep/Glob. When you have updated the task, stop.
|
||||
""";
|
||||
|
||||
private const string MergeHelperTriageDefault = """
|
||||
@@ -461,11 +470,11 @@ public static class PromptFiles
|
||||
Work the three phases in order. Do not start a phase before the previous one is finished.
|
||||
|
||||
## Phase 3 — Run
|
||||
Do NOT use run_task_now for a batch — there is a single override slot and the second call fails with "override slot busy".
|
||||
Do NOT use run_task_now for a batch — there is a single override slot and the second call fails with "Override slot busy. Try again later.".
|
||||
|
||||
Read get_app_settings and tell the user how many parallel execution slots are configured (maxParallelExecutions). If it is 1, say plainly that the tasks will execute one after another and that the value is changeable in ClaudeDo's settings.
|
||||
|
||||
For each surviving task, resolve the effective max-turns it will run with — task.MaxTurns, else the list's get_list_config MaxTurns, else the model's preset/global default — and report it. If a task looks substantial (several files, or one you just split off above) but its effective turns look low, say so and ask before queuing it; set_task_config/get_task_config let you raise it per task.
|
||||
For each surviving task, call get_effective_run_config(taskId) and report the max-turns it will ACTUALLY run with. Do not derive that from task/list/preset values yourself — the resolved value is clamped to a global ceiling, so a raw task or list setting can be higher than what runs. The tool reports the effective value, its source, the raw requested value and whether it was clamped. If a task looks substantial (several files, or one you just split off above) but its effective turns look low, say so and ask before queuing it; set_task_config raises it per task, though the ceiling still applies.
|
||||
|
||||
Then, for each surviving task:
|
||||
- Idle or Failed → update_task_status(id, "Queued"). For a Failed task ask first whether to reset_failed_task and re-queue it, or skip it.
|
||||
|
||||
@@ -206,11 +206,56 @@ public class PromptFilesTests
|
||||
[Fact]
|
||||
public void DefaultFor_merge_helper_checks_effective_max_turns_before_queuing()
|
||||
{
|
||||
// Must delegate to get_effective_run_config rather than re-deriving the
|
||||
// task/list/preset chain: TaskRunner.ResolveMaxTurns clamps the result to
|
||||
// AppSettings.MaxTurnsCeiling, so a hand-derived number can exceed what actually runs.
|
||||
var d = PromptFiles.DefaultFor(PromptKind.MergeHelperExecute);
|
||||
Assert.Contains("effective max-turns", d);
|
||||
Assert.Contains("get_list_config", d);
|
||||
Assert.Contains("get_effective_run_config", d);
|
||||
Assert.Contains("clamped", d);
|
||||
Assert.Contains("set_task_config", d);
|
||||
Assert.Contains("get_task_config", d);
|
||||
Assert.DoesNotContain("get_list_config", d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultFor_merge_helper_execute_quotes_the_override_slot_error_verbatim()
|
||||
{
|
||||
// ExternalMcpService.RunTaskNow rewraps OverrideSlotService's raw lowercase throw.
|
||||
var d = PromptFiles.DefaultFor(PromptKind.MergeHelperExecute);
|
||||
Assert.Contains("Override slot busy. Try again later.", d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultFor_system_scopes_suggest_improvement_to_top_level_tasks()
|
||||
{
|
||||
// TaskRunner only allowlists SuggestImprovement when ParentTaskId is null AND
|
||||
// PlanningPhase is None, and TaskRunMcpService throws for any child -- but this
|
||||
// prompt reaches every run, including planning children.
|
||||
var d = PromptFiles.DefaultFor(PromptKind.System);
|
||||
Assert.Contains("SuggestImprovement", d);
|
||||
Assert.Contains("standalone top-level task", d);
|
||||
Assert.Contains("improvements are one layer deep", d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultFor_planning_names_every_allowlisted_tool_and_claims_no_exclusivity()
|
||||
{
|
||||
// WindowsTerminalLauncher allowlists mcp__claudedo__*,Read,Grep,Glob,WebFetch,
|
||||
// WebSearch,Skill. The prompt used to say "Use nothing else" right after telling the
|
||||
// session to invoke the brainstorming skill -- forbidding its own first instruction.
|
||||
var d = PromptFiles.DefaultFor(PromptKind.Planning);
|
||||
Assert.DoesNotContain("Use nothing else", d);
|
||||
Assert.Contains("Skill", d);
|
||||
Assert.Contains("Grep", d);
|
||||
Assert.Contains("WebSearch", d);
|
||||
Assert.Contains("Write, Edit or Bash", d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultFor_refine_gates_the_read_tools_on_an_available_repo()
|
||||
{
|
||||
// RefinePrompt.BuildArgs only appends Read/Grep/Glob when canReadRepo is true.
|
||||
var d = PromptFiles.DefaultFor(PromptKind.Refine);
|
||||
Assert.Contains("only when a repository is available", d);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user