Repository navigation
Conversation
gbrain 0.51 (garrytan/gbrain#5149, 2026-09-17) made `put` refuse to replace an existing page unless the caller sends the revision it read: exit 1, a JSON receipt on stdout and `Error [revision_required]` on stderr. devbrain forwards `put` verbatim and Rebuild runs `gbrain put <slug>` with the file on stdin, so with gbrain >= 0.51 every update of an already-indexed page failed and `devbrain rebuild` aborted at the first one. The distill skill ran its put loop with output discarded, so the index quietly froze at each page's first version. putPage runs the put and, when gbrain answers revision_required, runs it once more with --force, replaying the same stdin. The Markdown page on disk is devbrain's source of truth and this wrapper is the index's only writer, so the disk copy always wins; a revision conflict is never real here, and a get round-trip for --expected-revision would add a failure mode without adding safety. Older engines never answer revision_required and so never see --force; a caller's own --force or --expected-revision gets gbrain's answer unchanged, as does any other failure. stdin is buffered only when gbrain would read it (not for an inline --content), so an interactive put cannot block on a terminal. Both call sites use it. The distill skill now reports a failing put instead of hiding it. Tests: black-box put retry, put non-retry on another error, rebuild retry (all watched failing on main first), and the stdin/--content detection table. make test green; verified against gbrain 0.60.248. Co-Authored-By: Claude Fable 5.1 <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.
In plain words: since gbrain 0.51 (2026-09-17),
devbrain brain putanddevbrain rebuildcould create a page but never update one that already existed. Every re-fold of an existing brain page died withrevision_required, and the distill skill threw the error away, so the search index quietly froze at each page's first version. This PR makes updates land again and makes a failing put visible.Problem
gbrain's "make concurrent writes durable and revision-safe" release (garrytan/gbrain#5149, v0.51.0.0) changed
put: replacing an existing page now needs--expected-revision <rev>(or--force). Otherwise gbrain exits 1 with a JSON receipt on stdout and this on stderr:devbrain forwards
putverbatim (internal/brain/brain.go,passthrough) andRebuildrunsgbrain put <slug>with the file on stdin (internal/brain/rebuild.go). Neither sends a revision, so with gbrain ≥ 0.51:devbrain brain put <slug> < page.mdon an existing slug exits 1;devbrain rebuildaborts at the first already-indexed page (its set -e semantics);/distillstep 5 randevbrain brain put … >/dev/null 2>&1, so nobody saw it. On my machine the index held 227 pages frozen at their first write, andgbrain doctorhad nothing to say because the writes never reached it.Fix
putPage(new,internal/brain/put.go) runs the put; when gbrain answersrevision_requiredit runs the same put once more with--force, replaying the same stdin bytes. Both call sites (Runpassthrough andRebuild) use it.Why
--forcerather than a read-then-write with--expected-revision: devbrain's Markdown pages on disk are the source of truth and this wrapper is the index's only writer, so the disk copy always wins. A revision conflict is never a real one here, and agetround-trip would add a failure mode without adding safety.revision_required, so they never see--force(compatible with gbrain < 0.51).--forceor--expected-revisionthemselves gets gbrain's own answer (those outcomes carry other codes, so no retry). Any other failure is relayed unchanged with gbrain's exit code.--content <text>/--content=<text>), so an interactiveput --contentcannot block on a terminal.assets/skills/distill/SKILL.mdstep 5: the put loop now printsbrain put failed for <slug>: <last line>instead of>/dev/null 2>&1, and tells the agent to carry that into the fold summary.Tests
All through the built binary with a gbrain stub that reproduces gbrain 0.60's exact failure shape:
TestBrainPutRetriesWithForceOnRevisionRequired: exit 0; gbrain calls are exactlyput <slug>thenput <slug> --force; both receive identical stdin; norevision_requiredleaks into the output; the retry's output is forwarded.TestBrainPutLeavesOtherFailuresAlone: a different error (invalid_params, exit 2) is not retried and passes through with its exit code.TestRebuildForcesUpdatesOfExistingPages:devbrain rebuildwith one on-disk page: same retry, exit 0, progress line printed.TestPutNeedsStdin: stdin versus inline--contentdetection, including gbrain's "a trailing--contentreads stdin".I watched the three behavioral tests fail on main first (exit 1 with the receipt, a single gbrain call).
make testis green (30 packages).Verified against the real engine (gbrain 0.60.248.0): the built binary updates an existing page (exit 0; gbrain's receipt reports
status: skippedfor identical content), while the stock 1.5.30 binary fails withError [revision_required]on the same call.🤖 Generated with Claude Code