# Ticket: Add audited campaign closeout to SD qualifier

Status: complete
Type: ticket
Updated: 2026-08-12
Next Action: none; operators may close reviewed idle stale campaigns from Overview, one at a time, with an explicit reason
Parent: work/wp/active/wp-build-standalone-pi-sd-qualification-operator-application.md

## Problem

The campaign workspace has no clear administrative closeout action. A generic
state-transition form is buried in setup, exposes `ABORTED` only from
`RUNNING`, and leaves stale `DRAFT`, `INTAKE`, and `BLOCKED` campaigns in the
in-process dashboard indefinitely.

## Expected Behavior

An authenticated operator can close a campaign that will not continue without
misrepresenting it as an approved, rejected, or failed qualification. The
application requires a reason, preserves all evidence, appends an audit event,
records the terminal time and actor, and moves the campaign to History. It
refuses closeout while coordinator work or a qualification run remains active.

## Acceptance Criteria

- [x] Campaign Overview exposes an explicit `Close campaign` action for eligible nonterminal campaigns.
- [x] Closeout requires a nonblank reason and a confirmation action.
- [x] `DRAFT`, `INTAKE`, `BASELINE_READY`, `AUTHORIZED`, `RUNNING`, `POST_CHECK`, `REVIEW`, and `BLOCKED` campaigns can be administratively closed when idle.
- [x] Active coordinator work or an open campaign run prevents closeout with an actionable message.
- [x] Closeout uses the existing terminal `ABORTED` state and records actor, timestamp, reason, and an append-only audit event without deleting evidence.
- [x] Closed campaigns leave the dashboard's In process list and appear in History as closed without a qualification conclusion.
- [x] Existing qualification approval, rejection, failure, transition, coordinator, and running-campaign behavior remains unchanged.
- [x] Only the web application is recreated on `srv-rpi00.local`; durable workers retain identity and start time.
- [x] Source is committed locally on a dedicated Git branch and is not pushed.

## Verification

Exact ARM64 release `campaign-closeout-520014c` passed 40 focused closeout,
workflow, coordinator, and responsive tests, plus the no-migration check.
Authenticated Playwright verified the action, required inputs, endpoint,
desktop/mobile containment, successful event polling, and zero current-page
console errors on the deployed application. The Aug. 10 campaign retained
state `RUNNING`, version `2`, and its prior update timestamp; all four durable
worker identities and start times were unchanged. See
`work/evidence/sd-qualifier-campaign-closeout-deployment-20260812.md`.
