Skip to content

fix(state): recover non-reconcile canonical tuple 409 conflicts with rebase-or-skip - #965

Merged
steipete merged 1 commit into
mainfrom
fix/apply-tuple-conflict-recovery
Jul 30, 2026
Merged

fix(state): recover non-reconcile canonical tuple 409 conflicts with rebase-or-skip#965
steipete merged 1 commit into
mainfrom
fix/apply-tuple-conflict-recovery

Conversation

@steipete

Copy link
Copy Markdown
Contributor

Problem

Comment-sync and apply runs crash with CanonicalRecordTupleConflictError: POST /internal/state/records/tuples returned 409: canonical_record_tuple_conflict (sample run 30555649490, step "Apply unchanged proposed decisions with checkpoints").

publishMainWithStateAppend posts canonical record tuples per item, but postCanonicalRecordTupleWithRecovery only recovers 409 conflicts when CLAWSWEEPER_CANONICAL_PUBLICATION_KIND === "reconcile" (set only by scripts/apply-workflow-helpers.sh). Apply-lane and comment-sync publications run without that kind, so the first conflict kills the entire run mid-checkpoint. With ~70 concurrent review workers constantly bumping record revisions in the ExactReviewQueue DO, these races are now routine — the lane fails continuously.

Fix

Non-reconcile conflicts now go through a dedicated recovery path in src/repair/publish-main.ts (recoverNonReconcilePublicationConflict) that reuses the existing reconcile helpers and never force-writes:

  • Sections we changed are computed from the mutation itself: a section is ours when its content digest differs from the state-baseline expectedDigest the mutation asserted.
  • Equivalent concurrent write: if CURRENT already matches our target on every section we changed, sync CURRENT into the working root and count the item as resolved (no retry).
  • Unrelated-section race: rebase once — CURRENT's digests as expectedDigest, our content for sections we changed, CURRENT's content for the rest — under a deterministic record-tuple-rebase:<run>:<attempt>:<contentHash> delivery id (mirrors the record-reconcile: retry pattern in a separate non-reconcile namespace). The rebased tuple is validated before posting; an invalid combination skips instead.
  • Same-section race, or the single retry conflicts again: skip just that item — sync CURRENT to root, warn with key and revision, continue with the remaining items. If every item in the plan is skipped this way, the run still throws (mirrors the reconcile all-failed guard). Infrastructure errors (isCanonicalInfrastructureError) still throw immediately.

