Skip to content

SMOODEV-2769: Fix th pearls pull wedging on uncommitted agents heartbeat - #283

Merged
brentrager merged 3 commits into
mainfrom
SMOODEV-2769-pearls-pull-dirty
Jul 26, 2026
Merged

SMOODEV-2769: Fix th pearls pull wedging on uncommitted agents heartbeat#283
brentrager merged 3 commits into
mainfrom
SMOODEV-2769-pearls-pull-dirty

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

Problem

th pearls pull failed on every invocation with:

Error: smooth-dolt pull failed (exit 1): smooth-dolt: pull: Error 1105: cannot merge with uncommitted changes

Found while syncing pearls/Jira. It looked like store corruption — but th pearls doctor reported the store healthy and in sync, and th pearls push succeeded throughout.

The asymmetry is the tell. DOLT_PUSH only ships committed history, so it doesn't care about a dirty working set. DOLT_PULL merges, 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 inbox and the th msg watch poll loop call AgentRegistry::touch to heartbeat the agents table with no commit behind it (crates/smooth-cli/src/main.rs:4072 and :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 watch could never receive remote messages. It calls sync_pull_pearl_state, which swallows pull errors — so each poll's heartbeat blocked the next poll's pull, forever, silently.

Fix

SmoothDolt::pull commits the working set before merging, via a new commit_working_set helper that no-ops on a clean store (commit passes --allow-empty, so an unconditional call would add an empty commit per pull).

Fixed at the shared choke point rather than at each touch call 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

  • New test commit_working_set_cleans_dirty_store_and_noops_when_clean inits 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 the smooth-dolt binary isn't built.
  • cargo test -p smooai-smooth-pearls180 passed, 0 failed.
  • cargo fmt --check clean; no new clippy warnings (missing_errors_doc is 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

… 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-bot

changeset-bot Bot commented Jul 26, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ebbf0e8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@smooai/smooth Patch

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
brentrager enabled auto-merge (squash) July 26, 2026 21:44
@brentrager
brentrager merged commit 7f6b64f into main Jul 26, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant