# 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: ~20–40 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.
