Transaction and operational recovery
Day Shift uses repository transactions for multi-path mutations such as structural workspace migration and promotion. The safety model is evidence-first: inspect the command result and retained operational state, decide whether the correct outcome is no retry, a fresh plan, roll-forward, or restore, and invoke only the owning command’s explicit recovery lane.
Files that describe operational state
Section titled “Files that describe operational state”The repository write lock is .day-shift/state/write.lock. It records a transaction id, opaque owner token, host, process id, heartbeat, and lease expiry. Transaction staging lives under .day-shift/state/transactions/<transaction-id>/; a complete retained transaction has a restricted manifest.json, restricted staged files, and a status record. Successful recovery writes a sanitized receipt under .day-shift/state/recovery-records/. Migration and promotion also bind a durable domain record as one of the transaction’s canonical writes.
These paths are implementation evidence, not a manual repair interface. Never edit a manifest, status, staged file, lock, durable record, or recovery receipt to make a command appear terminal.
Transaction sequence and irreversible boundary
Section titled “Transaction sequence and irreversible boundary”A write-capable command captures destination-presence and content-revision preconditions during preview. Apply acquires one exclusive lock, revalidates those preconditions under the lock, stages every intended write and retirement with restrictive permissions, and only then replaces canonical targets in deterministic path order. Each replacement is postcondition-checked before the next operation.
Before the first canonical replacement, an interruption is a truthful no-write outcome. Between replacements or during postcondition verification, the outcome is incomplete and retained evidence identifies which targets remain at their before, intended, retired, missing, or diverged state. After every postcondition verifies, cleanup failure does not erase the committed verdict; it leaves the verified manifest and status available for inspected cleanup.
Classify before acting
Section titled “Classify before acting”Use the write command’s JSON result and read-only inspection evidence:
| Evidence | Safe response |
|---|---|
| Active lock or owner liveness not safely disproven | Wait. Do not take over or delete the lock. |
| Stale lock without matching transaction evidence | Stop. Expiry alone is insufficient for takeover. |
| Preview/apply precondition conflict | No staging or canonical write occurred; inspect the changed path and generate a fresh preview. |
no-write with retained staging |
Preserve it until inspection proves cleanup or an owning recovery action is safe. |
incomplete with all current targets matching before or intended revisions |
Use the exact offered restore or roll-forward action with the current fingerprint. |
| Any diverged target, invalid or missing manifest, missing staged bytes, or mismatched durable record | Stop. Recovery must reject rather than guess. |
committed with cleanup errors |
Verify terminal postconditions and receipt evidence, then resume the supported cleanup path. |
An expired lock may be taken over only when owner liveness is disproven and matching transaction evidence makes ownership unambiguous. The same transaction id and exact current evidence fingerprint must still match after lock acquisition.
Choose roll-forward or restore
Section titled “Choose roll-forward or restore”roll-forward applies the verified intended staged bytes and retirements that remain incomplete. restore replays verified before-bytes and reverses retirements when every affected target can be returned safely. Neither action is a general undo command.
The recovery call must bind the retained transaction id, exact current evidence fingerprint, action, bounded actor, and bounded reason. The owning command also requires its recovery confirmation token. Migration uses workspace migrate --recover; promotion uses the matching task promote --recover or work promote --recover lane.
Recovery is fail-closed. A stale fingerprint, live lock, diverged target, unavailable action, unsafe restore, missing staged evidence, wrong transaction kind, or conflicting recovery receipt causes no recovery mutation. Generic transactions do not gain a public recovery command merely because low-level staging exists.
Interrupted recovery and receipts
Section titled “Interrupted recovery and receipts”If recovery is interrupted after target changes but before receipt persistence, the next inspection can prove that postconditions already match and let the same exact action finish the receipt. If the receipt exists but cleanup was interrupted, an identical current proof can resume cleanup without rewriting targets. A receipt whose transaction, action, durable-record binding, fingerprint, or sanitized audit fields differ is a conflict and must remain untouched.
A stale lock-release residual can be resumed only when terminal receipt evidence matches and liveness is disproven. Never delete the lock first; recovery owns the verification and cleanup order.
Stop conditions
Section titled “Stop conditions”Stop normal writes when any target is diverged, when operational metadata is malformed, when the only verified copy is staged, when a live lock exists, or when the owning command does not offer the desired action. Record the failed command, transaction id, current fingerprint, changed or uncertain targets, residual risk, and next read-only inspection.
Do not represent manual deletion, force replacement, automatic retry, review-driven mutation, demotion, or arbitrary transaction rollback as shipped recovery. Use Migrate an existing workspace for the full structural migration protocol and Troubleshooting for symptom-driven triage.