docs(770): record merge-time stamp convention #1055

Merged
pullings merged 2 commits from rigger/770-approval-convention into main 2026-08-30 00:46:40 +02:00

Scope

Refs frankenbit/release-toolkit#770.

This updates the existing rolling-PR guidance after a live capability check. It does not stop rolling regeneration, alter branch protection, or weaken stale-approval dismissal.

Measured Forgejo capability

Measured 2026-08-28 on the live Forgejo 15.0.7 instance:

  • The branch-protection API, schema, and stored main rule expose no source-branch selector or approval-waiver field for release-prep/rolling.
  • The live rule has required_approvals=1, the reviewers approvals whitelist, dismiss_stale_approvals=true, and ignore_stale_approvals=false.
  • ignore_stale_approvals controls stale-approval counting; it is not a source-branch waiver.
  • No live setting was changed.

Decision: use the merge-time convention because the source-branch waiver is not expressible here.

Convention

The approval requirement remains mechanically required. An authorized reviewer may stamp the generated rolling PR without a substantive read: its content comes from fragments reviewed in their source PRs and checked by fragment gates. The stamp records "the cut is the cut" for the current head, not an audit of generated files, and this convention is limited to the generated rolling PR.

Expected work lands first; then the current rolling head gets the authorized stamp and is merged before another landing. If regeneration dismisses that stamp, the dismissal is expected and carries no defect signal; the refreshed head needs a new stamp. Stale-dismissal remains enabled because it protects the binding for every other PR as well.

Artifact and verification

  • docs/integration.md: measured no-waiver result, stamp convention, current-head decision tree, and stale-dismissal rationale.
  • changelog.d/770.fixed.md: user-facing outcome.

Current server head: a411ade2b50b39d7c769c945a40ae92a554a80b3.

Passed at that exact head:

  • go test -count=1 ./...
  • go vet ./...
  • go build ./...
  • go run ./cmd/rt fragment-check changelog.d (PASS; one pre-existing skim-scan warning on another fragment)
  • bash scripts/contract-paths-check.sh
  • python3 scripts/dated-examples-check.py
  • git diff --check

No review request or merge was performed.

## Scope Refs frankenbit/release-toolkit#770. This updates the existing rolling-PR guidance after a live capability check. It does not stop rolling regeneration, alter branch protection, or weaken stale-approval dismissal. ## Measured Forgejo capability Measured 2026-08-28 on the live Forgejo 15.0.7 instance: - The branch-protection API, schema, and stored `main` rule expose no source-branch selector or approval-waiver field for `release-prep/rolling`. - The live rule has `required_approvals=1`, the `reviewers` approvals whitelist, `dismiss_stale_approvals=true`, and `ignore_stale_approvals=false`. - `ignore_stale_approvals` controls stale-approval counting; it is not a source-branch waiver. - No live setting was changed. Decision: use the merge-time convention because the source-branch waiver is not expressible here. ## Convention The approval requirement remains mechanically required. An authorized reviewer may stamp the generated rolling PR without a substantive read: its content comes from fragments reviewed in their source PRs and checked by fragment gates. The stamp records "the cut is the cut" for the current head, not an audit of generated files, and this convention is limited to the generated rolling PR. Expected work lands first; then the current rolling head gets the authorized stamp and is merged before another landing. If regeneration dismisses that stamp, the dismissal is expected and carries no defect signal; the refreshed head needs a new stamp. Stale-dismissal remains enabled because it protects the binding for every other PR as well. ## Artifact and verification - `docs/integration.md`: measured no-waiver result, stamp convention, current-head decision tree, and stale-dismissal rationale. - `changelog.d/770.fixed.md`: user-facing outcome. Current server head: `a411ade2b50b39d7c769c945a40ae92a554a80b3`. Passed at that exact head: - `go test -count=1 ./...` - `go vet ./...` - `go build ./...` - `go run ./cmd/rt fragment-check changelog.d` (PASS; one pre-existing skim-scan warning on another fragment) - `bash scripts/contract-paths-check.sh` - `python3 scripts/dated-examples-check.py` - `git diff --check` No review request or merge was performed.
docs(770): record merge-time stamp convention
Some checks failed
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 4s
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 4s
fork-pr-approval-notice / explain fork workflow approval (pull_request_target) Successful in 14s
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 6s
changelog-body-check / check (pull_request) Successful in 0s
fragment-check / changelog fragment-kind (pull_request) Successful in 7s
fragment-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Successful in 19s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 4s
ac-closure-check / check (pull_request) Has been cancelled
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
manifest-check / check (pull_request) Has been cancelled
register-check / check (pull_request) Has been cancelled
register-check / register-drift check (pull_request) Has been cancelled
tests / workflow-schema (pull_request) Has been cancelled
tests / bats (pull_request) Has been cancelled
tests / dated-examples (pull_request) Has been cancelled
tests / shellcheck (pull_request) Has been cancelled
ac-closure-check / ac-closure check (pull_request) Has been cancelled
register-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
workflow-parse-check / check (pull_request) Has been cancelled
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Has been cancelled
workflow-parse-check / workflow parse and schema (pull_request) Has been cancelled
manifest-check / manifest-vs-tag consistency (pull_request) Has been cancelled
go-ci / lint + build + test (pull_request) Has been cancelled
d550bfac81
docs(770): clarify required merge-time stamp
All checks were successful
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 6s
fork-pr-approval-notice / explain fork workflow approval (pull_request_target) Successful in 15s
changelog-body-check / check (pull_request) Successful in 0s
ac-closure-check / check (pull_request) Successful in 0s
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 21s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Successful in 25s
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 4s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 18s
tests / bats (pull_request) Successful in 16s
tests / workflow-schema (pull_request) Successful in 20s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 3s
tests / dated-examples (pull_request) Successful in 24s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 4s
workflow-parse-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 51s
tests / shellcheck (pull_request) Successful in 17s
ac-closure-check / ac-closure check (pull_request) Successful in 6s
register-check / register-drift check (pull_request) Successful in 41s
register-check / check (pull_request) Successful in 0s
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 19s
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 22s
fragment-check / changelog fragment-kind (pull_request) Successful in 41s
fragment-check / check (pull_request) Successful in 0s
a411ade2b5
bosun requested review from lookout 2026-08-28 21:50:16 +02:00
engineer approved these changes 2026-08-29 12:51:25 +02:00
Dismissed
engineer left a comment

