audience: AI coding agents first.

# Incident resolver Defaults API — request

**Goal:** persist and serve authoritative global/per-type resolver defaults without duplicating dispatch capability authority.

**Execution authority:** factory-owned app work. MUST NOT modify coordinator, execution ledger, policy enforcement, canaries, signing, or `modules/harness/factory/**`.

**Canonical design:** `docs/specs/2026-08-09-factory-supervision-and-resolution-design.md`.

## Prerequisites

- Land `.worktrees/incident-dispatch-selector-options` capability/options implementation first.
- Trusted coordinator contracts exist; this request only configures them through validated settings.

## Files

- Create `collector/src/incidents/incident-resolver-defaults.ts` — schema, precedence, optimistic revision, atomic persistence.
- Create `collector/src/incidents/incident-resolver-defaults.test.ts` — persistence/merge/conflict/capability cases.
- Modify `collector/src/server.ts` — authenticated `GET/PUT /incidents/defaults` before incident detail regex.
- Modify `collector/src/paths.ts` — server-owned defaults path.
- Modify collector config/dependency injection seam used by server tests.
- Modify `apps/web/src/lib/incident-types.ts` — mirrored Defaults request/response wire types.
- Modify same-origin collector proxy allowlist/handlers for exact defaults routes.

## Contract

Copy verbatim:

```text
IncidentResolverDefaultsV1 {
  version: "incident-resolver-defaults/v1"
  global: IncidentResolutionDefaults
  byType: Record<IncidentTypeId, PartialIncidentResolutionDefaults>
}

IncidentResolutionDefaults {
  resolver: ResolverSeat[]
  budget: ResolutionBudget
  unsafe: boolean
  autoRepair: boolean
}
```

Canonical internal fields: `harness`, `model`, `effort`, `account`, `unsafe`. Compatibility adapter maps `harness -> cli` and `effort -> reasoningEffort` at existing incident dispatch boundary.

Routes:

```text
GET /incidents/defaults
PUT /incidents/defaults
```

Response includes revision/ETag and resolved capability validity. `PUT` requires expected revision.

## Behavior

- Precedence: global → per-type override → explicit manual filing → immutable pinned dispatch.
- Historical incidents never influence defaults.
- Validate every seat against current authoritative `/incidents/options` loader and account authority. Unknown/stale choice remains visible but invalid and blocks dispatch; never substitute.
- `PUT` uses bearer auth, same-origin mutation protection, bounded body, unknown-field rejection, compare-and-set revision, atomic durable persistence, and parent-directory fsync.
- Stale write returns `409 settings-conflict` with current revision.
- Persist complete versioned JSON/settings document; keep last-good in-memory state only after durable commit confirmation.
- Ship initial finite budget profiles exactly from canonical design. Bootstrap account from explicit deployed preset configuration only when capability-valid; missing account leaves visible invalid state.
- Manual/user-defined types default `autoRepair:false`. Protected types follow trusted policy flags but API cannot expand allowed protected scope.

## Out of scope

- Coordinator launch/takeover, worktrees, signing, canaries, artifact verification.
- UI rendering.
- New capability/account manifest.
- Incident history inference.

## Acceptance

- From `collector/`, run `bun test`.
- Run web typecheck/build for mirrored route types: `pnpm --filter web typecheck && pnpm --filter web build`.
- Expected clean PASS for GET/PUT/reload, global/per-type/explicit/pinned precedence, stale revision, concurrent writers, malformed policy, unknown type, stale capability/account, commit failure, and route-order collision with `/incidents/:id`.
- Live authenticated smoke: save non-empty global and per-type resolver chains, restart collector, read identical revision and values.
