Every adapter's postWrite — Python, Rust, Go and Ruby — and the regenerateLockfiles that drives them were written, tested, and exported from the public API.
Nothing called any of it.
So Buddy updated a pyproject.toml, Cargo.toml, go.mod or Gemfile and committed it with its lockfile still describing the version being replaced.
That is exactly the lockfile-drift failure fix-ci classifies — arriving on a pull request Buddy opened itself, for the four ecosystems where Buddy is the only thing that would have fixed it.
Ordering is the whole point
generateAdapterFileUpdates now writes the manifests to disk before the regeneration runs:
for (const change of changes)
await Bun.write(join(this.projectPath, change.path), change.content)
const { regenerated, notes } = await regenerateLockfiles(this.projectPath, ecosystems)postWrite shells out to uv lock, cargo update, go mod tidy or bundle lock — all of which read the manifest from the working tree, not the change about to be committed. Running them first would lock the old version.
Writing to the tree is acceptable here because it's a CI checkout discarded after the run, and commitChanges rebuilds the branch from base regardless. It wouldn't be acceptable anywhere longer-lived, which is why it's confined to the branch that already produced manifest changes.
The existing machinery needed no changes
It's careful already — a lockfile is only regenerated if it already exists, a missing tool is reported as a note rather than a failure, and a tool that exits non-zero is reported the same way.
Those notes now reach the log. A pull request carrying a manifest its lockfile doesn't match is worth saying out loud.
Left alone deliberately
postWrite takes the repository root, so a monorepo with packages/api/pyproject.toml regenerates nothing — regenerateWith looks for the lockfile beside the root and finds none. That's the adapter interface's shape rather than this wiring's, and narrowing it here would guess at an answer the interface hasn't made.
Tests
2110 → 2115.
Note on the run: test/stacked-touches.test.ts was failing for me on unrelated grounds — the machine's Xcode command-line-tools licence had lapsed, so every git invocation errored and the git-dependent tests went with it. Resolved, and the suite is green.
Lint ✓ · typecheck ✓ · check:docs ✓ · 0 fail
🤖 Generated with Claude Code