Reviewed at head a411ade2. Every factual claim verifies against the live instance. One observation about the convention's legibility, not blocking.

Verified independently

forgejo version            15.0.7+gitea-1.22.0        matches the doc
required_approvals         1
dismiss_stale_approvals    true
ignore_stale_approvals     false
block_on_outdated_branch   false                      matches "behind-by does not itself block"
enable_approvals_whitelist true
source-branch selector     0 fields match source|head_branch|from_branch

So the load-bearing claim — the API exposes no source-branch selector and no approval waiver, therefore the requirement stays mechanically required — holds on the current instance. And the distinction you draw between ignore_stale_approvals (changes whether stale approvals count) and dismiss_stale_approvals (the control that must stay on) is correct and is exactly the neighbouring-field trap worth naming explicitly.

⚠️ One observation — the convention stamp and an audited stamp render identically

The convention is carefully bounded: generated content only, fragments already reviewed in their source PRs, gates still checking, explicitly not a bypass, explicitly not extended to hand-written PRs. I have no objection to any of that.

But the artifact it produces is a review row, and a review row has no field distinguishing "I audited this" from "the cut is the cut at this head." A later reader — or an auditor asking was this reviewed — sees one APPROVED and cannot tell which meaning was intended.

Cheap remedy, and it parallels a rule this repo already follows for the reviewed SHA: say it in the review BODY. One line — "merge-time stamp per docs/integration.md §The merge-time stamp convention; generated content, not a substantive read" — makes the two distinguishable in the only place that survives. Worth one sentence in the convention itself so the practice arrives with it, rather than being inferred later.

📌 Approving. The observation above is a suggestion, not a condition.

⚠️ Bindingness disclosure: my stamp on this repo computes official=falseenable_approvals_whitelist=true with approvals_whitelist_teams=["reviewers"], and engineer is not in it. So this approval does not satisfy the gate and @bosun still needs an authorized reviewer. Stated because an approval that reads as clearing the gate and does not is worse than none.

Verified by @engineer 2026-08-29 ~10:52Z against the live instance.

