Files
ClaudeDo/docs/superpowers/specs/2026-04-23-default-agents-design.md

178 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Default Agents — Design
**Date:** 2026-04-23
**Status:** Approved
## Goal
Ship ClaudeDo with a curated set of default agents so that users have useful agents available on first launch, without losing the file-based ownership model (user-editable, user-deletable). Provide a "Restore defaults" action to recover missing defaults on demand.
## Agents to Ship
Six markdown agents covering the common stages of task execution plus one general-purpose agent:
| File | Focus |
|---|---|
| `code-reviewer.md` | Review diff for bugs, logic errors, convention adherence. Flags only high-confidence issues. |
| `test-writer.md` | Generate unit/integration tests for changed code. Follows existing test patterns. |
| `debugger.md` | Systematic root-cause analysis — reproduce, isolate, hypothesize, verify. |
| `security-reviewer.md` | OWASP-style audit focused on auth, SQL injection, input handling, secret exposure. |
| `explorer.md` | Fast codebase navigation and answering "where/how" questions. Terse output. |
| `researcher.md` | General-purpose research, doc summarization, analysis, investigation. Non-code. |
Each file uses Claude Code's standard agent frontmatter:
```markdown
---
name: <agent name>
description: <one-line description>
---
<system prompt body>
```
Content target: ~2040 lines per file. Style matches the existing Claude Code agent conventions.
## Behavior
**Seed on first launch, restore on demand:**
1. Bundled agents live alongside the Worker binary at `<AppContext.BaseDirectory>/DefaultAgents/*.md`.
2. At Worker startup, for each bundled file: if `~/.todo-app/agents/<name>.md` does NOT exist, copy it in. If it exists, leave it alone — the user owns their copy.
3. A "Restore default agents" button in the settings modal re-runs the same check, restoring any that the user has deleted.
The seed path and the restore path are the same code — only the invocation differs (startup vs. hub call).
## Components
### `DefaultAgents/*.md` (bundled content)
Location: `src/ClaudeDo.Worker/DefaultAgents/`
Packaging: `<Content Include="DefaultAgents\*.md" CopyToOutputDirectory="PreserveNewest" />` in `ClaudeDo.Worker.csproj`.
At runtime they land at `<AppContext.BaseDirectory>/DefaultAgents/*.md` next to the executable.
### `DefaultAgentSeeder` (new service)
Location: `src/ClaudeDo.Worker/Services/DefaultAgentSeeder.cs`
```
public sealed class DefaultAgentSeeder
{
public DefaultAgentSeeder(string bundleDir, string targetDir);
public Task<SeedResult> SeedMissingAsync(CancellationToken ct = default);
}
public sealed record SeedResult(int Copied, int Skipped);
```
Behavior of `SeedMissingAsync`:
- If `bundleDir` doesn't exist, log warning and return `(0, 0)`.
- Enumerate `*.md` in `bundleDir`.
- For each file, if the target path (`targetDir/<filename>`) is missing, copy it; else increment `Skipped`.
- Create `targetDir` if missing (consistent with existing `AgentFileService.WriteAsync`).
- Per-file exceptions are caught and logged; the seeder continues with the next file. The method itself does not throw for individual file failures.
### `Program.cs` wiring
After `AgentFileService` registration and before `app.Run()`:
```csharp
var bundleDir = Path.Combine(AppContext.BaseDirectory, "DefaultAgents");
var seeder = new DefaultAgentSeeder(bundleDir, agentsDir);
await seeder.SeedMissingAsync();
builder.Services.AddSingleton(seeder);
```
The seeder is also registered as a singleton so the hub can invoke it for the restore flow.
### `WorkerHub.RestoreDefaultAgents`
Location: add method to existing `src/ClaudeDo.Worker/Hub/WorkerHub.cs`.
Signature: `public async Task<SeedResult> RestoreDefaultAgents()`
Behavior:
- Calls `DefaultAgentSeeder.SeedMissingAsync()`.
- Returns the `SeedResult` to the caller.
- No separate broadcast — the UI will call `GetAgents` after the restore returns, reusing the existing refresh path.
### UI — Settings Modal
Location: `src/ClaudeDo.Ui/Views/Modals/SettingsModalView.axaml` + `SettingsModalViewModel`.
Add a "Restore default agents" button to the modal. On click:
1. Disable the button, show a spinner label.
2. Call `WorkerClient.RestoreDefaultAgentsAsync()`.
3. Show a brief inline confirmation: `"Restored {Copied} agent(s)"` or `"All defaults already present"`.
4. Trigger the existing agent list refresh so the new files appear immediately in the rest of the UI.
### `WorkerClient` method
Add `Task<SeedResult> RestoreDefaultAgentsAsync(CancellationToken ct = default)` to `WorkerClient` — thin wrapper that invokes the hub method.
## Data Flow
**Startup:**
```
Worker starts → DefaultAgentSeeder.SeedMissingAsync()
→ copies missing files into ~/.todo-app/agents/
AgentFileService.ScanAsync() (on first GetAgents call) → sees the seeded files
```
**User restores:**
```
Settings modal button click
→ WorkerClient.RestoreDefaultAgentsAsync()
→ WorkerHub.RestoreDefaultAgents()
→ DefaultAgentSeeder.SeedMissingAsync()
→ returns SeedResult(copied, skipped)
UI shows confirmation, triggers GetAgents refresh
```
## Error Handling
| Failure | Behavior |
|---|---|
| Missing `DefaultAgents/` bundle dir | Log warning, return `(0, 0)`. Startup proceeds. |
| Individual file copy failure (disk, permissions) | Catch per-file, log, continue with the remaining files. |
| Corrupt bundled markdown (no valid frontmatter) | Copied anyway — the `AgentFileService` frontmatter parser already falls back to filename-as-name. |
| Startup seeder exception (unexpected) | Log as warning, do not crash the Worker. Agents can still be restored via the button. |
| Hub `RestoreDefaultAgents` exception | Propagate to client as SignalR error; UI shows a generic "Restore failed" message. |
## Testing
**Unit:** `tests/ClaudeDo.Worker.Tests/Services/DefaultAgentSeederTests.cs`
- Seeds all files when target dir is empty.
- Skips files that already exist.
- Preserves existing user-modified files (file mtime / content unchanged).
- Returns accurate `SeedResult` counts.
- Handles missing bundle dir gracefully (returns `(0, 0)`, no throw).
- Creates target dir if it doesn't exist.
**Integration:** extend `tests/ClaudeDo.Worker.Tests/Hub/AgentSettingsHubTests.cs`
- `RestoreDefaultAgents` invokes the seeder and returns the count.
**No UI tests.** The project has no UI test harness; settings modal behavior is exercised manually.
## Build / Packaging
`src/ClaudeDo.Worker/ClaudeDo.Worker.csproj` gains:
```xml
<ItemGroup>
<Content Include="DefaultAgents\*.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
```
No new NuGet dependencies.
## Out of Scope
- Editing bundled agents in-place (user edits their copy under `~/.todo-app/agents/`; bundle is read-only by convention).
- Versioning / updating user copies when the bundled version changes. If a bundled agent is improved in a later release, the user's copy is not overwritten. A future release may add a "diff / reset to bundled" flow, but not now.
- Packaging as embedded resources. Content files copied to output are simpler, inspectable on disk, and consistent with the file-based agent model.