A skipped item may repeat its GitHub action next cycle since side effects happen before publication (capture-before-mutate); comment idempotency fences and the unchanged-edit dedupe (#857) make that repeat a no-op, and the code comments call out that those fences must not be weakened. Reconcile behavior is preserved exactly — its recovery block is unchanged aside from returning an explicit outcome.

Proof

Four new tests in test/repair/publish-main.test.ts, each proven red against the origin/main implementation (all four fail pre-fix: the old code rethrows the 409 for every non-reconcile conflict):

  • non-reconcile conflict whose CURRENT already contains the change → resolved, CURRENT synced to root, single POST
  • conflict on an unrelated section → rebased retry succeeds with CURRENT digests + our section content, record-tuple-rebase: delivery id
  • conflict on our own section → item skipped with key+revision warning, sibling tuple still publishes
  • every item conflicting on its own section → run throws

Full gate: pnpm run build:all, focused suite 15/15, pnpm run format, pnpm run lint, pnpm run check green, autoreview clean.

…rebase-or-skip

Apply-lane and comment-sync publications posted canonical record tuples
without any conflict recovery, so the first 409 from a concurrent review
worker killed the entire run mid-checkpoint. Non-reconcile conflicts now
absorb equivalent concurrent writes, rebase unrelated-section races onto
CURRENT with a single deterministic record-tuple-rebase retry, and skip
same-section races per item (syncing CURRENT to the working root) while
the rest of the plan continues; all-items-conflicted still fails the run
and infrastructure errors still throw immediately. Reconcile-lane
recovery is unchanged.
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 automation 🚨 Merging this PR could break CI, automerge, proof capture, label sync, or automation. labels Jul 30, 2026
@clawsweeper

clawsweeper Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 30, 2026, 12:01 PM ET / 16:01 UTC.

ClawSweeper review

What this changes

This PR makes apply and comment-sync publication recover from canonical record-tuple 409 conflicts by accepting equivalent writes, rebasing one unrelated-section race, and skipping same-section conflicts while sibling items continue.

Merge readiness

Blocked until real behavior proof from a real setup is added - 5 items remain

Keep open: this fresh reliability PR addresses a concrete canonical-state publication failure and is not obsolete on current main. The conflict strategy is narrowly scoped and test-covered, but it needs real after-fix behavior proof before merge and should not modify the release-owned changelog.

Priority: P2
Reviewed head: 47193221e44ca7917bb624dc01b2c5475e5f5127

Review scores

Measure Result What it means
Overall readiness 🦪 silver shellfish (2/6) The patch has a coherent bounded design and focused tests, but merge confidence is capped by mock-only proof and the release-owned changelog edit.
Proof confidence 🦪 silver shellfish (2/6) Needs real behavior proof before merge: The PR body reports focused tests and checks, but it does not include inspectable after-fix evidence from a real apply or comment-sync conflict-recovery run. Add a redacted terminal transcript or runtime log, excluding private endpoints, IP addresses, keys, and other sensitive data. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Patch quality 🦐 gold shrimp (3/6) 1 actionable review finding remain.

Verification

Check Result Evidence
Real behavior Needs proof Needs real behavior proof before merge: The PR body reports focused tests and checks, but it does not include inspectable after-fix evidence from a real apply or comment-sync conflict-recovery run. Add a redacted terminal transcript or runtime log, excluding private endpoints, IP addresses, keys, and other sensitive data. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed 4 items Targeted conflict handling: The PR changes the canonical publisher so each tuple returns an explicit resolved or skipped outcome; all-skipped publication remains a failing run, preserving the existing guard against silently succeeding with no canonical progress.
Focused behavioral coverage: The PR adds four cases covering an equivalent concurrent write, an unrelated-section rebase, a same-section skip while a sibling publishes, and all items conflicting.
Repository landing policy: The repository policy requires current real-behavior proof for code-bearing changes and says normal PRs must not edit the release-owned CHANGELOG.md.
Findings 1 actionable finding [P3] Remove the release-owned changelog entry
Security None None.

How this fits together

Apply and comment-sync workflows publish review records to the Worker-backed canonical state store after GitHub-side work has occurred. This publisher must reconcile concurrent review updates without overwriting authoritative sections or stopping an entire checkpoint for one conflicted item.

flowchart LR
  A[Apply or comment-sync run] --> B[Canonical tuple publisher]
  B --> C[Worker canonical state]
  C --> D{409 conflict?}
  D -->|No| E[Publish tuple]
  D -->|Equivalent target| F[Sync current state]
  D -->|Unrelated section| G[Rebase and retry once]
  D -->|Same section| H[Skip item and continue]
  E --> I[Checkpoint outcome]
  F --> I
  G --> I
  H --> I
Loading

Before merge

  • Add real behavior proof - Needs real behavior proof before merge: The PR body reports focused tests and checks, but it does not include inspectable after-fix evidence from a real apply or comment-sync conflict-recovery run. Add a redacted terminal transcript or runtime log, excluding private endpoints, IP addresses, keys, and other sensitive data. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Remove the release-owned changelog entry (P3) - Keep this release-note context in the PR body or commit message instead. The repository policy reserves CHANGELOG.md for release ownership, so this normal repair PR should not modify it.
  • Resolve merge risk (P1) - A skipped same-section conflict occurs after capture-before-mutate side effects; safe retry behavior therefore depends on the existing comment-idempotency and unchanged-edit deduplication fences remaining intact.
  • Resolve merge risk (P1) - The rebase path changes concurrent canonical-record handling in apply and comment-sync automation, so a redacted live conflict-recovery transcript is needed in addition to mocked tuple tests.
  • Complete next step (P2) - The remaining merge blocker is contributor-supplied real behavior proof, which an automated repair lane cannot produce for the contributor's apply/comment-sync environment.

Findings

  • [P3] Remove the release-owned changelog entry — CHANGELOG.md:169
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Patch scope 3 files affected; 366 additions, 14 deletions The change is concentrated in the canonical publisher, focused tests, and one release-note file.
Conflict scenarios 4 focused cases added The tests cover the intended equivalent-write, rebase, skip-with-sibling, and all-skipped outcomes.

Merge-risk options

Maintainer options:

  1. Prove the checkpoint recovery path (recommended)
    Before merge, provide a redacted real apply or comment-sync run that shows a canonical 409 is recovered or skipped per item while an unaffected item completes.
  2. Pause for a narrower rollout
    If a real conflict run cannot be demonstrated safely, pause this branch and land only after maintainers choose a staged validation path for the publisher change.

Technical review

Best possible solution:

Keep the bounded no-force-write recovery, remove the release-owned changelog edit, and add redacted after-fix proof showing a real apply or comment-sync checkpoint absorbs a tuple conflict while unaffected items complete.

Do we have a high-confidence way to reproduce the issue?

Yes at source level: the added focused tests construct the current non-reconcile 409 path and cover each intended recovery outcome. A live after-fix apply or comment-sync run has not been supplied, so runtime confirmation remains needed.

Is this the best way to solve the issue?

Mostly yes: the bounded equivalent/rebase-or-skip path avoids force-writing canonical state and retains an all-skipped failure guard. The release-owned changelog edit is not part of the correct solution and should be removed.

Full review comments:

  • [P3] Remove the release-owned changelog entry — CHANGELOG.md:169
    Keep this release-note context in the PR body or commit message instead. The repository policy reserves CHANGELOG.md for release ownership, so this normal repair PR should not modify it.
    Confidence: 0.99

Overall correctness: patch is correct
Overall confidence: 0.72

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against d91cefcabab2.

Labels

Label changes:

  • add P2: This is a bounded reliability repair for apply and comment-sync runs that can currently stop at a canonical-state conflict.
  • add merge-risk: 🚨 automation: The patch changes checkpoint publication behavior under concurrent Worker state updates, where a mistake could interrupt or repeat automation work.
  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦐 gold shrimp.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body reports focused tests and checks, but it does not include inspectable after-fix evidence from a real apply or comment-sync conflict-recovery run. Add a redacted terminal transcript or runtime log, excluding private endpoints, IP addresses, keys, and other sensitive data. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Label justifications:

  • P2: This is a bounded reliability repair for apply and comment-sync runs that can currently stop at a canonical-state conflict.
  • merge-risk: 🚨 automation: The patch changes checkpoint publication behavior under concurrent Worker state updates, where a mistake could interrupt or repeat automation work.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body reports focused tests and checks, but it does not include inspectable after-fix evidence from a real apply or comment-sync conflict-recovery run. Add a redacted terminal transcript or runtime log, excluding private endpoints, IP addresses, keys, and other sensitive data. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Evidence

What I checked:

  • Targeted conflict handling: The PR changes the canonical publisher so each tuple returns an explicit resolved or skipped outcome; all-skipped publication remains a failing run, preserving the existing guard against silently succeeding with no canonical progress. (src/repair/publish-main.ts:73, 47193221e44c)
  • Focused behavioral coverage: The PR adds four cases covering an equivalent concurrent write, an unrelated-section rebase, a same-section skip while a sibling publishes, and all items conflicting. (test/repair/publish-main.test.ts:362, 47193221e44c)
  • Repository landing policy: The repository policy requires current real-behavior proof for code-bearing changes and says normal PRs must not edit the release-owned CHANGELOG.md. (AGENTS.md:251, d91cefcabab2)
  • Related idempotency protection: The PR body correctly treats merged PR fix(queue): dedupe unchanged pull request edits #857 as adjacent protection for repeated GitHub-side actions, not as a replacement for canonical tuple conflict recovery. (src/repair/publish-main.ts:73, 47193221e44c)

Likely related people:

  • steipete: The PR supplies the operational failure report and a detailed implementation boundary for apply and comment-sync canonical publication; current-main ownership history was not conclusive from the available review material. (role: recent area contributor; confidence: low; commits: 47193221e44c; files: src/repair/publish-main.ts, test/repair/publish-main.test.ts)
  • clawsweeper[bot]: The current PR commit that changes the canonical publication path is attributed to this account. (role: introduced the proposed repair; confidence: medium; commits: 47193221e44c; files: src/repair/publish-main.ts, test/repair/publish-main.test.ts)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Remove the CHANGELOG.md entry.
  • Add a redacted real apply or comment-sync conflict-recovery transcript showing unaffected checkpoint work continues.
  • After updating the PR body with proof, request a fresh ClawSweeper review if it does not rerun automatically.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper

clawsweeper Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper status: review started.

I am starting a fresh review of this pull request: fix(state): recover non-reconcile canonical tuple 409 conflicts with rebase-or-skip This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

@steipete
steipete merged commit df0e4d7 into main Jul 30, 2026
18 checks passed
@steipete
steipete deleted the fix/apply-tuple-conflict-recovery branch July 30, 2026 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 automation 🚨 Merging this PR could break CI, automerge, proof capture, label sync, or automation. P2 Normal priority bug or improvement with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant