SMOODEV-2769: Fix th pearls pull wedging on uncommitted agents heartbeat - #283
Merged
Conversation
… stops wedging DOLT_PULL merges, and Dolt refuses to merge a dirty working set. But read-path commands dirty it as a side effect: `th msg inbox` and the `th msg watch` poll loop heartbeat the `agents` table via AgentRegistry::touch without committing behind it. The result was `th pearls pull` bailing with "cannot merge with uncommitted changes" on every invocation — and worse, `th msg watch` silently never receiving remote messages, because it swallows pull errors and its own heartbeat blocked the next poll's pull. `push` was unaffected and reported success throughout, since DOLT_PUSH only ships committed history, which is what made this look like store corruption rather than a merge precondition. Fix at the shared choke point rather than at each writer: pull now commits the working set first, so any dirtier — including a command interrupted midway — can't permanently wedge it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: ebbf0e8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
brentrager
enabled auto-merge (squash)
July 26, 2026 21:44
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.
Problem
th pearls pullfailed on every invocation with:Found while syncing pearls/Jira. It looked like store corruption — but
th pearls doctorreported the store healthy and in sync, andth pearls pushsucceeded throughout.The asymmetry is the tell.
DOLT_PUSHonly ships committed history, so it doesn't care about a dirty working set.DOLT_PULLmerges, and Dolt refuses to merge while the working set is dirty.And the working set was dirty as a side effect of ordinary reads:
th msg inboxand theth msg watchpoll loop callAgentRegistry::touchto heartbeat theagentstable with no commit behind it (crates/smooth-cli/src/main.rs:4072and:4130). Committing manually right before a pull didn't help either — the pull's own startup re-dirtied it.The quieter half of the bug:
th msg watchcould never receive remote messages. It callssync_pull_pearl_state, which swallows pull errors — so each poll's heartbeat blocked the next poll's pull, forever, silently.Fix
SmoothDolt::pullcommits the working set before merging, via a newcommit_working_sethelper that no-ops on a clean store (commitpasses--allow-empty, so an unconditional call would add an empty commit per pull).Fixed at the shared choke point rather than at each
touchcall site: every pull path routes through here, so an interrupted command or a future writer can't wedge pull either. Best-effort — if the commit fails the pull still runs and reports Dolt's own error, so this can only turn a failing pull into a working one.Verification
commit_working_set_cleans_dirty_store_and_noops_when_cleaninits a real Dolt store in a tempdir, dirties it the way the heartbeat does, and asserts the working set ends clean (and that a clean store is a no-op). Skips where thesmooth-doltbinary isn't built.cargo test -p smooai-smooth-pearls— 180 passed, 0 failed.cargo fmt --checkclean; no new clippy warnings (missing_errors_docis warn-level and pre-existing across every neighbor in the file).Notes
Not addressed here, and now largely mooted by this fix: the heartbeat previously never reached the remote at all, since nothing committed it. With pull committing the working set, it gets swept up on the next sync.
🤖 Generated with Claude Code