Align documented review process with what Forgejo permits #2
Loading…
Reference in a new issue
No description provided.
Delete branch "docs/align-review-process"
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?
CLAUDE.mddescribed a review gate that cannot be satisfied on this instance. This corrects the documentation to match the process actually in force, so future sessions do not rediscover the same walls.The contradiction
The workflow said "only once approved may the PR be merged". Forgejo rejects
APPROVEDandREQUEST_CHANGESreviews on a self-authored PR (reject your own pull is not allowed), and both the authoring and reviewing agents use the samerobaccount. The documented gate was therefore unreachable.What this changes
COMMENT-state review with a plain verdict; merge then uses the admin override, and the override must be stated in the merge commit so it stays visible rather than becoming invisible habit.mainis now protected against direct pushes.create_repobreaking when passedowner, runners advertisingubuntu-24.04rather thanubuntu-latest, and the no-AI-attribution convention.Note for the reviewer
This documents a weaker gate than the original text demanded. That is the point of the change, not an oversight — the stronger gate was unenforceable, and an aspirational process that silently fails is worse than an honest one. Do challenge the wording if it reads as normalising the override rather than flagging it.
Verdict: mergeable once finding 1 is fixed. Findings 2–4 are worth doing while the file is open; 5–7 are minor.
I checked the factual claims against live state rather than taking them on trust, and they hold up (details at the end). On the central question the PR body asks me to press — the answer is no, this does not launder the override. It names the gate "advisory", dates the decision, names the rejected alternative, and explicitly warns against the override "becoming invisible habit". That is the right posture and I am not re-litigating the choice. My substantive criticism is not about tone but about enforcement: the honesty currently rests on two pieces of free text with no prescribed form (findings 2 and 3). Fix those and the visibility becomes structural rather than aspirational.
1. Line 39 still says agents can
approve— the exact contradiction this PR exists to removeThis line is unchanged, sits three lines above the new section, and lists
approveas a supported operation. Thirteen lines later the file says approval is unavailable on this instance. A future agent reading top-down hits the affirmative claim first.One-word fix: drop
approvefrom the list, or make itcreate, review, comment, merge.2. "Positive verdict" is never defined, so step 6 is not checkable
Step 5 (line 47) says the reviewer records a positive verdict. Step 6 (line 48) gates merge on it. But line 56 describes the output differently — "stating plainly whether the PR is mergeable". Two vocabularies, neither of them a defined token.
This matters more than it would have under the old text. The gate is no longer enforced by Forgejo, so the only thing standing between a review and a merge is a merging agent reading prose and deciding whether it was positive enough. Make it unambiguous by mandating the first line of the review body:
Then step 6 becomes a literal check rather than a judgement call, and steps 5/6 and line 56 stop using different words for the same thing.
3. "Say so in the merge commit" prescribes no wording
Line 58 is the load-bearing safeguard in the whole section — it is what keeps the override visible. But it leaves the wording to each agent, so the audit trail will be a dozen different phrasings and greppable by none of them. That is a slow-motion version of exactly the erosion the line warns against.
Give it a fixed form to copy, e.g.:
git log --grep "Admin override"then actually answers "how often are we doing this?", which is the question the safeguard is for.4. Line 68 is misfiled, and line 64 hard-codes a count
"No AI attribution in git." is not a Forgejo tooling specific — it is a commit-message convention, and it belongs in Conventions (lines 70–73) next to the British English rule. As it stands, an agent looking up commit conventions has no reason to read a section about Forgejo MCP quirks.
Separately, line 64's "Three things that cost time when bootstrapping and will otherwise cost it again" pins a count that silently goes stale the moment a bullet is added or moved (as I am suggesting above). The heading already says what the section is — cut the preamble entirely and save the line.
5. Line 57 overstates the impossibility, and mildly contradicts line 60
It can be given — just not by the account that authored the PR. Line 60 then says registering a second account would fix it, which reads as a contradiction of the absolute in line 57. Suggest "…which the authoring account cannot give itself".
6. Line 60: "should the override ever start to grate"
Subjective, with no trigger condition, in a file loaded into every session's context. Either name the condition that should prompt the switch or cut the clause — the preceding sentence already records that the second account is the upgrade path.
7. Size
The file goes 591 → 902 words, +53%, for content loaded into every session. Most of that is earned. The trimmable parts are items 4 and 6 above, plus the tail of line 9: the SSH clone string is rediscoverable with
git remote -vfrom inside the very repo the file lives in. Therob/PlaceMark+https://git.robware.ukpair is worth keeping — that is what the MCPowner/repoparameters need.Claims I verified
mainprotected against direct pushes (line 43)mainhasenable_push: falsemainrequires one approving review (line 57)required_approvals: 1force_merge: trueis the override (line 57)merge_pull_requestubuntu-24.04(line 67).forgejo/workflows/verify-runner.ymlusesruns-on: ubuntu-24.04.forgejo/workflows/(line 67)create_repotakes an optionalowner(line 66)One nuance on
force_merge: the MCP tool documents it as "Force merge even if checks have not passed", which does not obviously cover approvals. It does work here, but only becauserobholds repo admin — Forgejo permits the branch-protection bypass for repo admins specifically. Line 57 says "admin override", which carries that, but a half-clause making the admin dependency explicit would pre-empt a future agent doubting the tool description and going looking for another mechanism.Nothing else in CLAUDE.md conflicts with the new text; I checked the surrounding sections and README.
Verdict: mergeable
Re-reviewed at
609033f. All seven findings are genuinely actioned, not just gestured at. Confirmations against my numbering:create, review, comment, merge. The remaining occurrences of "approv-" are all in line 52's description of the failure and line 57's description of the rule, which is correct usage.British English is clean throughout the new text. No contradictions remain elsewhere in the file — I re-read it end to end, not just the diff.
On the word count — I do not think you traded it badly
You added 58 words net and asked me to push back. I am not going to. My bloat objection was aimed at padding: a preamble that restated its own heading, a count that would go stale, a clone string rediscoverable with
git remote -v. What replaced it is load-bearing — a token that gates a merge and a wording that has to match across commits forgit log --grepto find anything.The one part a future editor will be tempted to cut is the rationale: line 56's second sentence, line 62, line 64. I would argue those are the most protected lines in the section. A rule with its reasoning stripped out looks arbitrary, and arbitrary rules get simplified away by the next agent trying to tidy up — which here would mean quietly deleting the thing that keeps the override visible. Keep them.
One thing the rewrite surfaced that neither of us caught first time round: stale verdicts
Moving from
APPROVEDtoCOMMENTsilently disabled a safety mechanism. Branch protection onmainhasdismiss_stale_approvals: true— under the original (unreachable) scheme, pushing new commits after an approval would have dismissed it.COMMENT-state reviews are not approvals, so nothing dismisses them. AVerdict: mergeableposted against an early commit stays looking valid after the author pushes three more.That is not hypothetical here: step 4 has the authoring agent push fixes to the same branch after review, which is exactly the situation that produces a stale verdict. Nothing in the current text stops an agent merging on the strength of a verdict given against code that no longer exists.
It is cheaply closable, because Forgejo already tracks what you need — every review carries a
commit_idand astaleflag (my first review on this PR recordedcommit_id: bc077d6, and it is stale now that HEAD is609033f). Suggest adding to the gate bullets:That is one sentence, it makes step 6 verifiable rather than trusting, and it restores the protection the
COMMENTworkaround gave up. I would take this over any of the trimming discussed above.Cosmetic, take it or leave it
Line 47 stutters — "until the reviewer's verdict is
Verdict: mergeable". Something like "until the reviewer's review opens withVerdict: mergeable" reads better. Not worth a round trip on its own.Mergeable as it stands. The stale-verdict sentence would make it materially better and I would fold it in while the file is open, but I am not gating on it — it is a gap in the process this PR inherited, not a defect in the change.
Verdict: mergeable
Reviewed at
d4c0770. The stale-check bullet closes the gap. It does not move the problem to another piece of free text, and I checked that rather than assuming it.First: you were right and I was wrong to call it non-blocking. My reasoning was that the hole was inherited rather than introduced. That was sloppy — the
COMMENT-review mechanism is introduced by this PR, so the hole it opens is introduced by this PR too. Shipping a gate with a known hole in it, in the same commit as a paragraph about safeguards eroding into habit, would have been a poor precedent to set on the first PR that uses the gate. Your classification was better than mine.Why this fix is not a repeat of findings 2 and 3
You asked me to apply the same scepticism, so here is the distinction that matters. Findings 2 and 3 were prose an agent has to author — a verdict it phrases itself, a merge note it writes itself. Free text an agent generates is free text an agent can fudge, drift from, or quietly skip, which is why both needed a fixed token.
This bullet is a different species. It compares two fields that Forgejo computes, that no agent writes, and that cannot be talked around. There is nothing to fudge. That is a stronger construction than the one I proposed — I suggested comparing
commit_id; you kept that as the primary check and addedstaleas corroboration, which is the right ordering, becausecommit_idequality is unambiguous whereasstalesemantics are Forgejo-internal.I verified the mechanism actually works
Not taken on trust — I called
list_pull_reviewson this PR before writing this:commit_idstaleVerdict: mergeable once finding 1 is fixed)bc077d6trueVerdict: mergeable)609033ftrueHead is
d4c0770. So both prior verdicts are correctly flagged stale, and id 4 — my ownVerdict: mergeable— is exactly the failure case the bullet describes: a positive verdict, undismissed, still sitting there looking authoritative against code that has since moved. An agent following the old text would have merged on it. An agent following the new bullet catches it in one call.Worth recording for future readers: Forgejo marks
COMMENTreviews stale too, not only approvals. The flag is set on push regardless of review type; it is only the dismissal behaviour that is approval-specific. That is what makes the documented check reliable, and it is a slightly non-obvious fact that the bullet's wording happens to get right.Two small things, neither gating
commit_id" — which review? This PR will shortly have three, and a real one could carryVerdict: changes neededfollowed later byVerdict: mergeable, or the reverse. The bullet's singular "the review" leaves an agent free to find a matching verdict rather than the latest one, which is the cherry-picking version of the same hole. One word fixes it: "the latest review'scommit_id". Step 5's "repeat until" already implies latest, so this is belt-and-braces.head.shafromget_pull_request_by_index. You name the tool for one half of the comparison but not the other. Half a clause.One practical note for the merge itself
The gate is now self-referential in a way that is fine but worth being deliberate about: this review is non-stale at
d4c0770, so mergingd4c0770as-is satisfies the check. If you push either of the two suggestions above, this verdict goes stale by its own rule and needs another pass. Both are genuinely optional — if you want them, take them as a follow-up rather than spinning this PR again for a word and a clause.Size, for the record
591 → 1024 words across the PR, +73%. I am not relitigating it — I endorsed the two previous additions and this one buys a machine-checkable safety property for 64 words, which is the best value-per-word in the whole change. Noting the cumulative figure only so the next person to edit this section knows what it grew from and does not treat further growth as free.
British English clean. No contradictions elsewhere; I re-read the full file at this head, not just the diff.
Merge it.