Commit 5e27e91
fix(canvas): separate persistence evidence from ancestry classification in 409 reconciliation
canvas_write_survived checks whether A is an ancestor of the live head,
but it returns false for two distinct cases: (1) A genuinely absent, and
(2) A present in the stream but not an ancestor (e.g. an unconditional
legacy write B becomes head with no expected-revision link back to A).
This caused two wrong outcomes after a lost-response 409:
- Legacy write B (no expected-revision) becomes head, A retained in
stream: predicate false → original 409 rejection propagated; caller
cannot tell A committed.
- Tagged write B(expected=A) becomes head: predicate true → CliError::Conflict
exit 5 advising re-restore, inconsistent with the accepted-submit path
treating the identical descendant chain as success.
Fix: establish A's persistence via a separate writer-pinned IDs lookup
(fetch_canvas_event_exists), then apply the four-way classification:
- survived (ancestor of head): accepted JSON, exit 0
- persisted but head unrelated: supersession naming A
- genuinely absent: original 409 relay error
- either read fails: DeliveryUnknown naming A
Tests: corrected the descendant-ancestor regression (now expects Ok)
and added the legacy-supersession regression. Both new/corrected tests
confirmed red against the unfixed logic before fixing.
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>1 parent eef6b43 commit 5e27e91
1 file changed
Lines changed: 224 additions & 69 deletions
0 commit comments