cairn: add PromotedBeadID writer + promote-mark CLI#50
Merged
Conversation
Neutral name so cmd/promote.go's upcoming promote-mark command can reuse the same Find-bypassing lookup instead of adding a near-duplicate.
Add `cairn promote-mark <id> --bead <bead-id>`: tier-conditional dispatch for PromotedBeadID, mirroring the shape already shipped for RecurrenceCount and CULL. Private scope commits directly; shared scope proposes a review branch via the new requestPromotionReview/ sendPromotionReviewMail (cmd/reviewer.go), mailing the reviewer to merge with `cairn review merge` since a promotion mark is a content change, not a deletion. PromotedBeadID doubles as an idempotency guard: repeating the same bead ID is a no-op success; a different bead ID on an already-promoted entry is refused rather than silently overwritten.
… crn-ghn8.2) The step already filed a bead per recurrence-promotion finding via bd create, but never persisted the promotion back onto the cairn entry, so promote-candidates kept re-reporting the same findings forever. Call cairn promote-mark <entry-id> --bead <bead-id> immediately after bd create returns its ID, mirroring how the capture-time recurrence path calls WriteBackRecurrenceCount right after incrementing RecurrenceCount. Applied identically to both mol-cairn-librarian.formula.toml and mol-cairn-librarian-rig.formula.toml per TestLibrarianRigFormulaHasSameStepsAsLibrarian.
…fs crn-lox2) Every call site (2 in cmd/cull_test.go, 5 in cmd/promote_test.go) passed the literal "old-fact", tripping golangci-lint's unparam check. Hardcode it inside the helper instead of threading a parameter that never varies.
quad341
added a commit
that referenced
this pull request
Jul 24, 2026
* test: librarian PROMOTE/CULL step idempotency (crn-28ge.1.11) promote-candidate-beads and cull-candidate-beads (crn-28ge.1.8, now on main) must skip already-tracked findings via the same bd-list-before- bd-create idiom the other three sweep steps use, or a second pass over an unchanged findings set files duplicate beads. cull-candidate-beads carries a sharper invariant: cairn cull-evict itself hard-errors on a repeat call for the same entry (its review branch name is deterministic), so the EXISTING check must run BEFORE that call, not just before the eventual bd create. Added an ordering- specific test for that beyond the shared presence check. Authored by validator (gc-validator-7306216f5c97 @ aa030f5); builder independently re-verified against clean origin/main (4858187) in an isolated worktree: gofmt/vet/build/full-suite -race all green, targeted TestLibrarian* tests pass individually and via full run. refs crn-28ge.1.11 * release-gate: librarian PROMOTE/CULL step idempotency test (crn-0sdm) Gate PASS for edc4937 (formulas/formulas_test.go, +61/-0, test-only). Bounded self-rebase performed: origin/main advanced to 5bf87a6 (PR #50) past the reviewed commit's assumed base; reconciled via cherry-pick (disjoint files, clean merge-tree). New tip 34eb1fa, content-identical to the reviewed commit.
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.
What this changes
Adds a way to record, on a memory entry itself, which bead it was promoted
into — a
PromotedBeadIDfield written back into the entry's TOMLfrontmatter — plus a new
cairn promote-mark --bead <id>CLI command thatsets it.
promote-markdispatches on the entry's scope tier: for a private-scopeentry it commits the field directly; for a shared/rig-scope entry it opens
the existing review-request flow instead (same "commit to a review branch,
mail a reviewer" path other write-back operations already use), so a
promotion into shared memory still gets a human/reviewer look before it's
final. Calling it twice with the same bead ID is a no-op success; calling it
again with a different bead ID is a hard error rather than silently
overwriting the original promotion record.
Why built this way
Mirrors the existing
RecurrenceCountwrite-back mechanism's exact shape(same anchor-based TOML frontmatter patch, same tier-conditional commit vs.
review-request dispatch) rather than introducing a new pattern — keeps this
consistent as cairn accumulates more "record something back onto the entry"
operations.
Review notes
cmd/promote.gointernal/cairn/entry.go(WriteBackPromotedBeadID,patchPromotedBeadID)internal/cairn/remember.go(
CommitPromotionToReviewBranch)cmd/reviewer.go(
requestPromotionReview/sendPromotionReviewMail)EntryForEvict→EntryByID— thelookup helper is now shared between
cull's eviction path andpromote-mark, so the name was generalized.Test plan
go build ./.../go vet ./...cleango test ./... -race— all packages greenshared-scope review-request, same-bead-ID idempotency, different-bead-ID
hard error (
cmd/promote_test.go)release-gates/promoted-bead-id-writer-promote-mark-gate.md