Phase 1 previously asked the user to confirm the absence of duplicates even when no candidate pair was found. The handler now decides that itself and moves straight to Phase 2; per-pair questions remain when at least one candidate exists.
118 lines
4.2 KiB
C#
118 lines
4.2 KiB
C#
using ClaudeDo.Data;
|
|
|
|
namespace ClaudeDo.Data.Tests;
|
|
|
|
public class PromptFilesTests
|
|
{
|
|
[Fact]
|
|
public void RenderTemplate_replaces_known_tokens()
|
|
{
|
|
var outp = PromptFiles.RenderTemplate(
|
|
"Plan for {date}, cap {maxTasks}.",
|
|
new Dictionary<string, string> { ["date"] = "2026-06-04", ["maxTasks"] = "5" });
|
|
Assert.Equal("Plan for 2026-06-04, cap 5.", outp);
|
|
}
|
|
|
|
[Fact]
|
|
public void RenderTemplate_leaves_unknown_braces_intact()
|
|
{
|
|
var outp = PromptFiles.RenderTemplate(
|
|
"## {Wochentag}, {dd.MM.yyyy} — {start}",
|
|
new Dictionary<string, string> { ["start"] = "01.06.2026" });
|
|
Assert.Equal("## {Wochentag}, {dd.MM.yyyy} — 01.06.2026", outp);
|
|
}
|
|
|
|
[Fact]
|
|
public void DefaultFor_system_mentions_blocked_marker_and_scope()
|
|
{
|
|
var d = PromptFiles.DefaultFor(PromptKind.System);
|
|
Assert.Contains("CLAUDEDO_BLOCKED:", d);
|
|
Assert.Contains("unattended", d, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
[Fact]
|
|
public void DefaultFor_planning_initial_has_title_and_description_tokens()
|
|
{
|
|
var d = PromptFiles.DefaultFor(PromptKind.PlanningInitial);
|
|
Assert.Contains("{title}", d);
|
|
Assert.Contains("{description}", d);
|
|
}
|
|
|
|
[Fact]
|
|
public void PathFor_planning_is_planning_system_file()
|
|
{
|
|
Assert.EndsWith("planning-system.md", PromptFiles.PathFor(PromptKind.Planning));
|
|
}
|
|
|
|
[Fact]
|
|
public void PathFor_merge_helper_kinds_map_to_their_files()
|
|
{
|
|
Assert.EndsWith("merge-helper-system.md", PromptFiles.PathFor(PromptKind.MergeHelper));
|
|
Assert.EndsWith("merge-helper-initial.md", PromptFiles.PathFor(PromptKind.MergeHelperInitial));
|
|
}
|
|
|
|
[Fact]
|
|
public void DefaultFor_merge_helper_covers_all_five_phases()
|
|
{
|
|
var d = PromptFiles.DefaultFor(PromptKind.MergeHelper);
|
|
Assert.False(string.IsNullOrWhiteSpace(d));
|
|
Assert.Contains("Phase 0", d);
|
|
Assert.Contains("Phase 1", d);
|
|
Assert.Contains("Phase 2", d);
|
|
Assert.Contains("Phase 3", d);
|
|
Assert.Contains("Phase 4", d);
|
|
Assert.Contains("Phase 5", d);
|
|
}
|
|
|
|
[Fact]
|
|
public void DefaultFor_merge_helper_names_the_tools_each_phase_needs()
|
|
{
|
|
var d = PromptFiles.DefaultFor(PromptKind.MergeHelper);
|
|
Assert.Contains("batch_get_tasks", d); // phase 0
|
|
Assert.Contains("update_task", d); // phase 1 + 2
|
|
Assert.Contains("get_app_settings", d); // phase 3
|
|
Assert.Contains("update_task_status", d); // phase 3
|
|
Assert.Contains("review_task", d); // phase 4
|
|
Assert.Contains("continue_merge", d); // phase 4
|
|
Assert.DoesNotContain("run_task_now(", d); // single override slot — must not batch-start
|
|
}
|
|
|
|
[Fact]
|
|
public void DefaultFor_merge_helper_only_asks_dedupe_questions_when_a_candidate_exists()
|
|
{
|
|
var d = PromptFiles.DefaultFor(PromptKind.MergeHelper);
|
|
Assert.Contains("move straight to Phase 2", d);
|
|
Assert.Contains("do not ask the user to confirm the absence of duplicates", d);
|
|
Assert.Contains("Cancel nothing without an explicit answer", d);
|
|
Assert.DoesNotContain("whenever you are unsure", d);
|
|
}
|
|
|
|
[Fact]
|
|
public void DefaultFor_merge_helper_initial_has_repo_token()
|
|
{
|
|
var d = PromptFiles.DefaultFor(PromptKind.MergeHelperInitial);
|
|
Assert.Contains("{repo}", d);
|
|
}
|
|
|
|
[Fact]
|
|
public void DefaultFor_merge_helper_initial_has_scope_and_tasks_tokens()
|
|
{
|
|
var d = PromptFiles.DefaultFor(PromptKind.MergeHelperInitial);
|
|
Assert.False(string.IsNullOrWhiteSpace(d));
|
|
Assert.Contains("{scope}", d);
|
|
Assert.Contains("{tasks}", d);
|
|
}
|
|
|
|
[Fact]
|
|
public void RenderTemplate_merge_helper_initial_substitutes_scope_and_tasks()
|
|
{
|
|
var outp = PromptFiles.RenderTemplate(
|
|
PromptFiles.DefaultFor(PromptKind.MergeHelperInitial),
|
|
new Dictionary<string, string> { ["scope"] = "All lists", ["tasks"] = "- [Idle] T1" });
|
|
Assert.Contains("Scope: All lists", outp);
|
|
Assert.Contains("- [Idle] T1", outp);
|
|
Assert.DoesNotContain("{scope}", outp);
|
|
Assert.DoesNotContain("{tasks}", outp);
|
|
}
|
|
}
|