fix: git-commit push-retry replay was silently deleting concurrently-merged content - #97
Merged
Merged
Conversation
…merged content Live incident: PyPI wads 0.2.30 (published minutes ago by this session's own rapid PR merges) shipped only 2 of 12 skill files -- the exact #89 bug, re-introduced by wads's own CI automation. Root cause: actions/git-commit's push-back retry (from #81/#83) resolves a version-file conflict during its rebase with `git checkout --theirs`. During `git rebase`, "theirs" is the commit BEING REPLAYED -- this job's own stale pre-fetch snapshot -- not upstream. So when PR #95 (adding [tool.hatch.build]) merged to master while an earlier, now-stale version-bump job was mid-retry, the retry's push was rejected, it rebased, hit a conflict on pyproject.toml, and "resolved" it by overwriting the WHOLE file with its own stale copy -- silently deleting the newly-merged [tool.hatch.build] table along with it. Restores the block directly on master (pyproject.toml) -- the next publish carries the fix to PyPI. Fixes the mechanism in actions/git-commit/action.yml: on a version-file conflict, keep `--ours` (the just-fetched upstream, carrying any real, concurrently-merged content) for the whole file, then surgically reapply only the version-line edit on top, read from the replayed commit's conflict- stage-3 content (`git show :3:<path>`) rather than trusting either side's whole file. Gets both properties #81/#83/#89 each only had half of: real content survives, and the version just published to PyPI still lands in git. New regression test (wads/tests/test_git_commit_push_retry.py) reproduces the exact incident -- a real content addition racing a version bump -- and is confirmed red on the old `--theirs` code, green on the fix. Updated the pre-existing pure-version-race test's message-text assertion for the renamed log line; its actual behavior (which version wins) is unchanged, confirmed by rerunning it against both old and new code. Full suite: 650 passed, 1 skipped (was 649/1 before this test addition). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This was referenced Sep 22, 2026
Closed
thorwhalen
added a commit
to thorwhalen/thoremin
that referenced
this pull request
Sep 22, 2026
PR #210 (074b88d, merged 2026-09-09T08:02) shipped `Clock.timeScale`, `realtimeOutputAllowed` (src/dag/timescale.ts), the Applier publishing the scale onto engine resources, and all three synth-role nodes (webaudio-synth, midi-out, lyria) consulting it before producing real-time output — the mechanism enforcing "never silently pitch-shift" at a non-1x clock speed. PR #213 (9150a02, merged two hours later the same day, "the score pipeline") is unrelated to any of this but its diff deletes every piece of it: timescale.ts, test/timescale_boundary.test.ts, the timeScale property on Clock/BatchClock/RealtimeClock, the TIME_SCALE_KEY publish in Applier, the re-export in dag/index.ts, and the realtimeOutputAllowed guard in all three synth nodes. Nothing in #213's description mentions touching any of this — it has the shape of a bad rebase/merge silently clobbering a sibling PR's content (the same failure mode as i2mint/wads#97). Restored verbatim from 074b88d; reverse-applies cleanly against current main and nothing landed since (#213's own score node, #214 delayed edges, #215 source-node splits) touches these files, so there is no reconciliation needed beyond re-adding what was removed. Verified: typecheck, full test suite (1696 tests / 139 files, including the restored 9-test timescale_boundary.test.ts), and build all green locally. Closes #219 Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary — live incident, urgent
PyPI's
wads0.2.30 (published minutes ago, by this session's own rapid PR merges) shipped only 2 of 12 skill files -- the exact #89 bug, re-introduced by wads's own CI automation right after #95 fixed it. Verified by downloading the real wheel from pypi.org.Root cause:
actions/git-commit's push-back retry (from #81/#83) resolves a version-file conflict during its rebase withgit checkout --theirs. Duringgit rebase, "theirs" is the commit being replayed -- this job's own stale pre-fetch snapshot -- not upstream. When PR #95 (adding[tool.hatch.build]) merged to master while an earlier, now-stale version-bump job was mid-retry, that retry's push was rejected, it rebased, hit a conflict onpyproject.toml, and "resolved" it by overwriting the whole file with its own stale copy -- silently deleting the newly-merged table along with it.Fix
pyproject.toml: restores the[tool.hatch.build]block directly on master. The next publish carries the fix back to PyPI.actions/git-commit/action.yml: on a version-file conflict, keep--ours(the just-fetched upstream, carrying any real concurrently-merged content) for the whole file, then surgically reapply only the version-line edit on top, read from the replayed commit's conflict-stage-3 content (git show :3:<path>) rather than trusting either side's whole file wholesale. This gets both properties uv-ci publish: version-bump push-back is rejected when another merge lands during the run #81/Publish push-back: two concurrent releases conflict on the version line and the replay aborts #83/Canonical skill layout ships 0 skill files: hatchling's symlink walk drops <pkg>/data/skills from the sdist #89 each only had half of: real content survives, AND the version just published to PyPI still lands in git (the reason Publish push-back: two concurrent releases conflict on the version line and the replay aborts #83 exists in the first place).Tests
test_real_content_merged_concurrently_survives_the_version_bump_replayreproduces the exact incident (a real content addition racing a version bump) -- confirmed red on the old--theirscode, green on the fix.test_conflicting_version_bumps_keep_the_replayed_version's message-text assertion for the renamed log line; its actual behavior (which version wins in a pure version-vs-version race) is unchanged -- reran it against both old and new code to confirm..[create,skills,test]).Refs #89, #81, #83.
Test plan
See above -- ran the full suite locally (
wads ci-localequivalent) plus the specific push-retry test module directly against both old and new code to prove the regression test is real.🤖 Generated with Claude Code
https://claude.ai/code/session_011HSBVhDjRU4apSLcRkavv9