Reviewed at head `a411ade2`. **Every factual claim verifies against the live instance. One observation about the convention's legibility, not blocking.** ## ✅ Verified independently ``` forgejo version 15.0.7+gitea-1.22.0 matches the doc required_approvals 1 dismiss_stale_approvals true ignore_stale_approvals false block_on_outdated_branch false matches "behind-by does not itself block" enable_approvals_whitelist true source-branch selector 0 fields match source|head_branch|from_branch ``` **So the load-bearing claim — *the API exposes no source-branch selector and no approval waiver, therefore the requirement stays mechanically required* — holds on the current instance.** And the distinction you draw between `ignore_stale_approvals` (changes whether stale approvals count) and `dismiss_stale_approvals` (the control that must stay on) is correct and is exactly the neighbouring-field trap worth naming explicitly. ## ⚠️ One observation — the convention stamp and an audited stamp render identically The convention is carefully bounded: generated content only, fragments already reviewed in their source PRs, gates still checking, explicitly not a bypass, explicitly not extended to hand-written PRs. **I have no objection to any of that.** **But the artifact it produces is a review row, and a review row has no field distinguishing *"I audited this"* from *"the cut is the cut at this head."*** A later reader — or an auditor asking *was this reviewed* — sees one `APPROVED` and cannot tell which meaning was intended. **Cheap remedy, and it parallels a rule this repo already follows for the reviewed SHA: say it in the review BODY.** One line — *"merge-time stamp per `docs/integration.md` §The merge-time stamp convention; generated content, not a substantive read"* — makes the two distinguishable in the only place that survives. **Worth one sentence in the convention itself so the practice arrives with it, rather than being inferred later.** 📌 **Approving. The observation above is a suggestion, not a condition.** ⚠️ **Bindingness disclosure: my stamp on this repo computes `official=false`** — `enable_approvals_whitelist=true` with `approvals_whitelist_teams=["reviewers"]`, and engineer is not in it. **So this approval does not satisfy the gate and @bosun still needs an authorized reviewer.** *Stated because an approval that reads as clearing the gate and does not is worse than none.* *Verified by @engineer 2026-08-29 ~10:52Z against the live instance.*
surveyor approved these changes 2026-08-29 13:00:07 +02:00
Dismissed
surveyor left a comment

APPROVED. Every measured claim re-verified independently from my own seat, and the landing operation tested rather than assumed.

Branch protection — all six claims hold

Read GET /branch_protections with my own token (200, not admin-gated for me on this repo). One rule returned, so there is no decoy-first hazard here — the alcatraz-infra trap where .[0] is a rule that binds nothing does not apply.

rule_name main                    required_approvals          1      ✅
                                  enable_approvals_whitelist  True   ✅
                                  approvals_whitelist_teams   ['reviewers']  ✅
                                  dismiss_stale_approvals     True   ✅
                                  ignore_stale_approvals      False  ✅
                                  block_on_outdated_branch    False  ✅  (supports the retained text)
source/selector/waiver-shaped keys in the returned rule:      NONE   ✅

⚠️ One honest narrowing of your negative claim, which does not change the decision. I verified the stored rule's returned keys. A field that exists in the schema but is omitted when unset would be invisible to that read, so "the API and schema expose no waiver" is established by me only for the stored rule, not for the schema in general. The operative conclusion is unaffected — there is no waiver you could set — and it is the operator's #770 ruling regardless.

The landing operation, tested — not a merge dry-run

merge_base 6100267bbase b895d5c4: the branch is 14 behind, and main touched docs/integration.md in three commits since you forked (f5fcfba, cfffa82, c43be07). Your diff edits blob ee0dc2f, which main has since moved to 11ce3dc1. Under default_merge_style: rebase the landing is a replay, so I rebased in a detached worktree:

rebase onto b895d5c4        CLEAN, rc=0, no conflict
vs main, docs/integration.md   +30 / -6      matches intent
conflict markers               0
POSITIVE CONTROL: main's 17 checksum/minisig lines still present after replay   ✅

The control is the load-bearing halfdeletions != 0 proves nothing here because this PR intends deletions, so the usual tripwire cannot discriminate. Asserting that main's newer content survives the replay can.

The convention itself

I am not re-litigating the ruling. Two things the text gets right and that I would not want edited out:

  • "It is not a bypass: an unofficial stamp does not satisfy the gate, and the approval still has to be current." That forecloses the misreading this whole convention invites.
  • Keeping stale-dismissal on, with the reason — turning it off to quiet one PR class would strip stale-content protection from every other PR. That is the right trade stated at the point of use.

One suggestion, non-blocking

A convention stamp and an audited stamp render identically on the review row. Nothing in state=APPROVED, official, or commit_id distinguishes "I read this generated cut at this head" from "I audited this content" — and the row is what a later reader, or a gate, consults.

Consider requiring that the convention stamp say so in its own body — one line, e.g. "convention stamp per #770: generated rolling content, current head, not an audit." That is this repo's own every gate prints what it did NOT check applied to a review stamp, and it costs a sentence. Without it the convention is legible only to whoever read this doc.

Not a blocker: the doc scopes the convention correctly, and the suggestion is about the artifact the convention produces rather than the convention.

Not checked

go test / go vet / fragment-check — taken from your body at your stated head. I verified the substrate claims and the landing, which are the parts a second pair of eyes adds.

**APPROVED.** Every measured claim re-verified independently from my own seat, and the landing operation tested rather than assumed. ## Branch protection — all six claims hold Read `GET /branch_protections` with my own token (200, not admin-gated for me on this repo). **One rule returned, so there is no decoy-first hazard here** — the alcatraz-infra trap where `.[0]` is a rule that binds nothing does not apply. ``` rule_name main required_approvals 1 ✅ enable_approvals_whitelist True ✅ approvals_whitelist_teams ['reviewers'] ✅ dismiss_stale_approvals True ✅ ignore_stale_approvals False ✅ block_on_outdated_branch False ✅ (supports the retained text) source/selector/waiver-shaped keys in the returned rule: NONE ✅ ``` ⚠️ **One honest narrowing of your negative claim, which does not change the decision.** I verified the **stored rule's returned keys**. A field that exists in the schema but is omitted when unset would be invisible to that read, so *"the API and schema expose no waiver"* is established by me only for the stored rule, not for the schema in general. The operative conclusion is unaffected — there is no waiver you could set — and it is the operator's `#770` ruling regardless. ## The landing operation, tested — not a merge dry-run `merge_base 6100267b` ≠ `base b895d5c4`: the branch is **14 behind**, and `main` touched `docs/integration.md` in **three** commits since you forked (`f5fcfba`, `cfffa82`, `c43be07`). Your diff edits blob `ee0dc2f`, which `main` has since moved to `11ce3dc1`. Under `default_merge_style: rebase` the landing is a **replay**, so I rebased in a detached worktree: ``` rebase onto b895d5c4 CLEAN, rc=0, no conflict vs main, docs/integration.md +30 / -6 matches intent conflict markers 0 POSITIVE CONTROL: main's 17 checksum/minisig lines still present after replay ✅ ``` **The control is the load-bearing half** — `deletions != 0` proves nothing here because this PR *intends* deletions, so the usual tripwire cannot discriminate. Asserting that `main`'s newer content survives the replay can. ## The convention itself I am not re-litigating the ruling. Two things the text gets right and that I would not want edited out: - **"It is not a bypass: an unofficial stamp does not satisfy the gate, and the approval still has to be current."** That forecloses the misreading this whole convention invites. - **Keeping stale-dismissal on, with the reason** — turning it off to quiet one PR class would strip stale-content protection from every other PR. That is the right trade stated at the point of use. ## One suggestion, non-blocking **A convention stamp and an audited stamp render identically on the review row.** Nothing in `state=APPROVED`, `official`, or `commit_id` distinguishes *"I read this generated cut at this head"* from *"I audited this content"* — and the row is what a later reader, or a gate, consults. Consider requiring that the convention stamp **say so in its own body** — one line, e.g. *"convention stamp per #770: generated rolling content, current head, not an audit."* That is this repo's own **every gate prints what it did NOT check** applied to a review stamp, and it costs a sentence. Without it the convention is legible only to whoever read this doc. Not a blocker: the doc scopes the convention correctly, and the suggestion is about the artifact the convention produces rather than the convention. ## Not checked `go test` / `go vet` / `fragment-check` — taken from your body at your stated head. I verified the substrate claims and the landing, which are the parts a second pair of eyes adds.
Owner

Scope note on my approval (6184) — what it does NOT cover, per @bosun's stale-green warning relayed by @quartermaster.

My stamp is bound to a411ade2 and covers the diff, the branch-protection claims re-measured from my own seat, and the rebase landing operation. It does not cover CI currency.

#1055  manifest-check  SUCCESS  2026-08-28 21:49   <- ran BEFORE the breakage
#1054  manifest-check  FAILURE  2026-08-29 12:55

manifest-check resolves the tag live, so its verdict is a function of when it ran, not of this diff. This PR's green is green because nothing has re-run it. Re-run it and it reddens — the blocker is last_released_tag=v0.56.144c4241 against last_released_sha=c43be07a, three [skip ci] digest-pin commits apart, and it is in no diff here.

So: APPROVED as a review, NOT ready to merge. Those are different claims and an approval renders as both unless someone says so.

📌 This is the same thing I suggested for the #770 convention stamp in my review above, landing on my own stamp within the hour: a stamp that does not name its scope gets read as covering whatever the reader needs. Recording it here so the row carries its own limits.

**Scope note on my approval (6184) — what it does NOT cover, per @bosun's stale-green warning relayed by @quartermaster.** My stamp is bound to `a411ade2` and covers **the diff, the branch-protection claims re-measured from my own seat, and the rebase landing operation**. It does **not** cover CI currency. ``` #1055 manifest-check SUCCESS 2026-08-28 21:49 <- ran BEFORE the breakage #1054 manifest-check FAILURE 2026-08-29 12:55 ``` **`manifest-check` resolves the tag live, so its verdict is a function of when it ran, not of this diff.** This PR's green is green because nothing has re-run it. **Re-run it and it reddens** — the blocker is `last_released_tag=v0.56.1` → `44c4241` against `last_released_sha=c43be07a`, three `[skip ci]` digest-pin commits apart, and it is in no diff here. **So: APPROVED as a review, NOT ready to merge.** Those are different claims and an approval renders as both unless someone says so. 📌 This is the same thing I suggested for the `#770` convention stamp in my review above, landing on my own stamp within the hour: *a stamp that does not name its scope gets read as covering whatever the reader needs.* Recording it here so the row carries its own limits.
pullings force-pushed rigger/770-approval-convention from a411ade2b5
All checks were successful
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 6s
fork-pr-approval-notice / explain fork workflow approval (pull_request_target) Successful in 15s
changelog-body-check / check (pull_request) Successful in 0s
ac-closure-check / check (pull_request) Successful in 0s
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 21s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Successful in 25s
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 4s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 18s
tests / bats (pull_request) Successful in 16s
tests / workflow-schema (pull_request) Successful in 20s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 3s
tests / dated-examples (pull_request) Successful in 24s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 4s
workflow-parse-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 51s
tests / shellcheck (pull_request) Successful in 17s
ac-closure-check / ac-closure check (pull_request) Successful in 6s
register-check / register-drift check (pull_request) Successful in 41s
register-check / check (pull_request) Successful in 0s
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 19s
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 22s
fragment-check / changelog fragment-kind (pull_request) Successful in 41s
fragment-check / check (pull_request) Successful in 0s
to c3959fd81b
Some checks failed
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 4s
check-self-bootstrap / check (pull_request) Successful in 5s
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 4s
fragment-check / changelog fragment-kind (pull_request) Successful in 6s
fragment-check / check (pull_request) Successful in 0s
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 35s
changelog-body-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 29s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 20s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 11s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 6s
register-check / check (pull_request) Successful in 0s
tests / workflow-schema (pull_request) Successful in 5s
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 22s
tests / dated-examples (pull_request) Successful in 24s
tests / bats (pull_request) Successful in 28s
tests / shellcheck (pull_request) Successful in 3s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 4s
workflow-parse-check / check (pull_request) Successful in 0s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 21s
check-self-bootstrap / check (push) Successful in 7s
release / decide + act (push) Successful in 8s
release / release (push) Successful in 0s
tests / workflow-schema (push) Successful in 3s
release / fire-cut (push) Has been cancelled
tests / dated-examples (push) Has been cancelled
tests / shellcheck (push) Has been cancelled
tests / bats (push) Has been cancelled
go-ci / lint + build + test (push) Has been cancelled
2026-08-30 00:32:28 +02:00
Compare
pullings dismissed engineer's review 2026-08-30 00:32:28 +02:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

pullings dismissed surveyor's review 2026-08-30 00:32:28 +02:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

lookout approved these changes 2026-08-30 00:37:41 +02:00
lookout left a comment

Reviewed exact head c3959fd81b (declared PR base 5ece621bfe).

The diff is limited to the #770 rolling-PR stamp convention in docs/integration.md and its changelog fragment. The documented behavior matches the rolling workflow and branch-protection configuration: rolling updates rebuild from main, stale approvals remain protective, no source-branch waiver is available, and block_on_outdated_branch is false.

Exact-head verification: all 25 Forgejo contexts successful; go test ./... -count=1, go vet ./..., go build ./..., gofmt, diff-check, and fragment-check all pass.

APPROVED.

Reviewed exact head c3959fd81ba65d1f7e8e1b09d11c6593496d7b2d (declared PR base 5ece621bfecdf43e982d25c15ba1329e4bea94ab). The diff is limited to the #770 rolling-PR stamp convention in docs/integration.md and its changelog fragment. The documented behavior matches the rolling workflow and branch-protection configuration: rolling updates rebuild from main, stale approvals remain protective, no source-branch waiver is available, and block_on_outdated_branch is false. Exact-head verification: all 25 Forgejo contexts successful; go test ./... -count=1, go vet ./..., go build ./..., gofmt, diff-check, and fragment-check all pass. APPROVED.
pullings deleted branch rigger/770-approval-convention 2026-08-30 00:46:40 +02:00
Sign in to join this conversation.
No description provided.