feat(release): implement Cutter transactional cut + fold #499 fail-atomic (ADR-0009 §6) #554
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#554
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implement
internal/release.Cuttertransactional cut per ADR-0009 §6 (folds #499 fail-atomic design).Motivation
Phase 6 core substrate.
internal/release.Cutteris the transactional engine underlying all cut orchestrators (rt decide,rt prep,rt release). Per ADR-0009 §6, #499 fail-atomic lands here as first-class transactional design (not a follow-up).Scope
internal/release/*.go— Cutter implementing #505 interface with §6 transactional invariantAC
internal/release.Cutterimplements #505 interface + §6 transactional designgo vet ./...+golangci-lint runcleanAC restate note (2026-07-27, framing-verify surface)
Engineer's framing-verify (bus 6464) surfaced that the original AC bullet "unit tests + equivalence-harness cases green" is not satisfiable at the #554 level, because the bash pipeline's topology Y —
release-prep.sh(seal) in workflow run N anddraft-release.sh(tag+publish) in a separate workflow run M across a PR merge — means no single bash script exists that does what the Cutter does in one transaction. That non-atomicity IS #499; the Cutter's ADR-0009 §6 design opportunity is to UNIFY them.Consequence: no #554-local bash oracle to diff against. The milestone-level bats-oracle gate is satisfied by consumers #556 (rt prep → release-prep.bats) and #557 (rt release → draft-release.bats), both of which DO have bash oracles.
Precedent: Phase 5
internal/selfboot.CommitBake(a library, not a subcommand) was gated by tree-SHA property invariant, not subcommand-diff. Same shape.Design decisions folded into #554 (ratified 2026-07-27):
rt prep(#556). Isolates the CommitBake ambient-identity carry-forward to the consumer; Cutter git-side-effect-free in prefix; rollback = file restore.CreateReleaseDraft(Target=expectedHead)with idempotent-replay viaGetReleaseByTag+ manifest-compare (ErrReplayConflicton disagree / no-op on match).LOCK_EX|LOCK_NB) at construction, repo-root path →ErrConcurrentCut. Workflow-level concurrency deferred to Phase 7 verify (schema-hazard open Q, #499 remedy 1).Rollbackrestores fromTransaction.ConsumedFragments()in-memory. §4 exactly-one-of invariant.Related
Filed 2026-07-27 by Bosun on operator continuation for Phase 6 dispatch. AC restated 2026-07-27 per Engineer framing-verify (bus 6464) + Bosun ratify.
Complete — PR #560 merged @
79e5947(state=closed, merged=true, rebase; main HEAD =79e5947, content-verified:restoreFragments-first-in-(c) +removeFragmentseam + the new regression test all present on main).All 5 ACs satisfied (re-derived from the merged substrate + CI 8/8 green):
Cutterimplements #505 —var _ Cutter = (*cutter)(nil)compile-assert;Prepare/Fire/Rollbackprefix/suffix design.transactionality_test.go: success + gate-fail + injected(b)manifest-fail + injected(c)partial-delete, all assert the exactly-one-of invariant.TestNewCutter_concurrentCut(secondNewCutteron the same root →ErrConcurrentCut).go vet+golangci-lint runclean (0 issues; re-verified inforgejo-ci-go:latest).Review: one round — Surveyor 4606 caught a genuine §4 silent-loss on the
(c)partial-delete rollback path (restored manifest+changelog but not fragments); fixed in the same PR (restoreFragmentsfirst in the(c)rollback) with a reproduce-red → fix → green closed loop, the injection now a permanent regression case. APPROVED 4607, independently verified.#499 stays open — it folds into this Cutter as the ADR-0009 §6 design, and per the milestone it closes at the phase gate (when the orchestrators #555–559 land and the harness is green), not at this PR.
Closing #554 (implementation complete + merged). Downstream: #556 (
rt prep) / #557 (rt release) consume this Cutter and carry the equivalence-harness coverage; #555 (rt decide) is pure-decision, not a Cutter consumer.