# Close-evidence outbox Status: **durable core implemented, not connected to the live claim loop**. The outbox preserves one bounded Activity Core completion or failure intent after repository work. Replaying an outbox entry calls only the queue close adapter; it never dispatches a model, invokes an approach, or repeats repository mutation. ## Storage and identity The default root is: ```text $REIN_AHARNESS_STATE_DIR/close-outbox/ ``` When that variable is absent, the harness uses `$XDG_STATE_HOME/rein-aharness` or `~/.local/state/rein-aharness`. State lives outside target checkouts. Outbox directories are mode `0700`; lock and JSON files are mode `0600`. An entry is keyed by the digest of the bounded Activity Core `run_id` and repository `transaction_id`. Re-enqueuing the identical intent returns its existing pending or delivered state. Reusing that identity for a different action, result, error, or reopen decision is a conflict and is refused. The v1 close intent contains: - `action`: `complete` or `fail`; - bounded normalized JSON `result` evidence; - a caller-sanitized bounded error and explicit `reopen` decision for failures; - no prompt, provider body, credential, raw tool stream, or workload callback. Results allow only finite JSON values, bounded depth, collection size, string length, integer range, key length, and a total encoded size of 64 KiB. ## Durability and replay Enqueue and retry-state updates use a same-directory temporary file, file `fsync`, atomic replace, and directory `fsync` under a process-safe `flock`. The retry attempt is durable before the delivery callback begins. Normal callback return marks the entry delivered and atomically moves it from `pending/` to `delivered/`. An ordinary exception retains it in `pending/` with only the exception class and a generic failure marker; exception text is not persisted. Process interrupts propagate; the already-recorded attempt remains pending. Invalid, oversized, or directory/state-mismatched records are moved intact to `quarantine/` with a bounded reason sidecar and are never delivered automatically. A network timeout may occur after Activity Core accepted a close. Retrying the same close intent can therefore repeat the queue mutation request, but cannot repeat repository workload. Activity Core remains authoritative for terminal row state and must provide idempotent or reconcilable close semantics. ## Activation gates The live claim loop still returns an in-memory failure when close delivery fails. Connecting it to this outbox requires: 1. the lease-bound repository transaction and accepted-result envelope; 2. enqueue-before-close using the same run and transaction identities; 3. Activity Core review of repeat close behavior for already-terminal rows; 4. startup/periodic replay that never calls workload code; and 5. operator status, quarantine inspection, and replay controls. Until those gates are implemented and reviewed, no production close behavior changes.