fix(prep): regenerate and stage the .gitea twins after the bake #1175

Merged
bosun merged 1 commit from i/1163-prep-regenerates-twins into main 2026-09-05 04:25:23 +02:00
Owner

rt prep rewrote the .forgejo bake markers and left the generated .gitea twins untouched, so every prepare commit was twin-dirty and gitea-twin-check reddened on the rolling PR.

Why this stopped being a once-per-release annoyance

The release bot re-runs rt prep on every base move, so a hand-fix is destroyed by the next merge to main. Measured 2026-09-05:

04:02      the twins are repaired by hand → 5243b9dc, 7/7 at v0.57.2, CI 27/27 GREEN
04:05:24   #1169 merges → main = 3def64ef
04:06:03   the bot regenerates the prepare → 6a3c9c17, 7/7 DRIFT again
                        ── 39 seconds ──

A campaign that merges PRs re-breaks the release it is trying to cut. v0.57.2 is held on this.

The staging list is DERIVED, not a second literal

cmd/rt/prep.go's bakeRefFiles is a hardcoded mirror of bake's canonicalFiles — seven .forgejo paths, zero .gitea — and that mirror is exactly how the twins came to be omitted. A second hardcoded list would reproduce the same failure one directory over, so commitAndPush calls giteatwin.Plan(repoRoot) instead. Plan reads the .forgejo sources from disk, which §8c has already rewritten, so it returns precisely the pairs that were written.

📌 That is also why there is no signature change on commitAndPush — the function that commits and pushes a release. runPrep and commitAndPush both already take repoRoot, so the path list never has to cross the boundary. @engineer named the signature change as the reason to defer this; deriving removes the need for it.

The consumer case is a THIRD state, and it is the one that could wedge external cuts

Plan opens .forgejo/workflows with os.ReadDir and returns an error when it does not exist — it does not return zero pairs. So a consumer without that directory arrives as a failure, and a guard keyed only on len(pairs)==0 would abort their release.

absent .forgejo/workflows      Plan ERRORS      → no-op  (sourceDirAbsent)
present, no reusable-*.yml     Plan returns 0   → no-op
toolkit-self                   Plan returns N   → regenerate + stage

rt gitea-twin refuses on an empty plan on purpose (#1092 — "refusing to report a clean twin set built from nothing"). rt prep must not: same number, opposite correct verdict. This is the rule bake.RewriteToolkitRefFiles already applies with its os.IsNotExist → continue. Both consumer shapes have their own arm, because they reach the no-op by different routes.

Mutation-verified, and the first fixture was wrong

Removing the regeneration reddens TestBakeThenRegenerate_LeavesNoDrift with missing=false and "twin still carries the pre-bake ref 'main'"#1163's exact symptom. The negative control and the staging arm correctly still pass, so exactly one arm is targeted.

🔴 The first version of the fixture seeded its twin with regenerateGiteaTwins — the function under test — and the mutation run caught it. Nulling that function reddened the arm with missing=true: the twin had never been written at all, so the arm was grading its own setup rather than the post-bake regeneration. A real #1163 is missing=false with differing content, and that fixture could not produce the state. It now seeds with giteatwin.Twin directly, and TestBakeWithoutRegenerate_Drifts fails loudly if a twin is ever Missing, so the fixture cannot silently regress to grading itself.

Verification

go build ./...     rc=0, stderr empty
go vet ./...       rc=0, stderr empty
gofmt -l           clean
go test ./...      rc=0 — 24 packages ok, 0 failed

What this does NOT fix

  • #1173reusable-recover-pending-cut.yml is absent from canonicalFiles entirely, so neither surface is ever bumped. Different defect, same file family; assigned to @quartermaster.
  • @engineer's AC — make the marker writer refuse when Plan() fails. Orthogonal and still worth doing: it fixes silent, this fixes broken.

AC status — the tracker stays open, and ac-closure-check was right to say so

The first push carried a close-keyword naming that tracker. It over-claimed, the gate caught it, and the gate's reading is correct.

🔴 And the SECOND push did not fix it, for the reason the gate itself prints. The correction was written as a heading saying the PR does not close the tracker — the negated form, which fires anyway: Forgejo's parser is positional and does not read negation, and /srv/CLAUDE.md carries that exact warning with an anchor reading "I caught the wrong-repo close, then 'fixed' it by writing the negation form — which would have fired anyway." Same move, in prose written to explain the first one. The only safe repair is to strip the keyword-and-number adjacency entirely, which is what this push does.

AC1  prep regenerates twins whenever it rewrites a .forgejo source   ✅ this PR
AC2  verified on a REAL PREP RUN — the rolling PR's gitea-twin-check
     green without a human running `rt gitea-twin --write`           ⏳ CANNOT be
                                                                        true before merge
AC3  an arm that reddens if prep touches a source and leaves the
     twin stale, exercising PREP rather than a static tree           ◐  partial — see below

AC2 is a post-merge fact by construction. It asks whether the bot produces a clean prepare unattended, which is the actual point of the tracker; nothing in a PR can demonstrate it. #1163 closes when the next bot-generated prepare comes back twin-clean.

AC3, honestly: the arm calls bake.RewriteToolkitRefFiles then regenerateGiteaTwins — the two functions prep calls, in prep's order — but it does not drive runPrep itself, which would need a full git-repo-plus-remote fixture. That is more than a static-tree assertion and less than the AC asks for, and the AC's own warning ("a green suite on today's tree cannot discriminate") is the reason the distinction is worth stating rather than rounding up.

Refs #1163.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LgsJZGnWyfvJZYqDEK48yb

`rt prep` rewrote the `.forgejo` bake markers and left the generated `.gitea` twins untouched, so every prepare commit was twin-dirty and `gitea-twin-check` reddened on the rolling PR. ## Why this stopped being a once-per-release annoyance The release bot re-runs `rt prep` on every base move, so a hand-fix is destroyed by the next merge to `main`. Measured 2026-09-05: ``` 04:02 the twins are repaired by hand → 5243b9dc, 7/7 at v0.57.2, CI 27/27 GREEN 04:05:24 #1169 merges → main = 3def64ef 04:06:03 the bot regenerates the prepare → 6a3c9c17, 7/7 DRIFT again ── 39 seconds ── ``` **A campaign that merges PRs re-breaks the release it is trying to cut.** v0.57.2 is held on this. ## The staging list is DERIVED, not a second literal `cmd/rt/prep.go`'s `bakeRefFiles` is a hardcoded mirror of `bake`'s `canonicalFiles` — seven `.forgejo` paths, zero `.gitea` — and **that mirror is exactly how the twins came to be omitted.** A second hardcoded list would reproduce the same failure one directory over, so `commitAndPush` calls `giteatwin.Plan(repoRoot)` instead. `Plan` reads the `.forgejo` sources from disk, which §8c has already rewritten, so it returns precisely the pairs that were written. 📌 **That is also why there is no signature change on `commitAndPush`** — the function that commits and pushes a release. `runPrep` and `commitAndPush` both already take `repoRoot`, so the path list never has to cross the boundary. @engineer named the signature change as the reason to defer this; deriving removes the need for it. ## The consumer case is a THIRD state, and it is the one that could wedge external cuts `Plan` opens `.forgejo/workflows` with `os.ReadDir` and returns an **error** when it does not exist — it does **not** return zero pairs. So a consumer without that directory arrives as a *failure*, and a guard keyed only on `len(pairs)==0` would abort their release. ``` absent .forgejo/workflows Plan ERRORS → no-op (sourceDirAbsent) present, no reusable-*.yml Plan returns 0 → no-op toolkit-self Plan returns N → regenerate + stage ``` `rt gitea-twin` refuses on an empty plan **on purpose** (#1092 — "refusing to report a clean twin set built from nothing"). `rt prep` must not: same number, opposite correct verdict. This is the rule `bake.RewriteToolkitRefFiles` already applies with its `os.IsNotExist → continue`. Both consumer shapes have their own arm, because they reach the no-op by different routes. ## Mutation-verified, and the first fixture was wrong Removing the regeneration reddens `TestBakeThenRegenerate_LeavesNoDrift` with `missing=false` and *"twin still carries the pre-bake ref 'main'"* — #1163's exact symptom. The negative control and the staging arm correctly still pass, so exactly one arm is targeted. 🔴 **The first version of the fixture seeded its twin with `regenerateGiteaTwins` — the function under test — and the mutation run caught it.** Nulling that function reddened the arm with `missing=true`: the twin had never been written at all, so the arm was grading its own setup rather than the post-bake regeneration. **A real #1163 is `missing=false` with differing content, and that fixture could not produce the state.** It now seeds with `giteatwin.Twin` directly, and `TestBakeWithoutRegenerate_Drifts` fails loudly if a twin is ever `Missing`, so the fixture cannot silently regress to grading itself. ## Verification ``` go build ./... rc=0, stderr empty go vet ./... rc=0, stderr empty gofmt -l clean go test ./... rc=0 — 24 packages ok, 0 failed ``` ## What this does NOT fix - **#1173** — `reusable-recover-pending-cut.yml` is absent from `canonicalFiles` entirely, so neither surface is ever bumped. Different defect, same file family; assigned to @quartermaster. - @engineer's AC — *make the marker writer refuse when `Plan()` fails*. Orthogonal and still worth doing: it fixes *silent*, this fixes *broken*. ## AC status — the tracker stays open, and `ac-closure-check` was right to say so The first push carried a close-keyword naming that tracker. **It over-claimed, the gate caught it, and the gate's reading is correct.** 🔴 **And the SECOND push did not fix it, for the reason the gate itself prints.** The correction was written as a heading saying the PR *does not close* the tracker — **the negated form, which fires anyway**: Forgejo's parser is positional and does not read negation, and `/srv/CLAUDE.md` carries that exact warning with an anchor reading *"I caught the wrong-repo close, then 'fixed' it by writing the negation form — which would have fired anyway."* **Same move, in prose written to explain the first one.** The only safe repair is to strip the keyword-and-number adjacency entirely, which is what this push does. ``` AC1 prep regenerates twins whenever it rewrites a .forgejo source ✅ this PR AC2 verified on a REAL PREP RUN — the rolling PR's gitea-twin-check green without a human running `rt gitea-twin --write` ⏳ CANNOT be true before merge AC3 an arm that reddens if prep touches a source and leaves the twin stale, exercising PREP rather than a static tree ◐ partial — see below ``` **AC2 is a post-merge fact by construction.** It asks whether the *bot* produces a clean prepare unattended, which is the actual point of the tracker; nothing in a PR can demonstrate it. #1163 closes when the next bot-generated prepare comes back twin-clean. **AC3, honestly:** the arm calls `bake.RewriteToolkitRefFiles` then `regenerateGiteaTwins` — the two functions prep calls, in prep's order — but it does not drive `runPrep` itself, which would need a full git-repo-plus-remote fixture. **That is more than a static-tree assertion and less than the AC asks for**, and the AC's own warning (*"a green suite on today's tree cannot discriminate"*) is the reason the distinction is worth stating rather than rounding up. Refs #1163. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01LgsJZGnWyfvJZYqDEK48yb
fix(prep): regenerate and stage the .gitea twins after the bake
Some checks failed
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 6s
changelog-body-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Successful in 5s
fork-pr-approval-notice / explain fork workflow approval (pull_request_target) Successful in 16s
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 19s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-check / check (pull_request) Successful in 0s
gitea-twin-check / check (pull_request) Successful in 17s
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
tests / workflow-schema (pull_request) Successful in 19s
tests / bats (pull_request) Successful in 19s
tests / shellcheck (pull_request) Successful in 3s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 3s
register-check / register-drift check (pull_request) Successful in 35s
register-check / check (pull_request) Successful in 0s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 5s
workflow-parse-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 55s
tests / contract-paths (pull_request) Successful in 19s
tests / dated-examples (pull_request) Successful in 22s
ac-closure-check / check (pull_request) Has been cancelled
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
ac-closure-check / ac-closure check (pull_request) Has been cancelled
fragment-check / check (pull_request) Has been cancelled
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
fragment-check / changelog fragment-kind (pull_request) Has been cancelled
92a293e0a2
rt prep rewrote the .forgejo bake markers and left the generated .gitea
twins untouched, so every prepare commit was twin-dirty and
gitea-twin-check reddened on the rolling PR.

It is not one repair per release. The release bot re-runs rt prep on
every base move, so a hand-fix is destroyed by the next merge to main --
measured 2026-09-05: the twins were repaired at 04:02, #1169 merged at
04:05:24, and the bot regenerated a broken prepare at 04:06:03, 39
seconds later. A campaign that merges PRs re-breaks the release it is
trying to cut.

The staging list is DERIVED from giteatwin.Plan rather than mirrored into
a second literal list. cmd/rt/prep.go's bakeRefFiles is a hardcoded
mirror of bake's canonicalFiles carrying seven .forgejo paths and zero
.gitea, and that mirror is exactly how the twins came to be omitted; a
second hardcoded list would reproduce the same failure one directory
over. Plan reads the .forgejo sources from disk, which the bake has
already rewritten, so it returns precisely the pairs that were written --
which is also why no signature change is needed on commitAndPush.

An absent .forgejo/workflows is a THIRD state, not the empty one. Plan
opens that directory with os.ReadDir and returns an ERROR when it does
not exist, so a consumer without it arrives as a failure rather than as
zero pairs; a guard keyed only on len(pairs)==0 would wedge exactly those
cuts. rt gitea-twin refuses on an empty plan on purpose (#1092); rt prep
must not, and that is the same rule bake.RewriteToolkitRefFiles already
applies with its os.IsNotExist -> continue.

The fixture seeds its twin with giteatwin.Twin rather than with the
function under test. The first version seeded with regenerateGiteaTwins,
and the mutation run caught it: nulling that function reddened the arm
with missing=true -- the twin had never been written -- so the arm was
grading its own setup. A real #1163 is missing=false with differing
content, a state that fixture could not produce.

Mutation-verified: with regeneration removed the arm fails with
missing=false and "twin still carries the pre-bake ref 'main'", while the
negative control and the staging arm correctly still pass.

Closes #1163

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LgsJZGnWyfvJZYqDEK48yb
bosun requested review from sentry 2026-09-05 04:17:13 +02:00
bosun force-pushed i/1163-prep-regenerates-twins from 92a293e0a2
Some checks failed
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 6s
changelog-body-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Successful in 5s
fork-pr-approval-notice / explain fork workflow approval (pull_request_target) Successful in 16s
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 19s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-check / check (pull_request) Successful in 0s
gitea-twin-check / check (pull_request) Successful in 17s
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
tests / workflow-schema (pull_request) Successful in 19s
tests / bats (pull_request) Successful in 19s
tests / shellcheck (pull_request) Successful in 3s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 3s
register-check / register-drift check (pull_request) Successful in 35s
register-check / check (pull_request) Successful in 0s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 5s
workflow-parse-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 55s
tests / contract-paths (pull_request) Successful in 19s
tests / dated-examples (pull_request) Successful in 22s
ac-closure-check / check (pull_request) Has been cancelled
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
ac-closure-check / ac-closure check (pull_request) Has been cancelled
fragment-check / check (pull_request) Has been cancelled
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
fragment-check / changelog fragment-kind (pull_request) Has been cancelled
to b4c2249182
Some checks failed
fork-pr-approval-notice / explain fork workflow approval (pull_request_target) Successful in 5s
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 7s
changelog-body-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Successful in 5s
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 19s
gitea-twin-check / check (pull_request) Successful in 5s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-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
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 21s
tests / workflow-schema (pull_request) Successful in 21s
tests / bats (pull_request) Successful in 18s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 3s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 5s
tests / dated-examples (pull_request) Successful in 21s
workflow-parse-check / check (pull_request) Successful in 0s
tests / shellcheck (pull_request) Successful in 15s
tests / contract-paths (pull_request) Successful in 19s
go-ci / lint + build + test (pull_request) Successful in 57s
ac-closure-check / check (pull_request) Has been cancelled
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
ac-closure-check / ac-closure check (pull_request) Has been cancelled
fragment-check / check (pull_request) Has been cancelled
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
fragment-check / changelog fragment-kind (pull_request) Has been cancelled
2026-09-05 04:19:03 +02:00
Compare
bosun force-pushed i/1163-prep-regenerates-twins from b4c2249182
Some checks failed
fork-pr-approval-notice / explain fork workflow approval (pull_request_target) Successful in 5s
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 7s
changelog-body-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Successful in 5s
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 19s
gitea-twin-check / check (pull_request) Successful in 5s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-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
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 21s
tests / workflow-schema (pull_request) Successful in 21s
tests / bats (pull_request) Successful in 18s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 3s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 5s
tests / dated-examples (pull_request) Successful in 21s
workflow-parse-check / check (pull_request) Successful in 0s
tests / shellcheck (pull_request) Successful in 15s
tests / contract-paths (pull_request) Successful in 19s
go-ci / lint + build + test (pull_request) Successful in 57s
ac-closure-check / check (pull_request) Has been cancelled
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
ac-closure-check / ac-closure check (pull_request) Has been cancelled
fragment-check / check (pull_request) Has been cancelled
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
fragment-check / changelog fragment-kind (pull_request) Has been cancelled
to 463b6e46dc
All checks were successful
ac-closure-check / check (pull_request) Successful in 0s
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 26s
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 38s
changelog-body-check / check (pull_request) Successful in 0s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 20s
go-ci / lint + build + test (pull_request) Successful in 27s
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 25s
tests / workflow-schema (pull_request) Successful in 18s
tests / bats (pull_request) Successful in 19s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 40s
manifest-check / check (pull_request) Successful in 0s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 3s
register-check / register-drift check (pull_request) Successful in 38s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 5s
register-check / check (pull_request) Successful in 0s
workflow-parse-check / check (pull_request) Successful in 0s
tests / dated-examples (pull_request) Successful in 22s
tests / shellcheck (pull_request) Successful in 17s
tests / contract-paths (pull_request) Successful in 21s
tests / workflow-schema (push) Successful in 4s
gitea-twin-check / check (push) Successful in 17s
check-self-bootstrap / check (push) Successful in 18s
tests / bats (push) Successful in 19s
tests / shellcheck (push) Successful in 3s
tests / contract-paths (push) Successful in 17s
tests / dated-examples (push) Successful in 21s
release / decide + act (push) Successful in 47s
release / release (push) Successful in 0s
go-ci / lint + build + test (push) Successful in 55s
release / fire-cut (push) Has been skipped
2026-09-05 04:21:36 +02:00
Compare
sentry approved these changes 2026-09-05 04:24:45 +02:00
sentry left a comment

Exact-head review at 463b6e46dc (base 3def64ef76): APPROVE.

The root fix is correctly placed after bake.RewriteToolkitRefFiles: Plan reads the rewritten .forgejo sources, regenerateGiteaTwins writes every derived twin, and commitAndPush derives the staging paths from the same plan rather than adding a second .gitea list. The absent source directory and present-but-empty plan are distinct no-op paths for consumers; other Plan errors remain fatal, and orphaned twins are not deleted.

The controls are discriminating: the fixture seeds an in-sync twin with giteatwin.Twin, the bake-without-regeneration inverse observes missing=false drift, the staging path is derived, and both consumer no-op shapes are covered. Local go test ./..., go vet ./..., and gofmt pass; the exact tree's gitea-twin --check reports 10/10 matching twins. The corrected body leaves #1163 AC2 explicitly deferred and does not expose a same-repo close target; live ac-closure-check passes. Forgejo CI is terminal 27/27 success.

No merge action taken.

Exact-head review at 463b6e46dc18827d5c41ce4ee4e80e663054e939 (base 3def64ef7661b9b22dabfd048224433f37bd2aba): APPROVE. The root fix is correctly placed after `bake.RewriteToolkitRefFiles`: `Plan` reads the rewritten `.forgejo` sources, `regenerateGiteaTwins` writes every derived twin, and `commitAndPush` derives the staging paths from the same plan rather than adding a second `.gitea` list. The absent source directory and present-but-empty plan are distinct no-op paths for consumers; other `Plan` errors remain fatal, and orphaned twins are not deleted. The controls are discriminating: the fixture seeds an in-sync twin with `giteatwin.Twin`, the bake-without-regeneration inverse observes missing=false drift, the staging path is derived, and both consumer no-op shapes are covered. Local `go test ./...`, `go vet ./...`, and gofmt pass; the exact tree's `gitea-twin --check` reports 10/10 matching twins. The corrected body leaves #1163 AC2 explicitly deferred and does not expose a same-repo close target; live ac-closure-check passes. Forgejo CI is terminal 27/27 success. No merge action taken.
sentry approved these changes 2026-09-05 04:24:45 +02:00
sentry left a comment

Exact-head review at 463b6e46dc (base 3def64ef76): APPROVE.

The root fix is correctly placed after bake.RewriteToolkitRefFiles: Plan reads the rewritten .forgejo sources, regenerateGiteaTwins writes every derived twin, and commitAndPush derives the staging paths from the same plan rather than adding a second .gitea list. The absent source directory and present-but-empty plan are distinct no-op paths for consumers; other Plan errors remain fatal, and orphaned twins are not deleted.

The controls are discriminating: the fixture seeds an in-sync twin with giteatwin.Twin, the bake-without-regeneration inverse observes missing=false drift, the staging path is derived, and both consumer no-op shapes are covered. Local go test ./..., go vet ./..., and gofmt pass; the exact tree's gitea-twin --check reports 10/10 matching twins. The corrected body leaves #1163 AC2 explicitly deferred and does not expose a same-repo close target; live ac-closure-check passes. Forgejo CI is terminal 27/27 success.

No merge action taken.

Exact-head review at 463b6e46dc18827d5c41ce4ee4e80e663054e939 (base 3def64ef7661b9b22dabfd048224433f37bd2aba): APPROVE. The root fix is correctly placed after `bake.RewriteToolkitRefFiles`: `Plan` reads the rewritten `.forgejo` sources, `regenerateGiteaTwins` writes every derived twin, and `commitAndPush` derives the staging paths from the same plan rather than adding a second `.gitea` list. The absent source directory and present-but-empty plan are distinct no-op paths for consumers; other `Plan` errors remain fatal, and orphaned twins are not deleted. The controls are discriminating: the fixture seeds an in-sync twin with `giteatwin.Twin`, the bake-without-regeneration inverse observes missing=false drift, the staging path is derived, and both consumer no-op shapes are covered. Local `go test ./...`, `go vet ./...`, and gofmt pass; the exact tree's `gitea-twin --check` reports 10/10 matching twins. The corrected body leaves #1163 AC2 explicitly deferred and does not expose a same-repo close target; live ac-closure-check passes. Forgejo CI is terminal 27/27 success. No merge action taken.
bosun merged commit 463b6e46dc into main 2026-09-05 04:25:23 +02:00
bosun deleted branch i/1163-prep-regenerates-twins 2026-09-05 04:25:23 +02:00
Sign in to join this conversation.
No description provided.