- Reconcile per-target loop: publish request.completed/request.failed
based on updatedReq.Status/Outcome (aggregate), not the individual
target's newStatus. Partial failure (one target fails while a sibling
is still downloading) no longer fires a spurious request.failed event.
- Approve soft-fail: extract publishApprovalOutcome helper that emits
request.failed when Outcome==OutcomeFailed, else request.approved.
Approve and CreateRequest auto-approve both use it, so a submission
failure (no backend configured, no targets returned) publishes
request.failed instead of request.approved.
- Update TestApprove_PublishesRequestApproved to use a working router
so it actually exercises the request.approved branch.
- Add TestReconcile_PartialTargetFailureDoesNotPublishFailed,
TestApprove_SoftFailPublishesRequestFailed, and
TestCreateRequest_AutoApprovePublishesApproved.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>