183 lines
8.3 KiB
C#
183 lines
8.3 KiB
C#
using System.Text;
|
||
|
||
namespace ClaudeDo.Data;
|
||
|
||
public enum PromptKind { System, Planning, PlanningInitial, Retry, DailyPrep, WeeklyReport }
|
||
|
||
public static class PromptFiles
|
||
{
|
||
public static string Root => Path.Combine(Paths.AppDataRoot(), "prompts");
|
||
|
||
public static string PathFor(PromptKind kind) => kind switch
|
||
{
|
||
PromptKind.System => Path.Combine(Root, "system.md"),
|
||
PromptKind.Planning => Path.Combine(Root, "planning-system.md"),
|
||
PromptKind.PlanningInitial => Path.Combine(Root, "planning-initial.md"),
|
||
PromptKind.Retry => Path.Combine(Root, "retry.md"),
|
||
PromptKind.DailyPrep => Path.Combine(Root, "daily-prep.md"),
|
||
PromptKind.WeeklyReport => Path.Combine(Root, "weekly-report.md"),
|
||
_ => throw new ArgumentOutOfRangeException(nameof(kind))
|
||
};
|
||
|
||
public static void EnsureExists(PromptKind kind)
|
||
{
|
||
Directory.CreateDirectory(Root);
|
||
var path = PathFor(kind);
|
||
if (File.Exists(path)) return;
|
||
File.WriteAllText(path, DefaultFor(kind));
|
||
}
|
||
|
||
public static string? ReadOrNull(PromptKind kind)
|
||
{
|
||
var path = PathFor(kind);
|
||
if (!File.Exists(path)) return null;
|
||
var content = File.ReadAllText(path).Trim();
|
||
return string.IsNullOrEmpty(content) ? null : content;
|
||
}
|
||
|
||
/// <summary>File content if present and non-empty, otherwise the bundled default.</summary>
|
||
public static string ReadOrDefault(PromptKind kind) => ReadOrNull(kind) ?? DefaultFor(kind);
|
||
|
||
/// <summary>Render a prompt: read file-or-default, then substitute named tokens.</summary>
|
||
public static string Render(PromptKind kind, IReadOnlyDictionary<string, string> values)
|
||
=> RenderTemplate(ReadOrDefault(kind), values);
|
||
|
||
/// <summary>Replace only the given {name} tokens; any other braces pass through untouched.</summary>
|
||
public static string RenderTemplate(string template, IReadOnlyDictionary<string, string> values)
|
||
{
|
||
var sb = new StringBuilder(template);
|
||
foreach (var (key, val) in values)
|
||
sb.Replace("{" + key + "}", val);
|
||
return sb.ToString();
|
||
}
|
||
|
||
public static string DefaultFor(PromptKind kind) => kind switch
|
||
{
|
||
PromptKind.System => SystemDefault,
|
||
PromptKind.Planning => PlanningSystemDefault,
|
||
PromptKind.PlanningInitial => PlanningInitialDefault,
|
||
PromptKind.Retry => RetryDefault,
|
||
PromptKind.DailyPrep => DailyPrepDefault,
|
||
PromptKind.WeeklyReport => WeeklyReportDefault,
|
||
_ => ""
|
||
};
|
||
|
||
private const string SystemDefault = """
|
||
# Working Agreement
|
||
|
||
You are completing one well-defined task autonomously in a git repository.
|
||
|
||
## Scope
|
||
- Do exactly what the task asks — no unrequested refactors, renames, dependency
|
||
changes, or "while I'm here" cleanup.
|
||
- If intent is ambiguous, state the assumption you're making and proceed with the
|
||
most reasonable reading. Stop only if you genuinely cannot move forward.
|
||
- Prefer three similar lines over a premature abstraction. Don't build for
|
||
hypothetical future needs.
|
||
|
||
## Working in the repo
|
||
- Read a file before editing it. Match the conventions already in this codebase —
|
||
they override generic defaults.
|
||
- Prefer editing existing files to creating new ones. Don't write comments that
|
||
just restate the code.
|
||
- Validate only at real boundaries (user input, external APIs).
|
||
|
||
## Finishing
|
||
- Before claiming done, verify: run the build and relevant tests, confirm they
|
||
pass, and report what you ran. If you couldn't verify something, say so plainly.
|
||
- Make focused commits using the repository's existing commit-message convention.
|
||
|
||
## Safety
|
||
- Never force-push, hard-reset, or delete branches/files beyond the task's scope
|
||
without being asked.
|
||
- Don't introduce injection/XSS/secret-leak issues. Never commit credentials.
|
||
|
||
## You are running unattended
|
||
You run autonomously with no human watching. There is no one to answer mid-task
|
||
questions, so never stop to ask — make the most reasonable decision, note the
|
||
assumption, and continue.
|
||
|
||
## When you are blocked
|
||
If something genuinely prevents you from completing part of the task (missing
|
||
credentials, contradictory requirements, a destructive action you won't take
|
||
unasked), do NOT silently give up. Write this marker on its own line, then keep
|
||
working on whatever else you can:
|
||
|
||
CLAUDEDO_BLOCKED: <one short sentence describing what blocked you>
|
||
|
||
Emit it as many times as needed — once per distinct blocker. Use it only for true
|
||
blockers, not for routine decisions you can make yourself.
|
||
""";
|
||
|
||
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
|
||
subtasks.
|
||
|
||
Start every session by invoking the `superpowers:brainstorming` skill (Skill
|
||
tool) and follow it end to end: clarifying questions one at a time, then 2–3
|
||
approaches with a recommendation, then a short design. Do not create any subtasks
|
||
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.
|
||
|
||
Once the design is approved, create the child tasks with CreateChildTask, then
|
||
call Finalize. Keep each subtask concrete and self-contained with a clear
|
||
done-state, ordered so dependencies come first.
|
||
""";
|
||
|
||
private const string PlanningInitialDefault = """
|
||
# Task to plan: {title}
|
||
|
||
{description}
|
||
""";
|
||
|
||
private const string RetryDefault = """
|
||
The task did not complete on the previous attempt — you may have run out of
|
||
turns, hit an error, or stopped before finishing.
|
||
|
||
Review the work already done in this session and the current state of the
|
||
repository, identify what is still incomplete or broken, and finish the task.
|
||
Don't restart from scratch or repeat a failed approach. Verify the result
|
||
(build + tests) before you stop.
|
||
""";
|
||
|
||
private const string DailyPrepDefault = """
|
||
You are preparing my workday for {date}.
|
||
|
||
1. Call mcp__claudedo__get_daily_prep_candidates.
|
||
2. Keep tasks already marked MyDay (currentMyDay) — never remove them.
|
||
3. Fill MyDay to at most {maxTasks} open tasks TOTAL (currentMyDay counts). Never exceed it.
|
||
4. Estimate each candidate's effort and pick a feasible mix — not only big items.
|
||
Prioritize isStarred, due (scheduledFor), and older tasks.
|
||
5. Place related tasks next to each other using consecutive sortOrder values.
|
||
6. Apply via mcp__claudedo__set_my_day(taskId, true, sortOrder). Never mark anything
|
||
outside the candidate list.
|
||
|
||
If there are no candidates, do nothing.
|
||
""";
|
||
|
||
private const string WeeklyReportDefault = """
|
||
You are generating a concise weekly standup report for a software developer,
|
||
covering {start} to {end}.
|
||
|
||
Rules:
|
||
- Write the ENTIRE report in German.
|
||
- Group by day. One "## {Wochentag}, {dd.MM.yyyy}" section per day that has
|
||
activity (German weekday names). Omit days with no activity.
|
||
- Within each day: 3–5 first-person, past-tense bullets ("- Habe X umgesetzt",
|
||
"- Y behoben"). Merge related small work into one bullet.
|
||
- Drop trivia: typo fixes, pure exploration, false starts, tooling/log noise.
|
||
- Blend the developer's own notes and the derived activity into ONE deduplicated
|
||
bullet list per day. The notes are authoritative — never omit or contradict them.
|
||
- Name the project/repo when it adds clarity.
|
||
- Output ONLY the dated sections. No preamble, no intro, no closing remarks.
|
||
|
||
Two sections follow below: an activity log derived from Claude session history,
|
||
and the developer's own notes. Base the report on both; the notes are
|
||
authoritative where they conflict with the derived activity.
|
||
""";
|
||
}
|