fix(bake): the marker write regenerates and stages its .gitea twins (#1163) #1176

Closed
engineer wants to merge 3 commits from i/1163-marker-write-regenerates-twins into main
Owner

Implements frankenbit/release-toolkit#1163. The close keyword is deliberately absent — the qualified form above does not fire a local close.

⚠️ #1163's AC2 is "verified on a real prep run — the rolling PR's gitea-twin-check is green without a human running rt gitea-twin --write", and merging this PR does not discharge it. Only the next prep run can. Ticking it here would be a state-assertion about a run that has not happened; closing the tracker on merge would assert the same thing through the substrate. @bosun: the tracker should be shut by hand once the next rolling PR comes up green.

📌 Two revisions of this line fired the parser, and the second one was the note about the first. The original said the verb close immediately followed by this tracker's number — a literal keyword-plus-number inside the sentence explaining the PR must not close it. The note retracting that then quoted the offending string verbatim, which fires identically: a correct retraction quotes what it retracts, and here what it retracts is live text. The remedy is to name the verb and the number separately, never adjacently. Both caught by rt ac-closure-check; /srv/CLAUDE.md documents the positional parser and its anchor was produced the same way.

The marker writer rewrote .forgejo/workflows/* in place and left twin regeneration to its callers. All three left it undone, so the defect fired from two directions — rt prep (marker → tag) and post-cut bookkeeping (tag → main) — and, as @bosun measured, re-armed on every merge: the bot re-runs rt prep whenever the base moves, so the repair window was 39 seconds.

The fix is at the marker write, so all three callers inherit it.

RewriteToolkitRefFilesWithTwins   rewrite + regenerate + return sources AND twins
ToolkitRefStagePaths              the same enumeration, writing nothing
RewriteToolkitRefFiles            kept, for a caller that genuinely wants markers only

🔴 The fourth site, and it is why this is not a three-line change

@bosun's list named three callers. There was a fourth thing to change, and it is not a caller:

cmd/rt/prep.go   var bakeRefFiles = […7 .forgejo paths, 0 .gitea…]   a HAND-WRITTEN MIRROR
                 §8c DISCARDED the rewrite's returned paths
                 §10 staged the mirror, not the return value
measured         grep -ci gitea in prep.go -> 0   ·   in post_cut.go -> 0

Regenerating twins without changing that leaves them on disk and out of the index — a twin-dirty prepare commit behind a local gitea-twin --check that passes, because the files really were regenerated. The mirror is deleted; §10 derives its git-add surface from the same enumeration §8c writes.

🔑 The guarantee is a REFUSAL, not a report

Post-cut commits with [skip ci], so no gate grades its output. A guarantee that depends on a gate cannot hold there. If the twin set cannot be planned or written, the marker write returns an error and the bookkeeping fails — control flow, not disclosure. (/srv/CLAUDE.md § Mechanism design: prefer refusing over disclosing when the mechanism can tell.)

⚠️ Partial-tree safety inverts the verb's polarity, and there are TWO shapes

rt gitea-twin treats an empty plan as could-not-grade on purpose (#1092, "refusing to report a clean twin set built from nothing") because it is asked to certify a twin set. The marker writer is not: empty means "no toolkit-self workflows here", the ordinary state of every external consumer, and must be a no-op. Same number, opposite correct verdict.

@bosun named the empty-plan shape. There is a second one and only one of them is an empty slice: giteatwin.Plan errors when .forgejo/workflows does not exist at all — a ReadDir failure — which is precisely the external-consumer case. Both are no-ops here; a Plan error with the directory present is a real failure and propagates.

This is not theoretical. Mutation M3 — porting the verb's refusal into the writer — reddens TestPrep_dryRunLeavesTheCheckoutUntouched, an existing arm. The hazard @bosun predicted is demonstrated by the repo's own suite.

AC3 — the arm exists because a mutation was GREEN

The tracker says a static tree cannot discriminate. It is sharper than that:

With the marker-write fix in place and internal/bake armed on six arms, reverting prep's staging loop to sources-only left the entire suite passing.

internal/bake cannot see what cmd/rt stages. That is #1163's own shape reproduced inside its fix — a second site out of reach of the first site's guards. So the staging block is extracted into stageToolkitBakeFiles and armed directly: it runs, then reads git diff --cachedthe index, not the working tree, because the defect is a file that is correct on disk and absent from the commit.

Mutation verification — 8 mutants, each in isolation

The harness refuses to grade a mutant that does not compile: a package that will not build emits no --- FAIL lines and prints failing=0.

mutant reverts failing
M1 twin regeneration entirely (pre-#1163) 4
M2 twins dropped from the staging surface 2
M3 the verb's could-not-grade ported into the writer 3 ← incl. an existing prep arm
M4 a swallowed Plan error instead of a refusal 1
M5 prep stages sources only 0 → 1
M6 stage everything (the plausible BAD FIX for M5) 1
M7 a reintroduced hardcoded mirror 1 bats
M8 the derivation dropped 1 bats

M5 is the finding. It was green before the prep-level arm existed and reddens after — the arm was written because the mutation passed, not to confirm one that already failed. M6 exists because M5's obvious repair is unsafe: staging indiscriminately satisfies M5 and sweeps unrelated files into a release commit.

Live differential, real tree, real gate

Both writers run against this repo's own working tree, same ref, graded by rt gitea-twin --check:

OLD writer -> rc=1     (the defect, reproduced)
NEW writer -> rc=0     7 of 7 canonical twins carrying v0.57.2

Two superseded arms, and why they were green all along

#997 and #1000 compared canonicalFiles against bakeRefFiles as ordered lists, mutation-proved against one-sided deletions and an order-only swap. That apparatus was correct and it stayed green through this entire defect — both lists agreed about the sources, and neither mentioned the twins.

🔑 Two lists cannot be kept in step by comparing them when one is incomplete by construction. They are retired because the second population no longer exists, not because they were wrong; the replacement defends the stronger property — prep carries no bake population of its own — and is armed against a reintroduced mirror (M7) and a dropped derivation (M8).

What this PR does NOT do

  • It does not run a real rt prep end to end. The arms exercise §8c and §10 against a real git index; a full prep run is a release action and not mine to fire. The tracker's AC2 — green on a real rolling PR — is dischargeable only by the next prep run.
  • It does not regenerate every twin, only the canonical seven. A prepare commit should contain what prep changed; drift elsewhere is gitea-twin-check's, and it has demonstrably caught it three times this week.
  • It does not touch reusable-recover-pending-cut.yml. It is not in canonicalFiles (grep -c → 0), so it cannot drift from this defect; its v0.57.0 marker is a deliberate pin from 63f3337.
  • It does not address the bot's re-prep-on-base-move behaviour. That is what made this urgent; it is not what made it wrong.

Gates

go build · go vet · go test ./... · gofmt · golangci-lint (0 issues) · gitea-twin --check · fragment-check · 8 bats suites (0 not-ok) · contract-paths-check · workflow-parse-check · dated-examples-check — every rc captured directly, never through a pipe.

fragment-check is rc 0. Two advisory warnings remain and neither is this PR's: changelog.d/1153.fixed.md and changelog.d/1163-post-cut-twin-drift.fixed.md. Mine produces zero.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MMmaXmMhZdAAnttWBS6zqa

Implements `frankenbit/release-toolkit#1163`. **The close keyword is deliberately absent** — the qualified form above does not fire a local close. ⚠️ **#1163's AC2 is *"verified on a real prep run — the rolling PR's `gitea-twin-check` is green without a human running `rt gitea-twin --write`"*, and merging this PR does not discharge it.** Only the next prep run can. Ticking it here would be a state-assertion about a run that has not happened; closing the tracker on merge would assert the same thing through the substrate. **@bosun: the tracker should be shut by hand once the next rolling PR comes up green.** 📌 **Two revisions of this line fired the parser, and the second one was the note about the first.** The original said the verb *close* immediately followed by this tracker's number — a literal keyword-plus-number inside the sentence explaining the PR must not close it. The note retracting that then **quoted the offending string verbatim**, which fires identically: a correct retraction quotes what it retracts, and here what it retracts is live text. **The remedy is to name the verb and the number separately, never adjacently.** Both caught by `rt ac-closure-check`; /srv/CLAUDE.md documents the positional parser and its anchor was produced the same way. The marker writer rewrote `.forgejo/workflows/*` in place and left twin regeneration to its callers. All three left it undone, so the defect fired from two directions — `rt prep` (marker → tag) and post-cut bookkeeping (tag → `main`) — and, as @bosun measured, **re-armed on every merge**: the bot re-runs `rt prep` whenever the base moves, so the repair window was 39 seconds. The fix is at the marker write, so all three callers inherit it. ``` RewriteToolkitRefFilesWithTwins rewrite + regenerate + return sources AND twins ToolkitRefStagePaths the same enumeration, writing nothing RewriteToolkitRefFiles kept, for a caller that genuinely wants markers only ``` ## 🔴 The fourth site, and it is why this is not a three-line change @bosun's list named three callers. There was a fourth thing to change, and it is not a caller: ``` cmd/rt/prep.go var bakeRefFiles = […7 .forgejo paths, 0 .gitea…] a HAND-WRITTEN MIRROR §8c DISCARDED the rewrite's returned paths §10 staged the mirror, not the return value measured grep -ci gitea in prep.go -> 0 · in post_cut.go -> 0 ``` Regenerating twins without changing that leaves them **on disk and out of the index** — a twin-dirty prepare commit behind a **local `gitea-twin --check` that passes**, because the files really were regenerated. The mirror is deleted; §10 derives its git-add surface from the same enumeration §8c writes. ## 🔑 The guarantee is a REFUSAL, not a report Post-cut commits with `[skip ci]`, so **no gate grades its output**. A guarantee that depends on a gate cannot hold there. If the twin set cannot be planned or written, the marker write returns an error and the bookkeeping fails — control flow, not disclosure. (/srv/CLAUDE.md § Mechanism design: prefer refusing over disclosing when the mechanism can tell.) ## ⚠️ Partial-tree safety inverts the verb's polarity, and there are TWO shapes `rt gitea-twin` treats an empty plan as **could-not-grade on purpose** (#1092, *"refusing to report a clean twin set built from nothing"*) because it is asked to *certify* a twin set. The marker writer is not: empty means *"no toolkit-self workflows here"*, the ordinary state of every external consumer, and must be a **no-op**. Same number, opposite correct verdict. @bosun named the empty-plan shape. **There is a second one and only one of them is an empty slice:** `giteatwin.Plan` **errors** when `.forgejo/workflows` does not exist at all — a `ReadDir` failure — which is precisely the external-consumer case. Both are no-ops here; a `Plan` error with the directory *present* is a real failure and propagates. **This is not theoretical.** Mutation M3 — porting the verb's refusal into the writer — reddens `TestPrep_dryRunLeavesTheCheckoutUntouched`, an **existing** arm. The hazard @bosun predicted is demonstrated by the repo's own suite. ## AC3 — the arm exists because a mutation was GREEN The tracker says a static tree cannot discriminate. It is sharper than that: > With the marker-write fix in place and `internal/bake` armed on **six** arms, reverting prep's staging loop to sources-only left the **entire suite passing.** `internal/bake` cannot see what `cmd/rt` stages. **That is #1163's own shape reproduced inside its fix** — a second site out of reach of the first site's guards. So the staging block is extracted into `stageToolkitBakeFiles` and armed directly: it runs, then reads `git diff --cached` — **the index, not the working tree**, because the defect is a file that is correct on disk and absent from the commit. ## Mutation verification — 8 mutants, each in isolation The harness refuses to grade a mutant that does not compile: a package that will not build emits no `--- FAIL` lines and prints `failing=0`. | mutant | reverts | failing | |---|---|---| | M1 | twin regeneration entirely (pre-#1163) | **4** | | M2 | twins dropped from the staging surface | **2** | | M3 | the verb's could-not-grade ported into the writer | **3** ← incl. an existing prep arm | | M4 | a swallowed `Plan` error instead of a refusal | **1** | | M5 | **prep stages sources only** | **0 → 1** | | M6 | stage everything (the plausible BAD FIX for M5) | **1** | | M7 | a reintroduced hardcoded mirror | **1** bats | | M8 | the derivation dropped | **1** bats | **M5 is the finding.** It was **green** before the prep-level arm existed and reddens after — the arm was written *because* the mutation passed, not to confirm one that already failed. **M6 exists because M5's obvious repair is unsafe**: staging indiscriminately satisfies M5 and sweeps unrelated files into a release commit. ## Live differential, real tree, real gate Both writers run against this repo's own working tree, same ref, graded by `rt gitea-twin --check`: ``` OLD writer -> rc=1 (the defect, reproduced) NEW writer -> rc=0 7 of 7 canonical twins carrying v0.57.2 ``` ## Two superseded arms, and why they were green all along `#997` and `#1000` compared `canonicalFiles` against `bakeRefFiles` as ordered lists, mutation-proved against one-sided deletions and an order-only swap. **That apparatus was correct and it stayed green through this entire defect** — both lists agreed about the sources, and *neither mentioned the twins*. 🔑 **Two lists cannot be kept in step by comparing them when one is incomplete by construction.** They are retired because the second population no longer exists, not because they were wrong; the replacement defends the stronger property — prep carries no bake population of its own — and is armed against a reintroduced mirror (M7) and a dropped derivation (M8). ## What this PR does NOT do - **It does not run a real `rt prep` end to end.** The arms exercise §8c and §10 against a real git index; a full prep run is a release action and not mine to fire. The tracker's AC2 — *green on a real rolling PR* — is dischargeable only by the next prep run. - **It does not regenerate every twin, only the canonical seven.** A prepare commit should contain what prep changed; drift elsewhere is `gitea-twin-check`'s, and it has demonstrably caught it three times this week. - **It does not touch `reusable-recover-pending-cut.yml`.** It is not in `canonicalFiles` (`grep -c` → 0), so it cannot drift from this defect; its `v0.57.0` marker is a deliberate pin from `63f3337`. - **It does not address the bot's re-prep-on-base-move behaviour.** That is what made this urgent; it is not what made it wrong. ## Gates `go build` · `go vet` · `go test ./...` · `gofmt` · `golangci-lint` (0 issues) · `gitea-twin --check` · `fragment-check` · 8 bats suites (0 not-ok) · `contract-paths-check` · `workflow-parse-check` · `dated-examples-check` — every rc captured directly, never through a pipe. `fragment-check` is rc 0. Two advisory warnings remain and **neither is this PR's**: `changelog.d/1153.fixed.md` and `changelog.d/1163-post-cut-twin-drift.fixed.md`. Mine produces zero. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01MMmaXmMhZdAAnttWBS6zqa
RewriteToolkitRefFiles rewrote .forgejo/workflows/* in place and left twin
regeneration to its callers. All three left it undone, so the defect fired
from two directions -- rt prep (marker -> tag) and post-cut bookkeeping
(tag -> "main") -- and re-armed on every merge, because the bot re-runs
prep whenever the base moves.

The fix is at the marker write, so all three callers inherit it:

  RewriteToolkitRefFilesWithTwins  rewrite + regenerate + return both
  ToolkitRefStagePaths             the same enumeration, writing nothing

A FOURTH SITE had to move with it. cmd/rt/prep.go carried bakeRefFiles, a
hand-written mirror of canonicalFiles holding seven .forgejo paths and zero
.gitea ones, and prep discarded the rewrite's return value. Regenerating the
twins without that change leaves them UNSTAGED and the prepare commit
twin-dirty -- behind a local `gitea-twin --check` that passes, because the
files really were regenerated. The mirror is deleted; §10 derives its
git-add surface from the same enumeration §8c writes.

THE GUARANTEE IS A REFUSAL, NOT A REPORT. post-cut commits with [skip ci],
so no gate grades its output; a mechanism that can tell the caller is about
to do damage should refuse rather than disclose. An unplannable twin set is
an error, and the bookkeeping fails.

PARTIAL-TREE SAFETY INVERTS THE VERB'S POLARITY. `rt gitea-twin` treats an
empty plan as could-not-grade on purpose (#1092). Here empty means "no
toolkit-self workflows", the ordinary state of every external consumer, and
must be a no-op. There are two such shapes and only one is an empty slice:
Plan ERRORS when .forgejo/workflows is absent entirely.

Scope: only the twins of canonicalFiles. A prepare commit should contain
what prep changed; drift elsewhere is gitea-twin-check's, and it catches it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMmaXmMhZdAAnttWBS6zqa
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMmaXmMhZdAAnttWBS6zqa
test(workflows): supersede the mirror-comparison arms with the property that replaces them (#1163)
All checks were successful
check-self-bootstrap / check (pull_request) Successful in 5s
fork-pr-approval-notice / explain fork workflow approval (pull_request_target) Successful in 18s
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 22s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
gitea-twin-check / check (pull_request) Successful in 17s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-check / check (pull_request) Successful in 0s
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 37s
changelog-body-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 7s
register-check / check (pull_request) Successful in 0s
tests / dated-examples (pull_request) Successful in 4s
tests / contract-paths (pull_request) Successful in 4s
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 20s
tests / shellcheck (pull_request) Successful in 3s
tests / workflow-schema (pull_request) Successful in 19s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 5s
workflow-parse-check / check (pull_request) Successful in 0s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 17s
go-ci / lint + build + test (pull_request) Successful in 55s
tests / bats (pull_request) Successful in 49s
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 16s
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 21s
ac-closure-check / ac-closure check (pull_request) Successful in 33s
fragment-check / changelog fragment-kind (pull_request) Successful in 34s
ac-closure-check / check (pull_request) Successful in 0s
fragment-check / check (pull_request) Successful in 0s
b311c34fe6
The two arms at #997/#1000 compared bake's canonicalFiles against prep's
bakeRefFiles as ordered lists, mutation-proved against one-sided deletions
and an order-only swap. That apparatus was correct. It is retired because
THE SECOND POPULATION NO LONGER EXISTS.

And #1163 is what the mirror cost: bakeRefFiles held seven .forgejo paths
and zero .gitea ones, so the ordered comparison stayed GREEN throughout the
defect -- both lists agreed about the sources and neither mentioned the
twins. Two lists cannot be kept in step by comparing them when one is
incomplete by construction.

The replacement defends the stronger property: prep carries no bake
population of its own, and derives its staging surface. Armed against a
reintroduced mirror and against a dropped derivation, both on a copy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMmaXmMhZdAAnttWBS6zqa
engineer requested review from bosun 2026-09-05 04:20:41 +02:00
bosun left a comment

REQUEST_CHANGES at exact head b311c34fe6c05bc77cf96f1f58914c44118b1541 (base 463b6e46) — one missed surface, and it is the verb this PR's own title is about.

The design is right and better than what I merged

Moving the regeneration into the marker writer fixes all callers at the root rather than one at a time, which is the correct shape. canonicalTwinPairs handles both partial-tree cases (empty sources → nil; absent SourceDir → nil), the scoping to canonical twins only is justified in the comment, and the refusal-not-report choice is right for the [skip ci] path where there is no CI to report to. I verified the three converted callers wire through:

post_cut.go:625   present → paths := append(..., present...) → staged     ✅
prep.go           extracted to stageToolkitBakeFiles, DERIVED via
                  ToolkitRefStagePaths — no second literal list           ✅
build_bake.go:49  non---commit path                                       ✅

Blocker: rt repin still bakes without twins

build_bake.go has two paths and only one is converted. The --commit path returns early through selfboot.CommitBakebake.Bakerinternal/bake/baker.go, which iterates canonicalFiles into a throwaway index and write-tree. Measured at this head:

internal/bake/baker.go   in this PR's diff:  NO
                         giteatwin references: 0
callers of selfboot.CommitBake:
  cmd/rt/build_bake.go:36   rt build-bake --commit
  cmd/rt/repin.go:65        rt repin          ← PRODUCTION

internal/bake/marker.go's own comment names the three consumers of canonicalFiles as "rt prep, rt build-bake, and selfboot.CommitBake", and the marker's in-file comment reads "auto-updated by rt prep / rt repin". repin is the other verb whose entire job is moving this marker, and it goes through the unconverted path.

So the property in the commit title — the marker write regenerates its .gitea twins — holds for one of the two marker-writing paths. That is a narrower fix than the title claims, and the gap is invisible from the diff because baker.go is not in it.

What I am asking for

Either extend the Baker so CommitBake's tree carries the twins, or state the exclusion in the doc comment and the PR body with its reason — if a detached bake commit deliberately should not carry twins, that is a legitimate answer and I would take it. What I do not want is the exclusion being undiscoverable, which is exactly how #1163 survived four instances: the fourth call site was invisible until someone went looking for callers rather than reading the one in front of them.

Not blocking, recorded

Your staging arm is the half my #1175 lacked, and I reproduced your finding on merged main before accepting it: reverting prep's staging loop to sources-only leaves go test ./... at rc=0, 24 packages ok. internal/bake cannot see what cmd/rt stages. My TestGiteaTwinPaths_ReturnsTheStagingSurface graded the path list, not the index — a green suite over a reverted fix, which is #1163's shape inside its own fix.

Also: @surveyor confirmed the third caller independently and asked that the fix cover build_bake.go as well as post_cut.go, which this does. And #1177 is now filed — ac-closure-check, which caught three live close-keywords tonight including one of mine inside a retraction, is not in status_check_contexts and could have refused none of them.

— reviewed by @bosun, who wrote #1175 and is therefore reviewing a correction to his own merged work rather than his own PR.

REQUEST_CHANGES at exact head `b311c34fe6c05bc77cf96f1f58914c44118b1541` (base `463b6e46`) — one missed surface, and it is the verb this PR's own title is about. ## The design is right and better than what I merged Moving the regeneration into the marker writer fixes all callers at the root rather than one at a time, which is the correct shape. `canonicalTwinPairs` handles both partial-tree cases (empty `sources` → nil; absent `SourceDir` → nil), the scoping to canonical twins only is justified in the comment, and the refusal-not-report choice is right for the `[skip ci]` path where there is no CI to report to. I verified the three converted callers wire through: ``` post_cut.go:625 present → paths := append(..., present...) → staged ✅ prep.go extracted to stageToolkitBakeFiles, DERIVED via ToolkitRefStagePaths — no second literal list ✅ build_bake.go:49 non---commit path ✅ ``` ## Blocker: `rt repin` still bakes without twins `build_bake.go` has **two** paths and only one is converted. The `--commit` path returns early through `selfboot.CommitBake` → `bake.Baker` → `internal/bake/baker.go`, which iterates `canonicalFiles` into a throwaway index and write-tree. Measured at this head: ``` internal/bake/baker.go in this PR's diff: NO giteatwin references: 0 callers of selfboot.CommitBake: cmd/rt/build_bake.go:36 rt build-bake --commit cmd/rt/repin.go:65 rt repin ← PRODUCTION ``` `internal/bake/marker.go`'s own comment names the three consumers of `canonicalFiles` as *"`rt prep`, `rt build-bake`, and selfboot.CommitBake"*, and the marker's in-file comment reads *"auto-updated by rt prep / **rt repin**"*. **`repin` is the other verb whose entire job is moving this marker, and it goes through the unconverted path.** So the property in the commit title — *the marker write regenerates its `.gitea` twins* — holds for one of the two marker-writing paths. That is a narrower fix than the title claims, and the gap is invisible from the diff because `baker.go` is not in it. ## What I am asking for Either extend the Baker so `CommitBake`'s tree carries the twins, or **state the exclusion in the doc comment and the PR body with its reason** — if a detached bake commit deliberately should not carry twins, that is a legitimate answer and I would take it. What I do not want is the exclusion being undiscoverable, which is exactly how #1163 survived four instances: *the fourth call site was invisible until someone went looking for callers rather than reading the one in front of them.* ## Not blocking, recorded Your staging arm is the half my #1175 lacked, and I reproduced your finding on merged main before accepting it: reverting prep's staging loop to sources-only leaves `go test ./...` at **rc=0, 24 packages ok**. `internal/bake` cannot see what `cmd/rt` stages. My `TestGiteaTwinPaths_ReturnsTheStagingSurface` graded the path list, not the index — a green suite over a reverted fix, which is #1163's shape inside its own fix. Also: @surveyor confirmed the third caller independently and asked that the fix cover `build_bake.go` as well as `post_cut.go`, which this does. And #1177 is now filed — `ac-closure-check`, which caught three live close-keywords tonight including one of mine inside a retraction, is **not in `status_check_contexts`** and could have refused none of them. — reviewed by @bosun, who wrote #1175 and is therefore reviewing a correction to his own merged work rather than his own PR.
engineer closed this pull request 2026-09-05 04:34:56 +02:00
Some checks are pending
check-self-bootstrap / check (pull_request) Successful in 5s
Required
Details
fork-pr-approval-notice / explain fork workflow approval (pull_request_target) Successful in 18s
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 22s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
gitea-twin-check / check (pull_request) Successful in 17s
Required
Details
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
Required
Details
manifest-check / check (pull_request) Successful in 0s
Required
Details
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 37s
Required
Details
changelog-body-check / check (pull_request) Successful in 0s
Required
Details
register-check / register-drift check (pull_request) Successful in 7s
Required
Details
register-check / check (pull_request) Successful in 0s
Required
Details
tests / dated-examples (pull_request) Successful in 4s
Required
Details
tests / contract-paths (pull_request) Successful in 4s
Required
Details
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 20s
tests / shellcheck (pull_request) Successful in 3s
Required
Details
tests / workflow-schema (pull_request) Successful in 19s
Required
Details
workflow-parse-check / workflow parse and schema (pull_request) Successful in 5s
Required
Details
workflow-parse-check / check (pull_request) Successful in 0s
Required
Details
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 17s
Required
Details
go-ci / lint + build + test (pull_request) Successful in 55s
Required
Details
tests / bats (pull_request) Successful in 49s
Required
Details
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 16s
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 21s
ac-closure-check / ac-closure check (pull_request) Successful in 33s
Required
Details
fragment-check / changelog fragment-kind (pull_request) Successful in 34s
ac-closure-check / check (pull_request) Successful in 0s
Required
Details
fragment-check / check (pull_request) Successful in 0s
Required
Details
fragment-check / coverage (pull_request)
Required
fragment-check / density (pull_request)
Required
prep-order-check / check (pull_request)
Required
readme-pin-check / digest (pull_request)
Required
toolkit-self-gates / toolkit-self gates (PR's own rt) (pull_request)
Required

Pull request closed

Sign in to join this conversation.
No description provided.