```yaml
id: UJ-002
title: Confirmed reap executes only current orphan candidate
actors: [dashboard-operator]
surface: inbox
goal: Operator reaps current orphan candidate and receives success feedback.
trigger: Confirm `Reap` at `/inbox` for `orphan-agent`.
fixtures: [FixtureAdapter, ORPHAN_ITEM]
success_state:
  visible: `Reap succeeded` renders.
  durable: Action journal records reap pid and result.
  persistence: UNKNOWN — SP-002: no action-journal read endpoint exists.
source_specs: [apps/web/src/components/inbox/InboxTriageRow.tsx, apps/web/src/components/inbox/ActionConfirmDialog.tsx, apps/web/src/lib/action-client.ts, apps/web/src/pages/api/collector/[...path].ts, collector/src/server.ts, collector/src/actions.ts, collector/src/actions.test.ts, apps/web/tests/actions.spec.ts]
readiness: blocked
canonical: false
blockers: [SP-002, SP-003]
```

## Path

| Hop | Evidence |
|---|---|
| UI trigger | `apps/web/src/components/inbox/InboxTriageRow.tsx:66` |
| Request construction | `apps/web/src/lib/action-client.ts:14` |
| Endpoint auth and parse | `collector/src/server.ts:37` |
| Authoritative write | `collector/src/actions.ts:150` |
| Response | `collector/src/actions.ts:189` |
| Terminal render | `apps/web/src/components/inbox/InboxTriageRow.tsx:94` |

## Happy path

### H1
- Setup: Fixture state advertises orphan candidate pid `88231` for `orphan-agent`.
- Action: Activate `Reap`, then confirm `Reap` at `/inbox`.
- Request: `POST /api/collector/actions/reap`.
- Response: `200` with `{ok:true,result:"ok"}`.
- Visible: `Reap succeeded` renders.
- Durable: `actions.jsonl` appends `{verb:"reap",args:{pid:"88231"},requestedBy:"orphan-agent",result:"ok",rc:0}`.
- Fresh read: UNKNOWN — SP-002: no `GET` endpoint exposes `actions.jsonl`.
- Forbidden: No process PID except `88231` is passed to `reaper-ctl`.
- Evidence:
  - Setup: `collector/src/actions.test.ts:42`
  - Action: `apps/web/tests/actions.spec.ts:35`
  - Request: `apps/web/src/lib/action-client.ts:14`, `apps/web/src/pages/api/collector/[...path].ts:77`
  - Response: `collector/src/actions.test.ts:143`
  - Visible: `apps/web/tests/actions.spec.ts:40`
  - Durable: `collector/src/actions.test.ts:147`
  - Fresh read: UNKNOWN — SP-002: `collector/src/server.ts:43` has no action-journal route.
  - Forbidden: `collector/src/actions.ts:186`

## Alternate and failure paths

### A1
- Setup: Reap action carries PID `99999`, absent from current orphan candidates.
- Action: Submit `Reap` at `/api/collector/actions/reap`.
- Request: `POST /api/collector/actions/reap`.
- Response: `400` with `{ok:false,error:"pid is not an orphan candidate"}`.
- Visible: `Reap failed` renders.
- Durable: `actions.jsonl` appends failed reap with `rc:400`; no process starts.
- Fresh read: UNKNOWN — SP-002: no `GET` endpoint exposes `actions.jsonl`.
- Forbidden: `reaper-ctl` is not invoked.
- Evidence:
  - Setup: `collector/src/actions.test.ts:108`
  - Action: `apps/web/src/components/inbox/InboxTriageRow.tsx:90`
  - Request: `apps/web/src/lib/action-client.ts:14`
  - Response: `collector/src/actions.ts:177`
  - Visible: `apps/web/src/components/inbox/InboxTriageRow.tsx:101`
  - Durable: `collector/src/actions.test.ts:121`
  - Fresh read: UNKNOWN — SP-002: `collector/src/server.ts:43` has no action-journal route.
  - Forbidden: `collector/src/actions.ts:177`

### A2
- Setup: Same current orphan candidate receives two confirmed reap submissions.
- Action: Confirm `Reap` twice at `/inbox`.
- Request: `POST /api/collector/actions/reap`.
- Response: UNKNOWN — SP-003: gateway accepts every replay and has no idempotency response contract.
- Visible: UNKNOWN — SP-003: duplicate submissions have no distinct UI result state.
- Durable: UNKNOWN — SP-003: repeated requests can invoke `reaper-ctl` repeatedly.
- Fresh read: UNKNOWN — SP-002: no `GET` endpoint exposes `actions.jsonl`.
- Forbidden: Second `reaper-ctl` invocation for same user confirmation must not occur.
- Evidence:
  - Setup: `collector/src/actions.ts:177`
  - Action: `apps/web/src/components/inbox/ActionConfirmDialog.tsx:43`
  - Request: `apps/web/src/lib/action-client.ts:14`
  - Response: UNKNOWN — SP-003: `collector/src/actions.ts:301` has no replay guard.
  - Visible: UNKNOWN — SP-003: `apps/web/src/components/inbox/InboxTriageRow.tsx:94` renders only generic success.
  - Durable: UNKNOWN — SP-003: `collector/src/actions.ts:186` invokes command per accepted request.
  - Fresh read: UNKNOWN — SP-002: `collector/src/server.ts:43` has no action-journal route.
  - Forbidden: `collector/src/actions.ts:186`

## Permissions and boundaries

N/A — dashboard has no user identity or RBAC boundary; collector authorization checks only one shared bearer token. `collector/src/server.ts:20`

## Source specs

- `apps/web/src/components/inbox/InboxTriageRow.tsx`
- `apps/web/src/components/inbox/ActionConfirmDialog.tsx`
- `apps/web/src/lib/action-client.ts`
- `apps/web/src/pages/api/collector/[...path].ts`
- `collector/src/server.ts`
- `collector/src/actions.ts`
- `collector/src/actions.test.ts`
- `apps/web/tests/actions.spec.ts`
