fix(ios): prevent duplicate mutations and preserve read retries

Merged
TH
11d ago
+1686-260

Summary

The journal owns commandId admission: finished mutations replay within the closed-id window, while reads execute again. Per-claim execution tokens isolate joiners across reuse. Recorded failures keep their code and hint. The original delivery owns shutdown completion; terminal replays return only the outcome.

22 files: 9 production, 8 tests, 2 fixtures, 2 docs, 1 patch changeset. After COMMAND_ALREADY_FINISHED, inspect with snapshot -i before deciding on another interaction.

Validation

Head 39a6304ccd587bd2430565a82514665a0b5484c8, based on a42bc352827f1c13d264f805bd2a75cdb2c94eec.

  • Focused iOS Swift at head: 89 passed. XCTest selection: 549 declared, none unreachable.
  • Exact-head affected gate passed: receipt run-vBWd8J, exactCommit=true, checkoutChanged=false.
  • This follow-up changes one comment to identify jsonResponse as the live occupancy-stamp owner. The stale-transition finding is unreachable: all journal transitions finish synchronously on the serial command queue before re-admission.
  • At runtime-equivalent b57eae7: 81 focused TypeScript tests, both native builds, and native duplication (75, zero new) passed; shared trait parity detects Swift or TS drift.
  • Fresh live route at b57eae7: open, 17-node snapshot, close; private cleanup exited runner 36736 and daemon 35265.
  • Rebase range-diff against f7879cf..7c883d7 reviewed; main’s persistent HTTP and shutdown-write drain remain intact. New-head hosted CI is pending.