Uh oh!
There was an error while loading. Please reload this page.
release-train: develop -> staging - #166
Merged
Merged
Conversation
…ks got impossible advice (backend#1409) (#154) * fix(pii-gate): the override could not rescue an unset secret, and forks got impossible advice (backend#1409) Two defects, plus the first test this gate has ever had. 1 · THE DOCUMENTED ESCAPE HATCH DID NOT WORK The `pii-gate-override` label was checked AFTER the unset-secret refusal, so on a PR where PII_DENYLIST is missing the refusal exited first and the label could not rescue anything. Both this file's own header ("Override a false positive: add the 'pii-gate-override' label") and backend#1409's remediation note ("or apply the pii-gate-override label to an individual PR") advertise it as the per-PR way out of exactly that state. That state is not hypothetical: the secret still does not exist, and today's `.github` promotion (8aabe41, 13:53) armed the fail-closed path, so all seven public repos now carry a red check that the documented workaround cannot clear. An override is a statement that this PR should not be evaluated, so it now precedes every reason the evaluation might refuse. 2 · A FORK PR WAS TOLD TO GO SET A SECRET THAT CANNOT HELP IT GitHub does not pass secrets to `pull_request` runs from a forked repository, so DENYLIST is empty on any fork PR regardless of what the org secret contains. The gate then took the unset-secret path, whose message asks an org admin to run `gh secret set` — advice that cannot work, because this is a property of the event and not of the configuration. Forks now get their own branch with a true reason and a real remedy: a maintainer reads the PR text and applies the override label to record it. Still fails closed. Compared against exactly "true", so an absent head.repo (deleted fork) falls through to the paths below, which refuse on an empty denylist and refuse again on a Compare read they cannot complete — an unknown fork status cannot buy a pass. This also unblocks #1409 defect 2. Making `pii-gate / pii-check` required would have made every fork PR unmergeable; with the fork path explicit, the check can be required for same-repo PRs and deliberately not for forks. Measured today: 0 fork PRs across all 7 public repos, so nothing is affected retroactively. 3 · A SELFTEST, IN THE SHAPE caller-drift ALREADY USES scripts/tests/pii-gate-selftest.sh extracts the gate's `run:` block and executes it against a stubbed `gh`. 15 cases: both new behaviours, the unset-secret and fork refusals, title/body/commit matching, and every fail-closed path (comma-only denylist, truncated commit list, unreadable Compare, missing base SHA, glob-shaped term), plus a regression case for defect 3 — an early match in a ~150KB haystack, which is the shape that used to be discarded via SIGPIPE. Every case asserts the exit status AND a distinguishing phrase, because a fork PR and an unconfigured org both exit 1 and the whole point of this change is that they must not say the same thing. A status-only test would pass while the gate gave impossible advice. Proof the suite bites rather than merely being green: run against the currently live main copy it fails exactly the 4 new cases and passes the other 11, so nothing pre-existing regressed. The test depends on the `run:` block staying free of `${{ }}` interpolation. That is asserted, not assumed — extraction fails loudly if a future edit inlines an expression, rather than silently covering less. Not fixed here, and still open on backend#1409: the secret itself does not exist (a content decision), and the check is required on 0 of 7 public repos. Scanning the diff rather than only PR metadata is backend#1559. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test(pii-gate): pad the regression haystack via commits, not a 150KB env var The defect-3 case exported a ~150KB PR_BODY. Linux caps a single exec argument or environment string at 128KB (MAX_ARG_STRLEN), so every exec after that export died with E2BIG -- grep, head, tr and even the trap rm. macOS has a larger limit, so it passed locally and failed on the runner: "/usr/bin/grep: Argument list too long". Also unrealistic. GitHub caps a PR body at 65,536 characters, so no real run could produce that env var. Padding now comes from 250 commit messages generated straight into the fixture file, which never travel through argv or the environment -- and that is the faithful shape anyway: backend#1409 describes the haystack as title + body + up to 250 commit messages, title first. The case now asserts the haystack size (80,390 bytes) exceeds the 64KB pipe buffer. Without that, the fixture could shrink and the case would stop reaching the defect while staying green -- a regression test that no longer reproduces its bug is the same class of false comfort #1409 is about. Proof it reaches the defect: reverting the matcher to the pre-#130 pipe form makes this case, and only this case, fail. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…ep-open sync (backend#1597) (#163) stale-backlog is column-blind: a quiet North Stars epic auto-closes after 6+8 weeks and routes to Cancelled. The sweep already exempts keep-open - this keeps that label synced from board state nightly. One-way by design; write failures fail the step. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ly does (backend#1597) (#164) project-number, org and target-priority were declared and never read; the step hard-codes the 'priority' label per D5. Measured all 16 callers on develop and prod branches: byte-identical, secrets: inherit only, no with: blocks - so outright removal breaks nothing. trigger-label stays (used in the job if:). Header comment now describes the actual behavior: trigger label in, binary 'priority' issue label out, no board field. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…4) (#162) release-train#34 merged 2026-08-06 and listed the repo, so release_train can now be true. It could not be set in the same PR as the caller flip (.github#153): caller-drift.py:562 verifies this field against release-train/repos.yml, so flipping it early fails the guard. RFC-BACKEND-1552 D2 is the decision; it amends RFC-BACKEND-1405 D1, which had named this repo in its exempt list. Verified: caller-drift exits 0, 20/20 repos, no drift. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
LukasWodka
commented
Aug 6, 2026
ContributorAuthor
bugbot run |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…d skips CLOSED issues (.github#166) (#167) * sec(ci): SHA-pin checkout+setup-python in the pii-gate selftest (backend#1491, D10) The new selftest workflow used floating @v4/@v5 while every other workflow here pins to a 40-char SHA; this repo runs no code-quality caller to catch the drift. * fix(reconcile): North Stars keep-open shield skips CLOSED issues (Bugbot .github#166) The shield filtered on status+type but not issue state, so closed North Stars issues got a sticky keep-open the classify step may then terminalize.
… has one (backend#1586) (#169) The WHY-THIS-FILE-EXISTS note closed with a present-tense claim - "there is no closure caller there to route it" - that the body of the same file now contradicts. e2e-test-agent's entry reads kanban-closure-router.yml: required # kanban-closure-routing.yml since the e2e-test-agent#13 remediation, and the caller is really there: tracebloc/e2e-test-agent@develop ships .github/workflows/kanban-closure-routing.yml resolving to tracebloc/.github/.github/workflows/kanban-closure-router.yml@main. Note the filename - `kanban-closure-routing.yml`, not `-caller.yml` - which is exactly the mismatch the MATCHING IS ON `uses:` CONTENT paragraph below warns about, and exactly why a reader checking the header's claim by filename would have concluded it was still true. This is a file whose entire purpose is being the single source of truth that caller-drift.yml enforces. A header that misstates the live state of a repo the body governs is the one defect it cannot afford, even in a comment: the guard checks the entries, nobody checks the prose, so the prose is where a stale claim survives longest. The fix keeps the motivating history and moves it into the past tense, because e2e-test-agent#1 really did close without routing and that is the evidence backend#1415 was built on. What changed is not the diagnosis, it is the repo: the motivating gap is closed, the detection gap the file exists to fix is not. Zero runtime impact - a comment. YAML parse re-verified (20 repos load). Found on the 2026-08-05 develop->staging hop (.github mirror #155, repo-inventory.yml:444), landed to staging under triage. Parent backend#1405. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…1603) (#171) * feat(ci): run the org's own code-quality suite on this repo (backend#1603) This repo publishes code-quality.yml -- and its action-pins job -- to all 19 other repos, and was the only repo that never ran it. The exemption was invisible because actionlint.yml looks like coverage: it type-checks every expression, validates needs/uses wiring, and shellchecks every run: block. What it does not do is look at action REFS. So the pinning rule this repo defines was the one rule this repo was not subject to. That is not theoretical. On 2026-08-06 .github#168 -- an otherwise correct fix -- reverted actions/checkout from its pinned commit SHA back to the mutable @v4 tag, in advance-deploy-env.yml, the most-consumed reusable workflow in the org and one that runs with PROJECTS_KANBAN_TOKEN in scope. action-pins exists to fail exactly that diff. It did not run. A human reading the diff caught it, which is the review path D10 was written to stop depending on. Armed from day one rather than soft-failed into a backlog, because the tree was measured first: shellcheck --severity=error clean over both shell scripts, house-rules.sh clean over the same, and 24 `uses:` refs across 23 workflows with zero pin violations. ruff and gitleaks could not be run locally and get their first honest look on this PR; whatever they surface is fixed or baselined here rather than the gate being softened -- the same bargain e2e-test-agent's caller records in its own comment. action-pins-soft-fail is set to false explicitly rather than left to inherit soft-fail. It is the check whose absence let #168 through, and every other repo consumes these workflows at @main and inherits whatever refs they pin, so this repo has a specific duty to enforce it on itself. actionlint.yml stays separate. The two gates have deliberately different postures -- actionlint blocks from day one against a tree cleaned in the same change; code-quality ships soft-fail: true for repos still clearing backlog -- and folding them together would force one posture onto both. No paths: filter, so the check can be made required without leaving workflow-free PRs waiting on a status that never reports. Refs backend#1603, backend#1491 (D10), backend#1276. * fix(ci): drop the action-pins inputs -- @main does not declare them yet First push of this branch produced a startup_failure on the reusable call (run 31086491251): every other check reported normally and `Code quality` never started. Cause: `action-pins` and `action-pins-soft-fail` were added in #159, which is on `develop`; `main` still carries the five-job version of code-quality.yml. Callers must reference @main (Q3), and passing an input the @main callee does not declare fails the entire call before any job runs. Same merge-order trap as the #160 audit red: a change becomes consumable by @main callers when it is PROMOTED, not when it is merged. The other five jobs still run armed, so most of backend#1603 closes now. The arming diff is written verbatim in the file so the follow-up is mechanical once #159 reaches main. Refs backend#1603.
… (backend#1600) (#168) * fix(kanban): advance the ISSUES each promoted PR closes, not just the PR (backend#1600) advance-deploy-env advanced only PRs; issues closed by a develop-merged PR were parked at On dev by the closure-router and never advanced when their code shipped, drifting permanently. For each PR in the push, resolve closingIssuesReferences (cross-repo aware) and advance each closing issue with the same monotonic guard, archived-skip and (new) dry-run behaviour. Adds a dry_run input; update_field short-circuits under it so both the PR and issue paths can be tested without writes. * fix(kanban): only advance CLOSED closing-issues (Bugbot .github#168 High) PRs merge to develop (not the default branch), so closingIssuesReferences lists still-OPEN issues; advancing those into deploy columns is wrong and reconcile bounces them to Backlog. Gate the advancement on issue.state == CLOSED. * sec(ci): restore the actions/checkout SHA pin (backend#1491 D10) This branch changed `actions/checkout@11d5960a…` to the mutable `@v4` tag in advance-deploy-env.yml — the most-consumed reusable workflow in the org, and one that runs with PROJECTS_KANBAN_TOKEN in scope. A floating major tag can be repointed by the upstream owner at any commit, which is exactly what D10 pinning removes. Nothing in CI would have caught it: tracebloc/.github runs only its own actionlint.yml, which does not inspect action refs, and it does not call the code-quality workflow whose action-pins job exists to fail this diff. That gap is now backend#1603 (.github#171, merged) — but action-pins itself cannot arm here until #159 reaches main, so for the moment this restore is the only thing standing between the unpin and every repo that consumes these workflows at @main. No functional change to the backend#1600 fix.
…oved to PR time (backend#1563 Layer 1) (#172) * feat(ci): version-bump gate — the train's prod-hop refusal, moved to PR time (backend#1563 L1) The release train already refuses to publish changed bytes under an already-released version (promote-repo.sh:version_preflight). Correct, and days late: backend#1561 spent a whole release leg discovering that py-package's pyproject.toml still said 0.17.0 while v0.17.0 was tagged and the delta touched tracebloc/*. This asks the same question on the PR that causes it. delta touches publish_paths AND v<version-on-this-PR> is already tagged -> red Not "the version file changed vs base", which #1563 words it as: that would demand a bump on every published-path PR, and one bump has always covered a whole release cycle. A check that is wrong on the common case gets removed. Parity is the point, so read_version and publishable_delta are copied from promote-repo.sh rule for rule — the per-extension anchors included, since those are what keep appVersion, a dependency pin and a leading comment out of the answer. Two deliberate divergences, both strictly tighter: `set -f` (a publish path is a glob, and promote-repo.sh only survives it by running where no publish path exists), and one paginated tag listing instead of a per-version git/ref probe that cannot tell 404 from 403. Fails closed on every unreadable input, and `soft-fail` does not reach any of them: it downgrades the verdict, never the machinery. Zero files scanned is a malfunction. No paths: filter and no job-level if:, so a required check can never go missing on a PR. 45-case decision table in scripts/tests/, run offline against a stubbed gh, covering every fail-closed path and all five repos' version file formats. Callers follow in one PR per repo, once this is on main. * sec(version-gate): a branch name is not a credential — tighten the promotion exemption Self-review before Bugbot. The release-train exemption keyed on the head ref alone, and a head ref is chosen by whoever opens the PR: `release-train/anything` was an exemption anybody could mint, from a fork included. It only skipped a version check the train re-runs at the prod hop, so nothing could actually publish through it — but "the gate is disarmed by naming your branch" is not a property to leave in a gate. Now all three must hold, and the extra two are facts about a real promotion rather than claims made by its author: head ref prefix, head in THIS repository (never a fork), base in staging/main/master. A promotion never targets develop, so a PR that borrows the name to reach develop is evaluated normally — with a warning naming the mismatch, because a bypass that does not apply should be visible rather than silently absent. Also: an EMPTY version-file read is retried on purpose (it is the exact symptom of the Contents API lag that left py-package untagged on 2026-07-29), so the message after three failed attempts now names both possibilities instead of saying only "could not read". 50 cases, 4 of them new and all four red before this change. * sec(version-gate): the fork test demands a confirmed false, not merely 'not true' head.repo is absent on a PR from a deleted fork, so IS_FORK arrives empty and 'not true' read that as 'same repo' — granting the promotion exemption on a field nobody could read. Exempting on an unread field is the shape of every fail-open in backend#1409. Three-way now: false exempts, true says fork, anything else says the head repository could not be confirmed. Evaluating a genuine promotion by mistake costs a re-run; exempting a fork by mistake costs the gate. * fix(version-bump-gate): head -1 the version parse; grep -oE prints per match Bugbot, .github#172. The yaml/toml/py branches take `head -1` on the LINE, then run `grep -oE "$semver"` on it -- and grep -oE prints one line per match, not per input line. A version line carrying a second semver in a trailing comment version = "1.2.3" # bumped from 1.0.0 therefore parses to the two-line value "1.2.3\n1.0.0". Measured, not theorised. Here that corrupts the regression guard: `sort -V | tail -1` answers 1.2.3 while `"$HEAD_VER"` is the whole two-line string, so the `!=` compare is true and the gate refuses a perfectly legitimate bump. The bare-file branch already guarded this with a trailing head -1; the other three did not. The json branch is safe -- jq emits a single value and the pattern is anchored with ^ -- so it is left alone rather than given a cosmetic head -1. This same defect is in promote-repo.sh:read_version, which this file copies rule for rule; it is fixed there in release-train#40. In the train the consequence is worse than a false refusal: the parsed value is interpolated into the tag-probe URL, a malformed URL 404s, and the caller reads that as "this version is not released" -- fail-OPEN on the one check that stops a re-publish under an existing tag.
…(backend#1602) (#170) * feat(standards): org-standards canon + CLAUDE.md sync guard (backend#1602) One canonical org-standards.md — the org's working rules — stamped into every active repo's CLAUDE.md between org-standards markers, so every Claude Code session in every repo loads the same rules. standards-sync.py audits the fleet develop-first (weekly report-only; a create-prs dispatch opens per-repo sync PRs against develop), with caller-drift's design rules: never all-clear from a failed read, absence never implicit (devex-bootstrap exempt with written reason), malformed markers reported and never auto-spliced. Offline selftest: 19 checks over the splice logic and every fail-closed path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(standards): install PyYAML in the selftest job; exact-ref branch existence (backend#1602) Both from Bugbot on .github#170. The selftest's good-path load_targets check parses YAML, and a clean setup-python has no PyYAML — the job died at the final check (mirrors caller-drift's selftest job now). And resolve_branch now uses the exact-match git/ref/heads/develop lookup, the same endpoint remediate() trusts for the base sha. Verified live: backend resolves develop, release-train falls back to main. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(standards): a guard crash exits 2 (could not evaluate), never 1 (drift) (backend#1602) Bugbot on .github#170: Python exits 1 on an unhandled traceback, and 1 is reserved for confirmed drift — so a malformed API payload or filesystem error produced a drift report instead of the unknown-state failure. The entry point now maps any crash to exit 2 with an ::error:: line. Pinned by a selftest that runs the guard with gh stripped from PATH. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…on a failed audit (#173) * feat(ci): required conformance gate — a contract change cannot merge on a failed audit caller-drift.yml has run on PRs touching repo-inventory.yml since backend#1415, and it correctly fails when the inventory disagrees with reality. But it is not a required status check: .github/develop requires only actionlint. So a PR that adds a repo to the train with drift went RED and could still be merged. The gate existed in trigger form and had no teeth. It cannot simply be marked required as-is. It carries a paths: filter, and a path-filtered required check never reports on PRs that miss the filter, leaving them pending forever - the trap actionlint.yml's own header documents. Dropping the filter would instead run a 20-repo API audit on every PR in this repo, which is the reason the filter is there. So this adds a job that ALWAYS runs and ALWAYS reports. On a PR that does not touch the contract it is green in seconds with zero audit API calls. On a PR that does, it requires caller-drift's verdict for that exact head sha. It keys on the WORKFLOW FILE, not the check name. Check-run names are not unique across workflows - caller-drift.yml and standards-sync.yml both expose a job called selftest - so polling by name would happily accept the wrong workflow's verdict. Querying actions/workflows/caller-drift.yml/runs?head_sha=... cannot be confused that way. Fail-closed on every non-success branch, each with a named reason: no run found within the poll budget, a non-success conclusion, an unreadable API, or a changed-file list that came back empty (unreadable, not "no files"). The --paginate on the files query matters: a PR over one page would otherwise look like it touches only its first 30 files, and a truncated read reporting "not guarded" is precisely the silent pass this file exists to prevent. The path match is exact (grep -qxF), verified offline against the cases that matter: docs/repo-inventory.yml and repo-inventory.yml.bak do NOT count as touching the contract. This PR edits repo-inventory.yml's header on purpose, so it exercises its own guarded path rather than shipping a gate whose interesting branch never ran. Refs backend#1608, backend#1415. * fix(inventory): .github's code-quality caller is required, not exempt Caught by the gate this PR adds, on its own first run. The audit reported: .github: code-quality.yml is marked `exempt` but a caller exists (code-quality-caller.yml). The exemption is stale. Correct, and the drift is an hour old: .github#171 landed the caller for backend#1603 and never flipped this entry. That is precisely the follow-up caller-drift.py's docstring tells you to do -- "land the caller first, flip the entry in a follow-up" -- because the inventory is read from the checkout while repo state is read from the audit branch, so doing both in one commit fails. So the sequence worked exactly as designed: the caller landed, the entry went stale, and the very next inventory-touching PR was refused until it was reconciled. That is the whole point of the gate, demonstrated on itself rather than asserted in a comment. The exemption text is replaced with the remediation history rather than deleted, matching how the pii-gate and e2e-test-agent entries record theirs -- the reason the exemption existed is evidence, not noise. * fix(gate): here-string, not a pipe — SIGPIPE under pipefail turned a hit into a miss Bugbot, .github#173. Reproduced before fixing: 20,000 filenames (~349 KB) with the guarded path FIRST printf '%s\n' "$FILES" | grep -qxF repo-inventory.yml -> pipeline rc 141, `if` takes the else branch, gate reports NOT GUARDED grep -q exits on its first match and closes the pipe. With enough left to write, printf takes SIGPIPE and exits 141; pipefail then makes the PIPELINE 141, so a real match reads as a miss. The gate would report "not guarded" and pass GREEN on precisely the PRs most likely to matter -- the failure gets MORE likely as the diff gets bigger, and it fails OPEN, which is the one direction this file exists to rule out. A here-string is a single command, so the status is grep's own. Verified: same input, same guarded path, correctly GUARDED. Swept the rest of the repo for the pattern. fr-gate.yml has two instances (`echo "$LABELS" | grep -q ...`), and both are safe on two independent counts: a PR's label JSON is orders of magnitude under the 64 KB pipe buffer, so echo finishes before grep can exit; and a false negative there means the gate does NOT skip, i.e. it fails CLOSED. Same pattern, opposite consequence -- left alone deliberately rather than changed for symmetry. The `| head -1` chains in version-bump-gate.yml and the kanban workflows are likewise safe: each is either terminated by `|| true` or fed by output far under the buffer. Refs backend#1608, backend#1409 (same defect class in the PII gate). * fix(gate): renames escaped the guard; poll budget was shorter than what it waits for Two Bugbot findings on .github#173. HIGH - a rename escaped the contract guard. The changed-file probe read only .filename, and a rename reports the NEW path there. So `git mv repo-inventory.yml elsewhere.yml` sailed through as "not guarded": the contract file moves out from under the audit and the gate waves it past - precisely the silent pass this workflow exists to close. Now reads BOTH .filename and .previous_filename, which is the same reason promote-repo.sh's publishable_delta matches both fields (a file renamed OUT of a published tree is still a publish-path change). I had read that comment while building the version-bump gate and failed to carry it across. Proven on a synthetic rename payload, since no open PR has one: old jq (.filename only) -> NOT GUARDED <- the hole new jq (+ .previous_filename) -> GUARDED and verified against a real PR that the `// empty` guard emits nothing extra when previous_filename is absent. MEDIUM - the poll budget was shorter than the thing it waits for. 40x30s = 20 minutes, while caller-drift's worst case is selftest (timeout 5m) + audit (timeout 30m) = 35m. A legitimately slow audit would have made the gate go red as though no verdict ever arrived, blocking a contract change until someone re-ran it by hand. Fail-closed is right; fail-closed on a budget that cannot cover the wait is just fail-annoying, and a gate people have to re-run by hand is a gate they campaign to remove. Budget is now 80x30s = 40m with the job timeout raised to 45m so the named error message surfaces rather than an opaque job timeout. Refs backend#1608.
…backend#1603 step 2) (#178) The second half of backend#1603. When code-quality-caller.yml landed in #171 it could not arm action-pins: the job and its two inputs were added in #159 and existed on `develop` only, and a caller must reference @main (Q3). Passing an input the @main callee does not declare kills the entire reusable call with a startup_failure - not the one job, the whole call - measured on that branch's first push, run 31086491251. #159 has since promoted, and `main` now carries the six-job version with both inputs. Verified against the @main copy before flipping, rather than assuming the promotion carried what it looks like it carried. Hard-armed rather than left to inherit soft-fail. This is the check whose absence let .github#168 revert actions/checkout from a pinned commit SHA to the mutable @v4 tag with nothing in CI to object - in advance-deploy-env.yml, the most-consumed reusable workflow in the org, running with PROJECTS_KANBAN_TOKEN in scope. Every other repo consumes these workflows at @main and inherits whatever refs they pin, so this repo has a specific duty to enforce the rule it publishes. Re-measured the tree before arming: 24 `uses:` refs across 23 workflows, zero violations. Arming imports no backlog.
LukasWodka
commented
Aug 6, 2026
ContributorAuthor
bugbot run |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c35327e. Configure here.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Automated promotion by the release train (RFC-0008 D14). Head is the train-managed
release-train/to-stagingbranch (a mirror ofdevelop), so it never collides with a human PR. Merged only when the fr-gate is green.Note
High Risk
Changes org-wide required checks, kanban GraphQL updates with PROJECTS_KANBAN_TOKEN, and security-sensitive PII/version gate logic consumed at @main by many repos.
Overview
This promotion bundles a large tracebloc/.github refresh: new fail-closed guards, kanban automation fixes, and org-wide standards tooling—not only a branch pointer move.
Kanban & deploy tracking:
advance-deploy-envgains adry_runinput and now advances closed issues linked from promoted PRs (including cross-repo), with the same monotonic rules as PR cards.kanban-reconcileauto-applieskeep-openon open issues in North Stars so the stale sweep cannot archive strategic epics.New or tightened CI: A
code-quality-callerruns the published reusable workflow in this repo withsoft-fail: falseand hardaction-pins.conformance-gateis an always-on PR check that, whenrepo-inventory.yml(or related contract files) change, requires a successfulcaller-driftrun on the same SHA. A reusableversion-bump-gatemirrors release-trainversion_preflightat PR time, with offline selftests.standards-syncplusorg-standards.mdsync a managed block into fleetCLAUDE.mdfiles.Gate behavior fixes:
public-pii-gatecheckspii-gate-overridebefore refusals and fails closed on fork PRs with fork-specific messaging.customer-priority-bumpdrops unused project/org/priority inputs (label-only under D5).repo-inventory.ymldocuments the conformance gate and marks.githubas requiring code-quality;e2e-test-agentis on the release train.Docs: README adds guidance to wire
version-bump-gate-callerforversion_filerepos.Reviewed by Cursor Bugbot for commit c35327e. Bugbot is set up for automated code reviews on this repo. Configure here.