Build durable close evidence outbox
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02b6f-7db1-7222-918b-e813a6bda38d
This commit is contained in:
parent
9866f35b30
commit
c97e5ea92d
5 changed files with 978 additions and 0 deletions
69
docs/close-evidence-outbox.md
Normal file
69
docs/close-evidence-outbox.md
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue