Deferred follow-up from Slice 2 (PR #3, merged in commit c328be5). Task T052 in specs/002-mock-call-real-crm/tasks.md:198.
Problem
The Slice 2 resume coordinator (src/opencloser/slice2/resume.py) replays missing CRM writes from a persisted writeback.json. Today the orchestrator writes that file only after every emit_* operation succeeds, so a real TransientDataverseError retry-exhaust leaves no replay artifact and resume_session raises ResumeError("writeback.json missing").
This means the natural resume_needed recovery path (which Slice 2 ships and documents — FR-023) cannot actually be exercised end-to-end without an orchestrator-side change. The resume coordinator's design is correct; the gap is purely in artifact-write ordering.
Fix (architectural)
Persist a planned-writeback.json sidecar artifact before the first emit_* attempt, mirroring the planned payloads the adapter would issue (the adapter already captures these for dry-run). The post-success writeback.json can stay as the authoritative final artifact.
Likely shape:
- New writer function (e.g.
write_planned_writeback_artifact) called at orchestrator start, right after the readiness gate passes.
slice2/resume.py loads planned-writeback.json (or writeback.json, in that order) instead of strictly requiring writeback.json.
writeback.json continues to be written on full success — keeps the "the final write succeeded" signal.
Test impact
The integration test tests/integration/test_us4_idempotency.py::test_us4_natural_transient_exhaust_yields_resume_needed currently asserts BOTH the RESUME_NEEDED exit and the ResumeError("writeback.json missing") raise — that second assertion will need updating when this lands, to assert successful resume replay instead. The test docstring explicitly flags this as a follow-up dependency.
Origin
Surfaced by the 2026-05-24 multi-agent swarm code review:
- Resume-coordinator audit (MEDIUM): "the resume path cannot recover natural transient-exhaust failures end-to-end".
- Test-pyramid audit (HIGH): "the runner's TransientDataverseError → RESUME_NEEDED branch is verified by inspection only via synthesized state".
Tracked in:
src/opencloser/slice2/resume.py:26-38 (KNOWN LIMITATION docstring)
specs/002-mock-call-real-crm/tasks.md:198 (DEFERRED entry)
specs/002-mock-call-real-crm/contracts/cli-slice2.md (T052 paragraph)
🤖 Generated with Claude Code
Deferred follow-up from Slice 2 (PR #3, merged in commit
c328be5). Task T052 inspecs/002-mock-call-real-crm/tasks.md:198.Problem
The Slice 2 resume coordinator (
src/opencloser/slice2/resume.py) replays missing CRM writes from a persistedwriteback.json. Today the orchestrator writes that file only after everyemit_*operation succeeds, so a realTransientDataverseErrorretry-exhaust leaves no replay artifact andresume_sessionraisesResumeError("writeback.json missing").This means the natural
resume_neededrecovery path (which Slice 2 ships and documents — FR-023) cannot actually be exercised end-to-end without an orchestrator-side change. The resume coordinator's design is correct; the gap is purely in artifact-write ordering.Fix (architectural)
Persist a
planned-writeback.jsonsidecar artifact before the firstemit_*attempt, mirroring the planned payloads the adapter would issue (the adapter already captures these for dry-run). The post-successwriteback.jsoncan stay as the authoritative final artifact.Likely shape:
write_planned_writeback_artifact) called at orchestrator start, right after the readiness gate passes.slice2/resume.pyloadsplanned-writeback.json(orwriteback.json, in that order) instead of strictly requiringwriteback.json.writeback.jsoncontinues to be written on full success — keeps the "the final write succeeded" signal.Test impact
The integration test
tests/integration/test_us4_idempotency.py::test_us4_natural_transient_exhaust_yields_resume_neededcurrently asserts BOTH theRESUME_NEEDEDexit and theResumeError("writeback.json missing")raise — that second assertion will need updating when this lands, to assert successful resume replay instead. The test docstring explicitly flags this as a follow-up dependency.Origin
Surfaced by the 2026-05-24 multi-agent swarm code review:
Tracked in:
src/opencloser/slice2/resume.py:26-38(KNOWN LIMITATION docstring)specs/002-mock-call-real-crm/tasks.md:198(DEFERRED entry)specs/002-mock-call-real-crm/contracts/cli-slice2.md(T052 paragraph)🤖 Generated with Claude Code