Skip to content

release-train: develop -> staging - #226

Merged
tracebloc-release-train[bot] merged 6 commits into
stagingfrom
release-train/to-staging
Aug 12, 2026
Merged

release-train: develop -> staging#226
tracebloc-release-train[bot] merged 6 commits into
stagingfrom
release-train/to-staging

Conversation

@LukasWodka

@LukasWodkaLukasWodka commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Automated promotion by the release train (RFC-0008 D14). Head is the train-managed release-train/to-staging branch (a mirror of develop), so it never collides with a human PR. Merged only when the fr-gate is green.


Note

Medium Risk
Touches the org-wide conformance guard that decides whether branch-protection exemptions are stale, so a logic bug could hide or invent fleet drift. Reporting and process-doc changes are lower risk.

Overview
Closes a fail-open in caller-drift's exempt-staleness probe: it previously checked only classic_present, so a branch protected solely by a ruleset still looked unprotected and the exemption stayed silently valid. The probe now treats classic or ruleset coverage as protected (backend#1681), with a matching selftest.

Adds a conformance matrix to the audit report (backend#1608 increment 3): every repo × family cell renders as OK, a finding count, or ? for unread, so a green run shows what was actually covered rather than only failures.

Also lands process hardening: a new .cursor/BUGBOT.md, a Sibling check item on the PR template, and a fix the class, not the instance rule in org-standards.md.

Reviewed by Cursor Bugbot for commit 183f3ce. Bugbot is set up for automated code reviews on this repo. Configure here.

LukasWodkaand others added 5 commits August 11, 2026 23:08
Four defects in one day shared a root cause: a fix that addressed the instance in
front of the author and left the rest of its class behind.
1. a guard wrapped around load(checkout) while discover(root) stayed bare
2. an epoch-completeness helper used at two sites while a third did it inline
with a raw non-distinct .count()
3. a core.hooksPath guard that canonicalised the DIRNAME of the path, not the
path, so core.hooksPath=.. escapes it
4. a pre-push hook that probed for make but not for the ruff/pytest toolchain
it then calls
The rule names both shapes deliberately. 1 and 2 are other CALL SITES -- findable
by grepping what you changed. 3 and 4 are single-site: another INPUT reaches the
same guard, and no grep of the symbol will show you that. A rule that only says to
check the code nearby catches half the class, which is how 3 and 4 shipped.
Same week, from the other direction: a fleet-wide verification script accumulated
five defects of exactly this kind, and every one surfaced by RUNNING it across all
16 repos rather than by reading the diff (tracebloc/release-train#48). Reviewing a
predicate is not the same as enumerating what reaches it.
Canon only. The sync (backend#1602) will report the fleet DRIFTED and can open the
CLAUDE.md PRs; per-repo copies are never edited by hand.
Refs backend#1646
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…oth (backend#1681) (#222)
`evaluate_protection`'s exempt-staleness check was `if probe.classic_present:`.
A branch protected SOLELY by a ruleset returns 404 from the classic endpoint, so
it read as unprotected and its exemption stayed silently valid -- the guard would
never notice that a role it believes is out of scope is in fact a real, protected
branch.
That is the two-systems defect the 20-line header of read_protection() exists to
prevent, sitting in the one place that decides whether an exemption is still
true. `probe.rulesets` is populated by the very same call; it was simply never
consulted. The finding now also names WHICH layer covers the branch, so the
reader is not sent to re-derive it.
The gap survived because the coverage stopped one path short: `_ruleset_only`
already existed in the selftest and was only ever pointed at the `required` path,
never at `exempt`. It is now used for both.
Verified:
* selftest 111 -> 117 pass, 0 fail
* MUTATION: restoring the old `classic_present`-only condition makes the new
case FAIL (findings=[]), so the test genuinely covers the hole rather than
passing either way
* LIVE against all 20 repos: "No drift. Every repo read, every entry matched."
-- no exemption was actually hiding behind this, so closing it costs nothing
today and catches the next one.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…well as drift (backend#1608) (#223)
Increment 3. The audit has always known every repo's state per family and only
ever emitted the FAILURES, so a green run said "No drift" and nothing about what
was actually covered. You could not tell a fleet that conforms from a fleet that
was barely checked -- which is the same question this epic keeps finding the
wrong answer to elsewhere (a caller that is present but advisory, a required
check that never reports).
Adds a per-repo x per-family table to the report: callers, copies, protection,
rulesets, for all 20 repos, with the train flag alongside.
Cells are deliberately three-valued:
OK evaluated and matched
N that many findings
? that family could not be READ
`?` is the point. "Zero findings because we checked" and "zero findings because
we never looked" must not render the same, and the whole guard exists to refuse
that conflation -- so the screen refuses it too.
Counted by DELTA around each family's block rather than by parsing the finding
strings. Those strings are prose written for humans; keying a table off them
would break the first time one is reworded.
Verified:
* LIVE, all 20 repos: renders 20 x 4, every cell OK, exit 0
* MUTATION: with an impossible required-check in the develop baseline, the
protection column shows **1** for exactly the 16 train repos and OK for the
4 non-train ones whose develop role is exempt, exit 1. The screen shows red,
and shows the SHAPE of the failure -- one family, one cohort.
* selftest 116 -> 122, including that a clean row and an unread row do not
render identically, and that an unreadable FAMILY marks only its own column
* ruff --isolated --select E4,E7,E9,F -> All checks passed!
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…mplate check (backend#1680) (#224)
Four instances on 2026-08-11, in TWO shapes -- and a rule aimed only at
"neighbouring bugs" catches half of them:
other CALL SITES
* discover() left bare beside a wrapped load()
* an epoch helper used at 2 sites while a 3rd did it inline
other INPUTS TO THE SAME GUARD
* the hooksPath guard canonicalised dirname, not the path, so `..` escaped it
* the pre-push hook probed `make` but not the venv toolchain it calls
The canon line names both shapes. The PR-template line is the part that does the
work: it produces an artifact a reviewer can see is MISSING, where a prose rule
produces nothing to look for.
Why mechanical rather than remembered: the stuck-run detector built FROM today's
lessons reproduced the same mistake -- it encoded the symptom (runner=NONE)
instead of the condition (nothing progressing), and would have cancelled a
healthy production deploy. The pattern survives being named, which is the whole
argument for a checklist item over a paragraph.
Cost, stated rather than discovered: editing the canon drifts all 19 repos and
needs a sync fan-out. That is the third such edit this week and is exactly the
treadmill worth deciding about (auto-merge on green, or batching) -- tracked on
backend#1680.
Verified: standards-sync selftest 27 checks / 0 failed; the report still splices
the block cleanly against all 19 targets.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…s passed (backend#1680) (#225)
.github had no `.cursor/BUGBOT.md` — one of five repos without one — despite being
public and holding the reusables ~120 callers consume at @main, plus the conformance
contract itself.
Written from this repo's actual defect history rather than generic advice. Nearly
every real finding here is one shape: a guard that reports success it did not verify.
The guide names the variants seen in this repo (empty response read as 'nothing
found', `|| echo 0`, a grep in a pipefail pipeline returning 141, a required check
that is path-filtered so it can never report, a soft-fail default on a required
check), plus the two-protection-systems trap and the @main caller/callee ordering rule
that turns a mistimed input into startup_failure.
Also records the non-issues that were being re-raised: retired pii-gate contexts,
the deliberate `strict: false`, and the long incident comments that are load-bearing
rather than verbose.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
ContributorAuthor

bugbot run

Comment threadorg-standards.md Outdated
@tracebloc-release-traintracebloc-release-trainBot added gate-nudge Toggled by the release train to (re-)fire the fr-gate and removed gate-nudge Toggled by the release train to (re-)fire the fr-gate labels Aug 12, 2026
#220 and #224 both landed the same rule one minute apart, so org-standards.md
carried two near-identical 'Fix the class, not the instance' bullets. Because
this file is the synced canon, the duplicate would propagate into every repo's
CLAUDE.md (Bugbot, on the develop->staging mirror #226, which it blocked).
Keeps the line-25 wording: the neighbouring bullets all use unbolded lead-ins,
and the removed one was the only bullet in the file starting with bold. It also
sat between the post-PR and recurring-finding bullets, splitting that flow.
Verified: one occurrence of the rule remains, zero bullets start with bold.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
ContributorAuthor

bugbot run

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 183f3ce. Configure here.

@tracebloc-release-traintracebloc-release-trainBot added gate-nudge Toggled by the release train to (re-)fire the fr-gate and removed gate-nudge Toggled by the release train to (re-)fire the fr-gate labels Aug 12, 2026
@tracebloc-release-train
tracebloc-release-trainBot merged commit 38e8897 into stagingAug 12, 2026
24 of 31 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@LukasWodka