From c76be47ac7c5a6c2e309fefa2a091f713cb57630 Mon Sep 17 00:00:00 2001 From: lukasWuttke <54042461+LukasWodka@users.noreply.github.com> Date: Sun, 13 Sep 2026 11:37:26 +0200 Subject: [PATCH 01/12] chore(onboard): add .github/workflows/advance-deploy-env.yml (content profile) --- .github/workflows/advance-deploy-env.yml | 53 ++++++++++++++---------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/.github/workflows/advance-deploy-env.yml b/.github/workflows/advance-deploy-env.yml index c74f523..437e704 100644 --- a/.github/workflows/advance-deploy-env.yml +++ b/.github/workflows/advance-deploy-env.yml @@ -1,4 +1,4 @@ -# GENERATED FILE -- DO NOT EDIT BY HAND (tracebloc/backend#3591). +# GENERATED FILE -- DO NOT EDIT BY HAND. # # Self-contained copy of the reusable workflow `.github/workflows/advance-deploy-env.yml` # (blob 3656a2eaa46555c157af7f713ec7d25f56aa487f) folded with tracebloc/org-config's own caller of it, @@ -15,6 +15,13 @@ # read-only App installation token; on a fork PR that token cannot be minted # (no secrets), so the checkout fails closed rather than running untrusted input. # +# PUBLIC SURFACE. This file is delivered to a public repo, so its comments carry +# no internal references: each one was replaced with `(internal ref)` by the +# one definition in scripts/public_surface.py (private-repo issue references, +# private repo names, RFC ids, tenant names). A reference anywhere outside a +# comment refuses the render instead of being edited -- it is a defect in the +# source, not a scrub target. +# # Regenerate: python3 scripts/render-self-contained.py (in tracebloc/org-config) # Verify: python3 scripts/render-self-contained.py --check (make selftest-self-contained) # @@ -55,7 +62,7 @@ name: Advance deploy environment # tracebloc/.github's `scripts/branch_status_map.py` -- read the list there rather # than from a copy here. The three names this comment used to list were a copy, and # the table has five. -# A value outside it is REFUSED (backend#2324): the mapper exits non-zero, this +# A value outside it is REFUSED ((internal ref)): the mapper exits non-zero, this # workflow fails red and the card keeps whatever Status it had. It used to be # accepted and passed straight to the board write, where it resolves to no option # id -- and in the closure router that no-write let the project's built-in @@ -72,7 +79,7 @@ jobs: # not newly shipped. Without this guard, creating a branch (BEFORE = zero # hash) falls through to the "last 50 commits" range below and mass-advances # ~50 recent PRs' kanban items — e.g. every time a new `staging` branch is - # cut for a repo (RFC-BACKEND-0008 D8/#1274). Skip create/delete pushes. + # cut for a repo ((internal ref) D8/#1274). Skip create/delete pushes. if: github.event.created != true && github.event.deleted != true runs-on: ubuntu-latest steps: @@ -81,7 +88,7 @@ jobs: fetch-depth: 0 # The mapping comes from .github, not from a copy in this file: one - # definition of branch -> Status (backend#2243). + # definition of branch -> Status ((internal ref)). - name: Mint a read-only token for org-config (private; the caller's own token cannot read it) id: org-config-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 @@ -107,7 +114,7 @@ jobs: # The workflow token, not the App token: this reads `.kanban.yml` # from the caller's own repo, which is `contents: read` on itself. GH_TOKEN: ${{ github.token }} - # ONE DEFINITION, SHARED WITH THE CLOSURE ROUTER (backend#2243). This step + # ONE DEFINITION, SHARED WITH THE CLOSURE ROUTER ((internal ref)). This step # used to hold its own `case` plus its own `yq` read of `.kanban.yml`, and # the router held two more copies that ignored the override entirely -- so # with a `.kanban.yml` present the two workflows wrote DIFFERENT statuses @@ -123,7 +130,7 @@ jobs: run: | echo "Branch '$BRANCH' is not develop/staging/master/main (and no .kanban.yml override) - nothing to do." - # THIS is the workflow backend#2036 was filed about. On 2026-08-14 at 06:22 + # THIS is the workflow (internal ref) was filed about. On 2026-08-14 at 06:22 # UTC, run 31776053792 on client-runtime died with # gh: API rate limit already exceeded for user ID 54042461 # exit 1 -- because every board caller in the fleet, both crons, the @@ -137,7 +144,7 @@ jobs: # org ProjectV2. # # Minted BEFORE the extract step, because the extract step is its first - # consumer (backend#3447): `/commits/{sha}/pulls` needs `pull-requests: read`, + # consumer ((internal ref)): `/commits/{sha}/pulls` needs `pull-requests: read`, # and the caller's `github.token` runs under the org default of restricted # `read` -- contents and packages only -- so under that token the read 403s # on every PRIVATE repo and succeeds on every public one. From .github#438 @@ -150,7 +157,7 @@ jobs: # # NO FALLBACK TO THE PAT: a fallback would let a broken App path keep # working silently, so the migration would look complete while nothing had - # migrated (backend#1680's whole subject). + # migrated ((internal ref)'s whole subject). - name: Mint an installation token id: app-token if: steps.env.outputs.env != '' @@ -159,7 +166,7 @@ jobs: app-id: ${{ secrets.RELEASE_TRAIN_APP_ID }} private-key: ${{ secrets.RELEASE_TRAIN_APP_PRIVATE_KEY }} owner: ${{ github.repository_owner }} - # LEAST PRIVILEGE, DERIVED FROM THIS JOB'S OWN CALLS (backend#2157). + # LEAST PRIVILEGE, DERIVED FROM THIS JOB'S OWN CALLS ((internal ref)). # Without any `permission-*` the token carried the App's FULL installation # grant -- contents:write included -- across every installed repo. The # step below makes exactly five kinds of call, and this is the union of @@ -179,7 +186,7 @@ jobs: # # `repositories:` STAYS UNNARROWED, but the reason it used to give is gone. # It cited the closing-issue advancement, which was deliberately cross-repo; - # backend#2722 removed that block, so nothing here reaches outside the + # (internal ref) removed that block, so nothing here reaches outside the # calling repo any more. `organization-projects` is an ORG-level grant and is # not narrowed by `owner:` alone either way, so leaving this unnarrowed costs # nothing measurable -- narrowing it is a plausible tidy-up, but it is a token @@ -193,7 +200,7 @@ jobs: # branch carrying a PR is the real test; if it reddens, read the failing # call rather than widening the list back to a full grant. # `contents: read` IS FOR THE EXTRACT STEP'S CALL SITE, NOT THE MAPPER'S - # (backend#3447). Read this before dropping it again. + # ((internal ref)). Read this before dropping it again. # # saadqbal's finding on .github#324 was narrow and is STILL CORRECT, by its # own test -- check the call site, not the prose. `contents: read` reached @@ -212,14 +219,14 @@ jobs: # scope is now this token's business, which it was not when #324 was # written. `fr-gate.yml`'s mint comment ("NOT DERIVED FROM A TEMPLATE") # records that endpoint as `contents: read + pull-requests: read`, derived - # from its own calls under backend#2157 and running as a required check on + # from its own calls under (internal ref) and running as a required check on # every promotion since; no workflow in this repo reads that endpoint under # `pull-requests: read` alone. Granting only PRs read - # would reproduce backend#3447 one scope over, in the same silent shape: + # would reproduce (internal ref) one scope over, in the same silent shape: # the read 403s, the fail-closed branch refuses the subject fallback, and # no card moves on any private repo. # - # `permission-issues` DROPPED (backend#2722). The only issue reads were + # `permission-issues` DROPPED ((internal ref)). The only issue reads were # `repository.issue(n) {state, projectItems}` in the removed closing-issue # block; with it gone, nothing in this workflow touches an issue. Re-add it # only alongside a call that needs it. @@ -236,10 +243,10 @@ jobs: # The App token minted ABOVE, not `github.token`: `/commits/{sha}/pulls` # needs `pull-requests: read` + `contents: read`, and the org-default # restricted workflow token holds only the latter on a private repo - # (backend#3447; the mint step's comment has the derivation). + # ((internal ref); the mint step's comment has the derivation). GH_TOKEN: ${{ steps.app-token.outputs.token }} # DERIVE each commit's PR from GitHub, not from its subject text - # (backend#3365). The org convention `type(scope): summary (backend#N)` + # ((internal ref)). The org convention `type(scope): summary (backend#N)` # puts a ticket in the `(#N)` slot, and an edited squash subject may carry # no `(#N)` at all -- so the old subject-grep attributed the wrong card or # none (2/48 on the 2026-09-07 staging hop). The script GETs each commit's @@ -339,9 +346,9 @@ jobs: # now -- nothing writes this value yet (#1578 does that, in a LATER # hop). An unknown Status returns "" here, the guard below fails, and # evaluation falls through to strict equality: the card BLOCKS every - # prod promotion carrying it. That is the backend#1411 shape, and the + # prod promotion carrying it. That is the (internal ref) shape, and the # column already EXISTS on the board, so this was a live landmine - # waiting for the first card to land in it (#1577, RFC-BACKEND-1552 D5). + # waiting for the first card to land in it (#1577, (internal ref) D5). "Staging (agent review)") echo 7 ;; # `Staging (human review)` IS GONE (saadqbal on .github#295). It ranked # here as a shim so the monotonic guard stayed stable across the #1592 @@ -363,7 +370,7 @@ jobs: # them. Both returned 0 here, which inverted the monotonic guard below # so the next push carrying an old commit demoted a Done card -- and # staging->develop back-merges re-carry old commits routinely - # (RFC-BACKEND-1405 D8, backend#1411). + # ((internal ref) D8, (internal ref)). "Done") echo 11 ;; "Cancelled") echo 11 ;; *) echo 0 ;; @@ -377,7 +384,7 @@ jobs: # items are already skipped above; this is defense-in-depth for any other # per-item error -- log it, flag the run, but keep processing the rest. RUN_FAILED=0 - # A FAILED LOOKUP IS NOT AN ABSENT CARD (Bugbot, org-config#3). Counted + # A FAILED LOOKUP IS NOT AN ABSENT CARD (Bugbot, (internal ref)). Counted # separately from RUN_FAILED because it is a different event: a card # whose state this run could not READ, as opposed to one it read and # could not write. The loop keeps going either way -- one 403 must not @@ -410,7 +417,7 @@ jobs: # `... 2>/dev/null) || RESP='{}'`, so a rate limit, a 403 or a network # error became an empty object, the item lookup below found nothing in # it, and the card was "not on project - skipping" -- unmoved, behind - # its shipped code, in a run that stayed GREEN (Bugbot, org-config#3). + # its shipped code, in a run that stayed GREEN (Bugbot, (internal ref)). # A read that failed is a could-not-tell and is recorded as one. # # `gh api graphql` exits 1 for a GraphQL-level error too, and ONE of @@ -485,14 +492,14 @@ jobs: # NO ISSUE ADVANCEMENT HERE. This workflow advances PRs only. # - # It used to also advance the issues each promoted PR closes (backend#1600), + # It used to also advance the issues each promoted PR closes ((internal ref)), # because the closure router parked a PR-closed issue at `On dev` and nothing # ever moved it when the code shipped -- it drifted permanently (2026-08-06: # all 20 drifted cards were closed issues, 0 PRs). That was a real problem and # #1600 was right to fix it; marching the card through the deploy columns was # the wrong remedy. # - # backend#2722 sends a completed issue straight to `Done` in + # (internal ref) sends a completed issue straight to `Done` in # kanban-closure-router.yml instead. `Done` is terminal, so there is nothing # left to drift, and kanban-archive sweeps it off the board daily -- which # answers #1600 more completely than advancing ever did. With no issue parked From 58be733d290f363290d18574d07113561d168ba0 Mon Sep 17 00:00:00 2001 From: lukasWuttke <54042461+LukasWodka@users.noreply.github.com> Date: Sun, 13 Sep 2026 11:37:27 +0200 Subject: [PATCH 02/12] chore(onboard): add .github/workflows/bugbot-gate.yml (content profile) --- .github/workflows/bugbot-gate.yml | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/.github/workflows/bugbot-gate.yml b/.github/workflows/bugbot-gate.yml index d7f5b09..2531b16 100644 --- a/.github/workflows/bugbot-gate.yml +++ b/.github/workflows/bugbot-gate.yml @@ -1,4 +1,4 @@ -# GENERATED FILE -- DO NOT EDIT BY HAND (tracebloc/backend#3591). +# GENERATED FILE -- DO NOT EDIT BY HAND. # # Self-contained copy of the reusable workflow `.github/workflows/bugbot-gate.yml` # (blob c526c0a1f25316f429afbadb00ae1eaa4d0807bc) folded with tracebloc/org-config's own caller of it, @@ -15,6 +15,13 @@ # read-only App installation token; on a fork PR that token cannot be minted # (no secrets), so the checkout fails closed rather than running untrusted input. # +# PUBLIC SURFACE. This file is delivered to a public repo, so its comments carry +# no internal references: each one was replaced with `(internal ref)` by the +# one definition in scripts/public_surface.py (private-repo issue references, +# private repo names, RFC ids, tenant names). A reference anywhere outside a +# comment refuses the render instead of being edited -- it is a defect in the +# source, not a scrub target. +# # Regenerate: python3 scripts/render-self-contained.py (in tracebloc/org-config) # Verify: python3 scripts/render-self-contained.py --check (make selftest-self-contained) # @@ -24,7 +31,7 @@ name: Bugbot review gate # Reusable workflow. Makes Cursor Bugbot's review a GATE instead of advice -# (tracebloc/backend#2284). `scripts/bugbot-gate.py` carries the measurements and +# ((internal ref)). `scripts/bugbot-gate.py` carries the measurements and # the reasoning; this file is the wiring, and only says what the script cannot. # # THE SHORT VERSION OF WHY THIS IS NOT "ADD `Cursor Bugbot` TO THE REQUIRED @@ -38,7 +45,7 @@ name: Bugbot review gate # a finding, because Bugbot re-runs only on a push or an explicit # `bugbot run`, so resolving a finding can never turn the check green again # -- and a promotion PR may not be pushed to at all. client#786 and -# frontend-app#863 both merged to `main` on 2026-08-21 carrying exactly that +# (internal ref) both merged to `main` on 2026-08-21 carrying exactly that # state (`neutral` on the merged head, one resolved Medium beneath). # # So the verdict is REPORTED here and the decision is derived from the threads. @@ -46,18 +53,18 @@ name: Bugbot review gate # ARMING THIS IS THREE STEPS, IN THIS ORDER, AND THE ORDER IS THE POINT. # # 1. this file reaches `main`. Every caller in this org pins -# `tracebloc/.github/...@main` (RFC-BACKEND-1405 Q3), so a caller added +# `tracebloc/.github/...@main` ((internal ref) Q3), so a caller added # before the reusable is ON main references something main does not have and # dies with a `startup_failure` -- a red check on the very PR introducing a # gate. code-quality-caller.yml records the identical sequencing for its # `action-pins` input: the job went to develop in #159 and was armed only # once `main` carried it. That is why the PR adding THIS file adds no caller. # 2. a caller is added, starting with tracebloc/.github itself. The gate is -# ADVICE at this point, and saying so plainly is the whole of backend#2284. +# ADVICE at this point, and saying so plainly is the whole of (internal ref). # 3. the `bugbot / review` context is added to branch protection, once step 2 # has been observed green on real PRs. # -# Never the reverse. backend#1976's lesson is that a contract claiming a context +# Never the reverse. (internal ref)'s lesson is that a contract claiming a context # reality lacks is itself a finding; and a required context no workflow reports # leaves every PR waiting forever (client#665, pii-gate/pii-check). Arm while # green, then let the contract claim it. @@ -91,7 +98,7 @@ name: Bugbot review gate # The consequence is written into the failure message rather than left to be # discovered: resolve the thread, then RE-RUN this check. Not "push a commit", # which is what a stale gate otherwise teaches. Adding the trigger when -# actionlint learns the event is a follow-up on backend#2284. +# actionlint learns the event is a follow-up on (internal ref). # # THIS JOB WAITS, on purpose. Its central claim is that Bugbot reviewed the # CURRENT head, which is false for the first minutes after every push -- so it @@ -166,7 +173,7 @@ jobs: env: # `github.token`, not `secrets.inherit`: this needs only the scopes # declared above, and inheriting would hand it every secret the caller - # holds for no gain (RFC-BACKEND-1405 Q5). + # holds for no gain ((internal ref) Q5). GH_TOKEN: ${{ github.token }} REPO: ${{ github.repository }} PR_NUMBER: ${{ github.event.pull_request.number }} From ae3cf16d899a58959abddd4bab21ca2ec1551065 Mon Sep 17 00:00:00 2001 From: lukasWuttke <54042461+LukasWodka@users.noreply.github.com> Date: Sun, 13 Sep 2026 11:37:29 +0200 Subject: [PATCH 03/12] chore(onboard): add .github/workflows/code-quality.yml (content profile) --- .github/workflows/code-quality.yml | 49 +++++++++++++++++------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index 4bf719a..a0375f0 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -1,7 +1,7 @@ -# GENERATED FILE -- DO NOT EDIT BY HAND (tracebloc/backend#3591). +# GENERATED FILE -- DO NOT EDIT BY HAND. # # Self-contained copy of the reusable workflow `.github/workflows/code-quality.yml` -# (blob 50e3e61e2be49ed44f62d7896f11d93dad513a5e) folded with tracebloc/org-config's own caller of it, +# (blob 989a83785c26b32ae6047acb06315a89fc991722) folded with tracebloc/org-config's own caller of it, # `.github/workflows/code-quality-caller.yml` (blob d0d9d4c4ecb1747e9f1b3fadcf516b79fe8c55bb), for a PUBLIC repo: GitHub lets a # public repo `uses:` a reusable workflow only from a public repo, and the # reusables live in the private tracebloc/org-config. So this file carries the @@ -15,6 +15,13 @@ # read-only App installation token; on a fork PR that token cannot be minted # (no secrets), so the checkout fails closed rather than running untrusted input. # +# PUBLIC SURFACE. This file is delivered to a public repo, so its comments carry +# no internal references: each one was replaced with `(internal ref)` by the +# one definition in scripts/public_surface.py (private-repo issue references, +# private repo names, RFC ids, tenant names). A reference anywhere outside a +# comment refuses the render instead of being edited -- it is a defect in the +# source, not a scrub target. +# # Regenerate: python3 scripts/render-self-contained.py (in tracebloc/org-config) # Verify: python3 scripts/render-self-contained.py --check (make selftest-self-contained) # @@ -67,7 +74,7 @@ name: Code quality # and anything else (ruff 2, shellcheck 2-4, gitleaks >1, 126/127, a signal) # fails the job with exit 2 whatever `soft-fail` says. A scan that produced no # verdict has not passed; recording it as clean is how a gate turns into -# decoration (Bugbot on org-config#3, backend#3658; backend#1729 rule 3). +# decoration (Bugbot on (internal ref), (internal ref); (internal ref) rule 3). # # ADOPTION — drop this in as `.github/workflows/code-quality-caller.yml` # @@ -103,8 +110,8 @@ name: Code quality # the App id and key that mint a read-only token for tracebloc/org-config, # the PRIVATE repo the house-rules and pipefail scripts are checked out of. # Callers pass those two BY NAME and nothing else -- decided under -# RFC-BACKEND-1405 Q5 (backend#1420, unwound in backend#1526; the carve-out -# for these two on org-config#3). `inherit` was briefly the convention +# (internal ref) Q5 ((internal ref), unwound in (internal ref); the carve-out +# for these two on (internal ref)). `inherit` was briefly the convention # ("harmless no-op, nothing is referenced"), but callers pin `@main`: the day # a reusable gains a `${{ secrets.X }}` step, every inheriting caller hands it # that repo's ENTIRE secret set (`toJSON(secrets)` dumps it). Explicit @@ -112,7 +119,7 @@ name: Code quality # REQUIRED declaration makes a caller that forgets fail at startup rather than # at run time with an empty app-id. Cursor Bugbot's recurring nag about the # "missing" `inherit` line is suppressed per-repo in `.cursor/BUGBOT.md` (the -# backend#1304 flywheel); the inverse -- a caller that ADDS `secrets: inherit` +# (internal ref) flywheel); the inverse -- a caller that ADDS `secrets: inherit` # -- is what deserves a finding. # # SUPPLY CHAIN @@ -240,7 +247,7 @@ jobs: GATE=".quality-tools/scripts/pipefail-early-close.sh" chmod +x "$GATE" - # TWO SCOPES, ONE RULE (backend#2967). `shell` is the tree's shell + # TWO SCOPES, ONE RULE ((internal ref)). `shell` is the tree's shell # files -- the verdict this job has always produced, under whatever # `soft-fail` the caller chose. `yaml` is the `run:` blocks of # workflows and composite actions, which were never in scope at all: @@ -279,7 +286,7 @@ jobs: # executable / not found), a signal death. Those are ALWAYS fatal, # soft-fail or not: a gate that could not check has not passed, and # letting soft-fail swallow it is how a gate becomes decoration - # (backend#1729 rule 3). + # ((internal ref) rule 3). # # Whitelisting the verdicts rather than blacklisting rc=2 is the # load-bearing part. The first version tested `[ "$RC" = 2 ]`, so a @@ -384,10 +391,10 @@ jobs: # produced by a git-mode scan. Switching any branch here to `gitleaks # dir`/`detect` (path-scoped fingerprints) silently invalidates every # baseline entry fleet-wide at once — 277 suppressions un-suppress in - # a single run (backend#1404 §4). Permanent fixtures live in per-repo + # a single run ((internal ref) §4). Permanent fixtures live in per-repo # `.gitleaks.toml` allowlists instead (auto-loaded from the checkout # root, commit-INDEPENDENT); only genuine historical exposure stays - # baselined, tracked for rotation in backend#1355. + # baselined, tracked for rotation in (internal ref). RC=0 if [ "$ALL_FILES" = "true" ] || [ -z "${BASE_SHA:-}" ]; then echo "Scanning the full history." @@ -403,7 +410,7 @@ jobs: # scan, the same as ruff/shellcheck/house-rules (Bugbot #65). If the # FALLBACK errors too, RC carries that code into the verdict check # below and the job fails -- it used to flow into the soft-fail - # branch and exit 0 (backend#3658). + # branch and exit 0 ((internal ref)). if [ "$RC" != "0" ] && [ "$RC" != "1" ]; then echo "::warning::gitleaks range scan errored (exit $RC) — falling back to a full-history scan." RC=0 @@ -411,7 +418,7 @@ jobs: fi fi - # ONLY 0 AND 1 ARE VERDICTS (Bugbot, org-config#3; backend#3658). Any + # ONLY 0 AND 1 ARE VERDICTS (Bugbot, (internal ref); (internal ref)). Any # other code -- from the full scan, or from the fallback after the range # scan already failed once -- is a scanner that could not run: a broken # binary, an unreadable repository, a signal death, 126/127. That is not @@ -432,7 +439,7 @@ jobs: # A report that exists but cannot be read is a scan whose result is # UNKNOWN -- it must never count as zero findings. `|| echo 0` did exactly # that, and under the default soft-fail it exited 0 as all-clear (Bugbot, - # org-config#3). Exit 2 here is deliberately outside the soft-fail path: + # (internal ref)). Exit 2 here is deliberately outside the soft-fail path: # soft-fail governs FINDINGS, not a scanner that could not be read. COUNT=0 if [ -s /tmp/gitleaks.json ]; then @@ -466,7 +473,7 @@ jobs: # (measured: tips at ~250 findings / ~24K, nondeterministically at the # boundary, because it is a race). A here-string is one command, so jq # always runs to completion and the status is its own. - # (backend#1778 -- same class as .github#173 and the PII gate's #1409.) + # ((internal ref) -- same class as .github#173 and the PII gate's #1409.) # # `|| true` keeps a parse failure non-fatal, which is what the existing # `2>/dev/null` already intended; it is near-unreachable anyway, since @@ -578,7 +585,7 @@ jobs: "$CHECKER" "$@" - # RFC-0087 D3 (backend#3523): what a repo declares, ships and installs must + # (internal ref) D3 ((internal ref)): what a repo declares, ships and installs must # be reachable from what it runs. Rides THIS job on purpose -- `quality / # house-rules` is a required status check on every train repo's develop # (measured 2026-09-09), so the checker is a gate the day it lands without @@ -619,7 +626,7 @@ jobs: python3 "$CHECKER" "$@" - # Whole-tree action-pin gate (backend#1492, D10). Hand-pinning does not hold: + # Whole-tree action-pin gate ((internal ref), D10). Hand-pinning does not hold: # while one PR pinned jlumbroso/free-disk-space, a second PR added a NEW # unpinned call site of the same action in a non-overlapping hunk of the same # file — both merged cleanly, no conflict, caught only by a human reading the @@ -635,13 +642,13 @@ jobs: # (comment lines excluded; quoted refs unwrapped) covers every real workflow # in the fleet, and anything it cannot parse — e.g. `uses: ${{ ... }}` # expressions — is REPORTED as a finding rather than skipped: a guard that - # cannot verify must refuse to claim it did (RFC-1405 property 2; with + # cannot verify must refuse to claim it did ((internal ref) property 2; with # soft-fail off, that refusal is red). # # ALLOWED forms (everything else is a finding): # ./local/path repo-local actions # tracebloc/<...>@main org reusables float on @main BY DECISION - # (RFC-1405 Q3; any other tracebloc ref is + # ((internal ref) Q3; any other tracebloc ref is # drift, same rule as caller-drift's) # owner/action[/path]@<40-hex sha> D10 pin (trailing "# vX.Y.Z" comment is # convention but not enforced here) @@ -667,7 +674,7 @@ jobs: # incapable of EVER arming the job -- it could only ever weaken it -- # while 16 of 16 callers pass `action-pins-soft-fail: false` expecting # the opposite, and four of them carry a comment claiming the check is - # "Armed ... independent of soft-fail above". It was not (backend#1681). + # "Armed ... independent of soft-fail above". It was not ((internal ref)). SOFT_FAIL: ${{ false && 'true' || 'false' }} run: | set -euo pipefail @@ -721,12 +728,12 @@ jobs: # clean tree. Malfunctions fail even under soft-fail: that flag # governs FINDINGS, never the scan's own integrity (Bugbot, # .github#159; the watchdog's findings-vs-malfunction split). - print("::error::action-pins scanned ZERO workflow files - the checkout or cwd is wrong; refusing to report a pass (backend#1492)") + print("::error::action-pins scanned ZERO workflow files - the checkout or cwd is wrong; refusing to report a pass") sys.exit(2) level = "warning" if os.environ.get("SOFT_FAIL") == "true" else "error" for f, lineno, ref, why in findings: - print(f"::{level} file={f},line={lineno}::unpinned action ref '{ref}' - {why} (backend#1492)") + print(f"::{level} file={f},line={lineno}::unpinned action ref '{ref}' - {why}") # The summary carries the FULL list, like ruff/format/gitleaks do: # annotations cap at ten per step, so a backlog-carrying repo would From 0018bbe462ca6c32c1f6f467860905e089473775 Mon Sep 17 00:00:00 2001 From: lukasWuttke <54042461+LukasWodka@users.noreply.github.com> Date: Sun, 13 Sep 2026 11:37:30 +0200 Subject: [PATCH 04/12] chore(onboard): add .github/workflows/customer-priority-bump.yml (content profile) --- .github/workflows/customer-priority-bump.yml | 49 +++++++++++--------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/.github/workflows/customer-priority-bump.yml b/.github/workflows/customer-priority-bump.yml index 978fb33..c7b2e6c 100644 --- a/.github/workflows/customer-priority-bump.yml +++ b/.github/workflows/customer-priority-bump.yml @@ -1,4 +1,4 @@ -# GENERATED FILE -- DO NOT EDIT BY HAND (tracebloc/backend#3591). +# GENERATED FILE -- DO NOT EDIT BY HAND. # # Self-contained copy of the reusable workflow `.github/workflows/customer-priority-bump.yml` # (blob f3c865da70e5d4b9eda8c49a229ba2ca829d06cd) folded with tracebloc/org-config's own caller of it, @@ -15,6 +15,13 @@ # read-only App installation token; on a fork PR that token cannot be minted # (no secrets), so the checkout fails closed rather than running untrusted input. # +# PUBLIC SURFACE. This file is delivered to a public repo, so its comments carry +# no internal references: each one was replaced with `(internal ref)` by the +# one definition in scripts/public_surface.py (private-repo issue references, +# private repo names, RFC ids, tenant names). A reference anywhere outside a +# comment refuses the render instead of being edited -- it is a defect in the +# source, not a scrub target. +# # Regenerate: python3 scripts/render-self-contained.py (in tracebloc/org-config) # Verify: python3 scripts/render-self-contained.py --check (make selftest-self-contained) # @@ -32,7 +39,7 @@ name: Label-driven issue triage # Writes no board field -- the Priority single-select was # removed from the board under D5. # work-type:bug -> move the issue's kanban card from `Backlog` to `Ready` -# (backend#2348). Defects skip refinement. +# ((internal ref)). Defects skip refinement. # # WHY BOTH LIVE IN ONE FILE, AND WHY THE FILENAME NO LONGER MATCHES # ---------------------------------------------------------------- @@ -53,18 +60,18 @@ name: Label-driven issue triage # work -- it no longer waits on anything, since the wiring below is complete. # # WIRED EVERYWHERE NOW. Every repo has a caller (`.github`'s landed under -# backend#2396) and `customer_priority_bump_caller_missing` is GONE from +# (internal ref)) and `customer_priority_bump_caller_missing` is GONE from # `repo-inventory.yml` -- no repo carries that key any more, so any text sending a # reader to that lookup is describing a key that cannot answer. (The STRING still # appears elsewhere in the repo, in `scripts/reason-citations.py` and in this # comment; it is the INVENTORY that no longer records it. @aptracebloc on #350.) # -# THE LABEL GAP IS CLOSED, AND NOW ASSERTED (backend#2598). This block used to +# THE LABEL GAP IS CLOSED, AND NOW ASSERTED ((internal ref)). This block used to # record a live defect: repos carrying this caller with no `work-type:*` labels at # all. GitHub silently DROPS a template label the target repo lacks -- no error, no # annotation, no run -- so the issue was filed unlabelled, `bug-to-ready` never saw # its label, and the card sat in `Backlog`, the refinement queue nobody pulls from. -# The exact miss backend#2348 was filed to close, surviving in the repos a +# The exact miss (internal ref) was filed to close, surviving in the repos a # caller-presence check calls done. # # Measured 2026-08-27 before the fix: `design-system-v2`, `release-train` and `rfcs` @@ -78,7 +85,7 @@ name: Label-driven issue triage # # TWO LESSONS WORTH MORE THAN THE FIX, both about the DOMAIN and not the answer: # -# * `e2e-test-agent` was invisible to backend#2598 as filed, because that ticket +# * `e2e-test-agent` was invisible to (internal ref) as filed, because that ticket # derived over the `work-type:*` PREFIX. That repo had `work-type:bug` and # `priority` and none of the other five, so a prefix sweep called it covered # while four labels its templates apply were being dropped. Deriving from a @@ -101,7 +108,7 @@ jobs: if: github.event.label.name == 'from:customer' runs-on: ubuntu-latest steps: - # Authenticates as the tracebloc-release-train App (backend#2036) instead of + # Authenticates as the tracebloc-release-train App ((internal ref)) instead of # one human's PAT. This one needs `issues: write` -- it labels an issue in the # calling repo -- which the App gained alongside `organization_projects: write`. # `owner:` makes the token ORG-scoped so the same mint works for every caller. @@ -114,7 +121,7 @@ jobs: app-id: ${{ secrets.RELEASE_TRAIN_APP_ID }} private-key: ${{ secrets.RELEASE_TRAIN_APP_PRIVATE_KEY }} owner: ${{ github.repository_owner }} - # LEAST PRIVILEGE, DERIVED FROM THIS JOB'S ONE CALL (backend#2157). The + # LEAST PRIVILEGE, DERIVED FROM THIS JOB'S ONE CALL ((internal ref)). The # step below runs `gh issue edit --add-label priority` and nothing else: # it resolves the issue and the repo's label set (Issues read) and writes # the label (Issues write). `issues: write` subsumes both. @@ -126,7 +133,7 @@ jobs: # # `repositories:` is deliberately NOT narrowed, matching the reasoning on # the `bug-to-ready` mint below: repo narrowing is measured in this org - # for a READ (add-to-kanban.yml, backend#2181) and not for a WRITE, and an + # for a READ (add-to-kanban.yml, (internal ref)) and not for a WRITE, and an # unmeasured narrowing on a workflow that fires from every repo in the # fleet fails red on every customer-labelled issue. # @@ -146,7 +153,7 @@ jobs: # Priority single-select field has been removed from the board. # # THE TRIGGER LABEL'S OWN DESCRIPTION NOW SAYS SO TOO, and for months it - # said the opposite (backend#2743). All twenty enrolled repos advertised + # said the opposite ((internal ref)). All twenty enrolled repos advertised # `from:customer` as "auto-bumps Priority to P1" -- an outcome D5 deleted # and this step stopped producing -- so the label that fires the rule # promised a board value nobody would ever see. It was uniformly wrong @@ -164,13 +171,13 @@ jobs: # `triage-labels-check.py` (.github#364) asserts a triage label EXISTS in # every enrolled repo, not that its description still describes this step # -- which is exactly how the stale text survived D5 with a green fleet. - # backend#2744 closes that, on top of #364 rather than beside it, because + # (internal ref) closes that, on top of #364 rather than beside it, because # the file it extends is not on `develop` yet. gh issue edit "$ISSUE_NUMBER" --repo "$REPO_FULL" --add-label priority echo "-> Issue #$ISSUE_NUMBER labelled 'priority'" # --------------------------------------------------------------------------- - # A bug-labelled issue lands in `Ready`, not `Backlog` (backend#2348) + # A bug-labelled issue lands in `Ready`, not `Backlog` ((internal ref)) # --------------------------------------------------------------------------- # THE RULE, quoted from `org-standards.md`: "label them `work-type:bug` (the # Bug template does it) and the board moves the card straight into `Ready`". @@ -178,8 +185,8 @@ jobs: # Nothing implemented it. `add-to-kanban.yml` adds every new issue at # `Backlog` and no workflow read the label afterwards, so the rule was carried # by whoever remembered. Measured 2026-08-22: seven bug-labelled tickets filed - # in one day (backend#2324, #2327, #2329, #2340, #2341, #2344, - # frontend-app#871) all landed in `Backlog` and all seven needed a hand-run + # in one day ((internal ref), #2327, #2329, #2340, #2341, #2344, + # (internal ref)) all landed in `Backlog` and all seven needed a hand-run # mutation. A 100% miss rate is the tell that nothing does it at all -- a rule # people mostly follow produces a mixed record. # @@ -202,7 +209,7 @@ jobs: # App installation token minted below. permissions: {} steps: - # LEAST PRIVILEGE, DERIVED FROM WHAT THIS RUNS (backend#2157), unlike the + # LEAST PRIVILEGE, DERIVED FROM WHAT THIS RUNS ((internal ref)), unlike the # `bump` job above which still carries the App's full installation grant # (`mint-scope.py`'s EXEMPT row for this file is about that job, not this # one). This step reads one issue's project items and writes one @@ -212,7 +219,7 @@ jobs: # `repositories:` is deliberately NOT narrowed here. The board write needs # the ORG-level grant that `owner:` yields, and the interaction between repo # narrowing and an org ProjectV2 write is measured for a READ - # (kanban-columns.yml, backend#2181) and not for a write. An unmeasured + # (kanban-columns.yml, (internal ref)) and not for a write. An unmeasured # narrowing on a workflow that fires for every bug in the fleet fails red on # every defect filed, and this job's whole point is that a defect should not # need a human to notice it. @@ -324,7 +331,7 @@ jobs: # derived from, so reading it in the same response as the ids means the # decision and the write cannot be made against two different boards. # - # FAIL CLOSED on the read (backend#1729 rule 3): an unreadable board is + # FAIL CLOSED on the read ((internal ref) rule 3): an unreadable board is # not evidence that the card may move. # shellcheck disable=SC2016 # the $names are GraphQL variables, not shell - keep literal if ! PROJ=$(gh api graphql -f query=' @@ -364,7 +371,7 @@ jobs: | select(.name=="Status") | .id' <<< "$PROJ") # THE OPTION ID IS DERIVED, NEVER HELD. A stored `Ready` option id would # keep writing after the board changed under it, and writing the WRONG - # column is strictly worse than writing nothing (backend#2348). + # column is strictly worse than writing nothing ((internal ref)). TARGET_OPT=$(jq -r --arg s "$TARGET_COLUMN" '.data.organization.projectV2.fields.nodes[]? | select(.name=="Status") | .options[] | select(.name==$s) | .id' <<< "$PROJ") if [ -z "$PROJECT_ID" ] || [ "$PROJECT_ID" = "null" ] \ @@ -437,7 +444,7 @@ jobs: # FAIL CLOSED, LOUDLY, AND THE DIRECTION IS THE DECISION HERE. # # The three sibling consumers of the board chose their failure paths as a - # SET (backend#2243), and this one resembles `advance-deploy-env.yml`: no + # SET ((internal ref)), and this one resembles `advance-deploy-env.yml`: no # fallback, abort. `kanban-closure-router.yml` exits 0 on a card it cannot # find because declining to write is its conservative end state -- it is # protecting shipped state from being overwritten. Declining here is not @@ -465,7 +472,7 @@ jobs: # MONOTONIC. Automation in this org never moves a card backward, and the # direction is asked of the BOARD rather than restated here: a rank table # in this file would agree with itself while disagreeing with reality - # (backend#1729 rule 1). + # ((internal ref) rule 1). # # promote the card is at $SOURCE_COLUMN, or is on the board with no # Status at all. Those are the only two states from which @@ -486,7 +493,7 @@ jobs: # "promotion" a demotion. Checked FIRST, before the # no-Status shortcut, because a board that cannot be trusted # to be in pipeline order cannot be trusted for any card - # (backend#1994 is the same hole one file over: existence was + # ((internal ref) is the same hole one file over: existence was # checked and ORDER was not). promote_decision() { # $1=the card's current column $2=isArchived _s=$(col_index "${SOURCE_COLUMN}"); _t=$(col_index "${TARGET_COLUMN}") From 24fc2bbf41c5289dbdb28be53b0ef3d8fc6d86f0 Mon Sep 17 00:00:00 2001 From: lukasWuttke <54042461+LukasWodka@users.noreply.github.com> Date: Sun, 13 Sep 2026 11:37:32 +0200 Subject: [PATCH 05/12] chore(onboard): add .github/workflows/fr-gate.yml (content profile) --- .github/workflows/fr-gate.yml | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/fr-gate.yml b/.github/workflows/fr-gate.yml index 422efb4..b4fc96d 100644 --- a/.github/workflows/fr-gate.yml +++ b/.github/workflows/fr-gate.yml @@ -1,7 +1,7 @@ -# GENERATED FILE -- DO NOT EDIT BY HAND (tracebloc/backend#3591). +# GENERATED FILE -- DO NOT EDIT BY HAND. # # Self-contained copy of the reusable workflow `.github/workflows/fr-gate.yml` -# (blob 948ea255acb8ea4e4d7a259fe16fec2855ddac32) folded with tracebloc/org-config's own caller of it, +# (blob 97fcf6a3fb0bbb3ff46f3a3f2a9be7e471ae89ee) folded with tracebloc/org-config's own caller of it, # `.github/workflows/fr-gate-caller.yml` (blob b2e63da19a0d0369a7d7364b4596f53128f3c8ca), for a PUBLIC repo: GitHub lets a # public repo `uses:` a reusable workflow only from a public repo, and the # reusables live in the private tracebloc/org-config. So this file carries the @@ -15,6 +15,13 @@ # read-only App installation token; on a fork PR that token cannot be minted # (no secrets), so the checkout fails closed rather than running untrusted input. # +# PUBLIC SURFACE. This file is delivered to a public repo, so its comments carry +# no internal references: each one was replaced with `(internal ref)` by the +# one definition in scripts/public_surface.py (private-repo issue references, +# private repo names, RFC ids, tenant names). A reference anywhere outside a +# comment refuses the render instead of being edited -- it is a defect in the +# source, not a scrub target. +# # Regenerate: python3 scripts/render-self-contained.py (in tracebloc/org-config) # Verify: python3 scripts/render-self-contained.py --check (make selftest-self-contained) # @@ -96,7 +103,7 @@ jobs: run: | # Manual promotion PRs bypass the release train's Bugbot soft-gate, # its tagging, and its run records — and indirect-merge the train's - # own PRs (backend#1336 / averaging-service, 2026-07-29). Promotions + # own PRs ((internal ref) / averaging-service, 2026-07-29). Promotions # into staging/main/master are the train's job. Sanctioned lanes: # release-train/* the train's own mirror PRs # hotfix-backmerge/* hotfix.yml's automated back-merges @@ -108,7 +115,7 @@ jobs: if echo "$LABELS" | grep -q '"hotfix"'; then exit 0 fi - echo "::error::Manual promotion PRs are retired — promotions into this branch go through the release train (tracebloc/release-train → Actions → 'Release train'). For a single-repo emergency prod fix use the 'hotfix' label; 'skip-fr-gate' remains the audited full override." + echo "::error::Manual promotion PRs are retired — promotions into this branch go through the org's release train (a maintainer dispatches its 'Release train' workflow). For a single-repo emergency prod fix use the 'hotfix' label; 'skip-fr-gate' remains the audited full override." exit 1 - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -117,7 +124,7 @@ jobs: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha }} - # THE WALK LIVES HERE, NOT IN THE CALLING REPO (backend#3323, RFC-0075 D6). + # THE WALK LIVES HERE, NOT IN THE CALLING REPO ((internal ref), (internal ref) D6). # The two steps below used to carry it inline; the release train needs the # same walk to cut the prod hop at the FR frontier, and a second copy in # release-train is the drift rule 9 forbids. So the script is checked out @@ -150,7 +157,7 @@ jobs: path: .fr-gate-tools persist-credentials: false - # Authenticates as the tracebloc-release-train App (backend#2036) instead of a + # Authenticates as the tracebloc-release-train App ((internal ref)) instead of a # human's PAT. `owner:` yields an ORG-scoped installation token, which this gate # needs: it reads the org PROJECT, and a repo-scoped token cannot. # @@ -172,7 +179,7 @@ jobs: app-id: ${{ secrets.RELEASE_TRAIN_APP_ID }} private-key: ${{ secrets.RELEASE_TRAIN_APP_PRIVATE_KEY }} owner: ${{ github.repository_owner }} - # THREE READS AND NOTHING ELSE (backend#2157). Without these it minted + # THREE READS AND NOTHING ELSE ((internal ref)). Without these it minted # the App's whole set -- contents:write, issues:write, # organization_projects:write, administration:read -- across every repo # the installation covers, to run a gate that writes nothing at all. From c5db693bace349f550e762525d3de2b62b94fa25 Mon Sep 17 00:00:00 2001 From: lukasWuttke <54042461+LukasWodka@users.noreply.github.com> Date: Sun, 13 Sep 2026 11:37:34 +0200 Subject: [PATCH 06/12] chore(onboard): add .github/workflows/fr-pass-comment.yml (content profile) --- .github/workflows/fr-pass-comment.yml | 29 +++++++++++++++++---------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/.github/workflows/fr-pass-comment.yml b/.github/workflows/fr-pass-comment.yml index 5ca4e5d..265b6ad 100644 --- a/.github/workflows/fr-pass-comment.yml +++ b/.github/workflows/fr-pass-comment.yml @@ -1,4 +1,4 @@ -# GENERATED FILE -- DO NOT EDIT BY HAND (tracebloc/backend#3591). +# GENERATED FILE -- DO NOT EDIT BY HAND. # # Self-contained copy of the reusable workflow `.github/workflows/fr-pass-comment.yml` # (blob 5b74b698d095e29a4a20f50d64576029bab31860) folded with tracebloc/org-config's own caller of it, @@ -15,6 +15,13 @@ # read-only App installation token; on a fork PR that token cannot be minted # (no secrets), so the checkout fails closed rather than running untrusted input. # +# PUBLIC SURFACE. This file is delivered to a public repo, so its comments carry +# no internal references: each one was replaced with `(internal ref)` by the +# one definition in scripts/public_surface.py (private-repo issue references, +# private repo names, RFC ids, tenant names). A reference anywhere outside a +# comment refuses the render instead of being edited -- it is a defect in the +# source, not a scrub target. +# # Regenerate: python3 scripts/render-self-contained.py (in tracebloc/org-config) # Verify: python3 scripts/render-self-contained.py --check (make selftest-self-contained) # @@ -30,7 +37,7 @@ name: FR pass comment handler # (D6: the dev-side review is gone — "On dev" is automatic — so /fr-pass only # applies at staging, the single functional-review gate.) # -# NEVER NO-OP IN SILENCE (backend#1319) +# NEVER NO-OP IN SILENCE ((internal ref)) # Every terminating path below leaves a signal on the thread: 👍 when the card # moved, 👎 plus a one-paragraph comment saying why when it did not. The single # deliberate exception is a comment that merely *mentions* the string without @@ -44,7 +51,7 @@ name: FR pass comment handler # about /fr-pass" filter; authorisation, self-signoff, board membership and the # column check all happen in steps that can report. # -# A REFUSAL IS NOT A SUCCESS (backend#1413) +# A REFUSAL IS NOT A SUCCESS ((internal ref)) # Exactly three outcomes exit 0 — `advanced`, `already-advanced` and # `not-a-command`. EVERY other terminating path exits 1, including # `not-authorised`, `self-signoff`, `not-on-project`, `ambiguous-item`, @@ -94,7 +101,7 @@ jobs: # that never gets in can never be reported. The precise match lives in the # step. # - # The other two stop this handler answering itself (backend#1413). Every + # The other two stop this handler answering itself ((internal ref)). Every # refusal note below contains the literal string `/fr-pass`, so posting one # re-fired this workflow — 6 of the 26 runs on 2026-08-01 were the bot reading # its own comment. That only ever terminated because the step's anchored grep @@ -124,7 +131,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 5 steps: - # Authenticates as the tracebloc-release-train App (backend#2036) instead of + # Authenticates as the tracebloc-release-train App ((internal ref)) instead of # one human's PAT. Needs BOTH grants: `organization_projects: write` to advance # the card and `issues: write` to post the outcome comment and its reaction. # `owner:` makes the token ORG-scoped -- a repo-scoped one cannot reach an org @@ -137,7 +144,7 @@ jobs: app-id: ${{ secrets.RELEASE_TRAIN_APP_ID }} private-key: ${{ secrets.RELEASE_TRAIN_APP_PRIVATE_KEY }} owner: ${{ github.repository_owner }} - # LEAST PRIVILEGE, DERIVED FROM THIS JOB'S OWN CALLS (backend#2157). + # LEAST PRIVILEGE, DERIVED FROM THIS JOB'S OWN CALLS ((internal ref)). # Two steps share this token and between them make six calls; this is the # union, with the permission each one documents: # @@ -201,7 +208,7 @@ jobs: # Publish an outcome on EVERY exit, including an unplanned one. The # reporting step keys off this one output, so a crash halfway through # (API error, jq error, a `set -e` trip) still produces a 👎 and an - # explanation rather than the silence reported in backend#1319. + # explanation rather than the silence reported in (internal ref). publish() { if [ ! -s "$RESULT_FILE" ]; then printf 'internal-error' > "$RESULT_FILE" @@ -296,7 +303,7 @@ jobs: fi # ----------------------------------------- 3. self sign-off (D30) - # THE bug from backend#1319 lived here, as a clause in the job-level + # THE bug from (internal ref) lived here, as a clause in the job-level # `if`: when the reviewer was also the PR author the whole job was # skipped, so no step was left to react or explain. 8 of the 13 # /fr-pass comments on 2026-07-29 died exactly this way. The rule is @@ -420,10 +427,10 @@ jobs: CURRENT=$(printf '%s' "$NODES" | jq -r '.[0].fieldValueByName.name // ""') # The two column names below are hard-coded, and this board has been - # renamed before (RFC-BACKEND-0008 collapsed the dev-side FR columns). + # renamed before ((internal ref) collapsed the dev-side FR columns). # Check they still exist, so the next rename fails loudly here instead # of reporting "wrong column" for every card on the board. - # Rename window (backend#1592): the staging-review column is "Staging + # Rename window ((internal ref)): the staging-review column is "Staging # (human review)" after the UI rename and "FR on staging" before it, and # the rename is a single instant with no overlap. So resolve it to # whichever exists and keep the loud failure for the case where NEITHER @@ -577,7 +584,7 @@ jobs: # clean advance stays a bare 👍 so the happy path keeps the thread quiet. if [ -s "$NOTE_FILE" ]; then # Prepend the marker the job `if` tests for, so this handler can - # recognise its own notes and not answer them (backend#1413). Added + # recognise its own notes and not answer them ((internal ref)). Added # here, at the single place a note is posted, rather than in each # `decide` call above — a note that forgets it would resurrect the # loop. First line, because the job `if` uses startsWith. HTML From 7d54100ae253f62455a093fb94d310dec22160bc Mon Sep 17 00:00:00 2001 From: lukasWuttke <54042461+LukasWodka@users.noreply.github.com> Date: Sun, 13 Sep 2026 11:37:35 +0200 Subject: [PATCH 07/12] chore(onboard): add .github/workflows/kanban-closure-router.yml (content profile) --- .github/workflows/kanban-closure-router.yml | 63 ++++++++++++--------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/.github/workflows/kanban-closure-router.yml b/.github/workflows/kanban-closure-router.yml index 0d57ef2..3409b62 100644 --- a/.github/workflows/kanban-closure-router.yml +++ b/.github/workflows/kanban-closure-router.yml @@ -1,7 +1,7 @@ -# GENERATED FILE -- DO NOT EDIT BY HAND (tracebloc/backend#3591). +# GENERATED FILE -- DO NOT EDIT BY HAND. # # Self-contained copy of the reusable workflow `.github/workflows/kanban-closure-router.yml` -# (blob 7ffe4b4c69900fa358142def93c524667350cdda) folded with tracebloc/org-config's own caller of it, +# (blob fa2c75bfff00979330c8f5d42d9147d0da739acc) folded with tracebloc/org-config's own caller of it, # `.github/workflows/kanban-closure-caller.yml` (blob e78122f771274190cbfcc450ccfce7ada2ff077a), for a PUBLIC repo: GitHub lets a # public repo `uses:` a reusable workflow only from a public repo, and the # reusables live in the private tracebloc/org-config. So this file carries the @@ -15,6 +15,13 @@ # read-only App installation token; on a fork PR that token cannot be minted # (no secrets), so the checkout fails closed rather than running untrusted input. # +# PUBLIC SURFACE. This file is delivered to a public repo, so its comments carry +# no internal references: each one was replaced with `(internal ref)` by the +# one definition in scripts/public_surface.py (private-repo issue references, +# private repo names, RFC ids, tenant names). A reference anywhere outside a +# comment refuses the render instead of being edited -- it is a defect in the +# source, not a scrub target. +# # Regenerate: python3 scripts/render-self-contained.py (in tracebloc/org-config) # Verify: python3 scripts/render-self-contained.py --check (make selftest-self-contained) # @@ -31,7 +38,7 @@ name: Route kanban Status on closure # - PR closed without merging → Cancelled # - Issue closed as completed → Done (terminal; how it was closed is irrelevant) # (was: mirror the closing PR's Status, which put finished issues in deploy -# columns — see the branch below and backend#2722) +# columns — see the branch below and (internal ref)) # - Issue closed as not_planned → Cancelled # - Issue closed (no state_reason) → Cancelled (default to abandoned) # @@ -53,7 +60,7 @@ jobs: runs-on: ubuntu-latest steps: # The mapping comes from .github, not from a copy in this file: one - # definition of branch -> Status (backend#2243). + # definition of branch -> Status ((internal ref)). - name: Mint a read-only token for org-config (private; the caller's own token cannot read it) id: org-config-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 @@ -72,14 +79,14 @@ jobs: path: .kanban-map persist-credentials: false - # Authenticates as the tracebloc-release-train App (backend#2036) instead of + # Authenticates as the tracebloc-release-train App ((internal ref)) instead of # one human's PAT. Needs both grants: `organization_projects: write` for the # card, `issues: write` for the sibling-merge label and the closure comment. # `owner:` makes the token ORG-scoped -- a repo-scoped one cannot reach an org # ProjectV2, and the closer lookup below is cross-repo besides. # # No fallback to the old PAT: a fallback would let a broken App path look like - # a working migration, which is the defect class backend#1680 exists to remove. + # a working migration, which is the defect class (internal ref) exists to remove. - name: Mint an installation token id: app-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 @@ -87,7 +94,7 @@ jobs: app-id: ${{ secrets.RELEASE_TRAIN_APP_ID }} private-key: ${{ secrets.RELEASE_TRAIN_APP_PRIVATE_KEY }} owner: ${{ github.repository_owner }} - # LEAST PRIVILEGE, DERIVED FROM THIS JOB'S OWN CALLS (backend#2157). + # LEAST PRIVILEGE, DERIVED FROM THIS JOB'S OWN CALLS ((internal ref)). # Four steps share this token; this is the union of what they call: # # organization().projectV2 fields/options projects read @@ -129,7 +136,7 @@ jobs: # client or website PR routinely closes a `backend` issue), and # `organization-projects` is an org-level grant regardless. The closer # lookup used to be cited here too; it was removed with the routing change - # (backend#2722) and is no longer a reason for anything. + # ((internal ref)) and is no longer a reason for anything. # # NOT PROVEN BY READING. An under-scoped token fails at the call site, and # this workflow's failure mode is a card the built-in "Item closed" @@ -154,13 +161,13 @@ jobs: # without them `set -u` aborts the script before any status= output is # written, leaving the built-in "Item closed" project workflow to set # Status=Cancelled. (They were originally added for the closing-PR-base - # lookup, which backend#2722 removed; the other consumers remain.) + # lookup, which (internal ref) removed; the other consumers remain.) ORG: ${{ 'tracebloc' }} REPO_FULL: ${{ github.repository }} # The PAT rather than the caller's GITHUB_TOKEN: this step's project reads # and the override mapper are cross-repo. (This comment used to explain a # closer lookup that ran tokenless and therefore never worked -- .github#126. - # backend#2722 removed the lookup entirely, so that history now describes no + # (internal ref) removed the lookup entirely, so that history now describes no # code and is dropped rather than left to mislead.) GH_TOKEN: ${{ steps.app-token.outputs.token }} run: | @@ -176,7 +183,7 @@ jobs: # the same visibility mechanism as SIBLING: a card the weekly pass must # disposition, marked so a human can see why. # - # UNUSABLE, NOT UNREADABLE (backend#2324). Two causes reach this holding + # UNUSABLE, NOT UNREADABLE ((internal ref)). Two causes reach this holding # state now -- a `.kanban.yml` that cannot be fetched or parsed, and one # that reads fine but names a Status the mapping does not declare -- and # the second sends an operator hunting a read failure that never happened. @@ -184,7 +191,7 @@ jobs: UNUSABLE_OVERRIDE="false" if [ "$EVENT_NAME" = "pull_request" ]; then if [ "$PR_MERGED" = "true" ]; then - # ONE SHARED MAPPING (backend#2243) -- and this site is why the fix + # ONE SHARED MAPPING ((internal ref)) -- and this site is why the fix # is a shared script rather than a second `yq` read: this workflow # never checks the caller out, so the per-repo `.kanban.yml` override # it was silently ignoring has to be FETCHED, not read off disk. @@ -198,7 +205,7 @@ jobs: # door -- and the door opens on any repo whose override cannot be # read, which is not a hypothetical population. # - # `resolve` REFUSES HERE TOO NOW (backend#2324), on an override naming + # `resolve` REFUSES HERE TOO NOW ((internal ref)), on an override naming # a Status the mapping does not declare. That case used to succeed and hand # this arm a name the update step below cannot resolve to an option id # -- so it aborted mid-write and reached the same "Item closed" branch @@ -240,7 +247,7 @@ jobs: # A PR merged into a SIBLING feature branch deploys nothing by # itself — its content travels onward inside the parent PR # (this fallthrough silently stranded 6 such cards; - # backend#1437 mechanism 1). The sibling-merge label below + # (internal ref) mechanism 1). The sibling-merge label below # makes the condition VISIBLE for the weekly board pass. The # Status write is deliberately KEPT: skipping it lets the # project's built-in "Item closed" automation set closed items @@ -256,18 +263,18 @@ jobs: elif [ "$EVENT_NAME" = "issues" ]; then if [ "$ISSUE_REASON" = "completed" ]; then # A COMPLETED ISSUE IS TERMINAL. It goes to Done, and nothing about how it - # was closed changes that (backend#2722). + # was closed changes that ((internal ref)). # # This used to mirror the closing PR's Status, so a PR-closed issue landed # in `On dev` / `FR on staging` / `Prod`. That contradicted the board model # -- deploy state is a property of a PR; an issue is either finished or it - # is not (RFC-BACKEND-1405 D8) -- and it cost real accuracy: on 2026-08-27 + # is not ((internal ref) D8) -- and it cost real accuracy: on 2026-08-27 # one session cleared 117 closed issues out of deploy columns by hand # (18 + 55 from `FR on staging`, 44 from `On dev`). Two of those passes # were functional-review batches, so the next prod payload would have read # 73 items larger than the work it actually contained. # - # WHY THIS RETIRES backend#1600 RATHER THAN FIGHTING IT. #1600 found that + # WHY THIS RETIRES (internal ref) RATHER THAN FIGHTING IT. #1600 found that # issues parked here by the old mirroring NEVER advanced when the code # shipped, and drifted permanently (2026-08-06: all 20 drifted cards were # closed issues, 0 PRs). It fixed the stranding by teaching @@ -311,7 +318,7 @@ jobs: } >> "$GITHUB_OUTPUT" echo "Routing decision: status=${STATUS:-(unchanged)} sibling=$SIBLING unusable-override=$UNUSABLE_OVERRIDE" - # Visibility for backend#1437 mechanism 1. Runs AFTER the Status update + # Visibility for (internal ref) mechanism 1. Runs AFTER the Status update # so a label failure can never suppress the column write - with the label # first, its hard-fail skipped the update via the implicit success() # condition and left the card wherever the built-in automation put it @@ -369,7 +376,7 @@ jobs: # Retry briefly to let auto-add fire if needed. # # A FAILED LOOKUP IS NOT AN ABSENT CARD -- the same class as - # advance-deploy-env's per-PR read (Bugbot, org-config#3). This used to + # advance-deploy-env's per-PR read (Bugbot, (internal ref)). This used to # be `... 2>/dev/null) || RESP='{}'`, so five rate-limited reads in a # row read as "not on project after 5 retries", exit 0, and the card # kept a Status the merge had just made false while the run stayed @@ -422,7 +429,7 @@ jobs: # # Only Done is guarded. A PR-derived Status is a deploy fact and may advance a # card normally. - # WHICH COLUMNS ARE DEPLOY STATES, ASKED OF THE BOARD (backend#1846). + # WHICH COLUMNS ARE DEPLOY STATES, ASKED OF THE BOARD ((internal ref)). # # This was a hand-maintained list of six names, duplicated in # kanban-reconcile.yml -- and it had already rotted once: it carried the @@ -450,7 +457,7 @@ jobs: # Is this column a DEPLOY STATE? Answered from the board's own ORDER -- # any column at or after "On dev" and at or before "Prod" -- so a column # INSERTED between them is classified correctly with no edit here - # (backend#1846). Only `col_index` differs between the two workflows, + # ((internal ref)). Only `col_index` differs between the two workflows, # because only their inputs differ; this decision must not. # # yes a deploy state @@ -465,7 +472,7 @@ jobs: # included -- comes back `no`, the router writes Done over # shipped state and reconcile asserts it. A reordered board is # UNREADABLE, not evidence that nothing deployed, so it fails - # closed exactly like a missing anchor (backend#1994). + # closed exactly like a missing anchor ((internal ref)). classify_column() { case "${1:-}" in ""|"No status") echo no; return ;; @@ -499,12 +506,12 @@ jobs: # AND SAY SO WHERE SOMEONE WILL SEE IT. Refusing is right, but it # parks the card with no way to self-heal, and a run-log notice is # invisible by the time anyone looks at the board. The two real - # cases needed OPPOSITE answers -- backend#1493 had shipped via + # cases needed OPPOSITE answers -- (internal ref) had shipped via # cli#452 and belonged in Prod; data-ingestors#488 was reverted and # belonged in Done -- so no default is correct and only the person # closing it knows which. CLOSE_NOTE="Closed while the board still shows \`$CURRENT_COL\`, which records a deployment." - CLOSE_NOTE="$CLOSE_NOTE The automation will not overwrite a deploy state with \`Done\` (RFC-BACKEND-1405 D8)," + CLOSE_NOTE="$CLOSE_NOTE The automation will not overwrite a deploy state with \`Done\`," CLOSE_NOTE="$CLOSE_NOTE so this card stays where it is until someone says which happened:" CLOSE_NOTE="$CLOSE_NOTE **it shipped** - move the card to the column it reached (\`Prod\` if it is in production);" CLOSE_NOTE="$CLOSE_NOTE **nothing was deployed** (reverted, abandoned, superseded) - clear the deploy state, then \`Done\`." @@ -535,12 +542,12 @@ jobs: set -euo pipefail # Same write rule as the sibling label below: a swallowed failure means the # card silently loses the only marker saying its Status is a placeholder. - # `override-unusable`, not `override-unreadable` (backend#2324): the label + # `override-unusable`, not `override-unreadable` ((internal ref)): the label # is the operator's entry point, and a card can now reach this state with a # `.kanban.yml` that read perfectly and named a column that does not exist. # # NOTHING TO MIGRATE, AND THE REASON IS MEASURED RATHER THAN INFERRED - # (backend#2801). This used to rest on a claim that the fleet had no + # ((internal ref)). This used to rest on a claim that the fleet had no # adopters of the override at all, which stopped being true. The # CONCLUSION survives on its own evidence: `override-unreadable` is # carried by ZERO issues or PRs org-wide (measured 2026-08-28), so there @@ -555,7 +562,7 @@ jobs: # step, and the parked card never gets the marker this holding state exists # to leave. My first wording was 133. The selftest measures it now. if ! gh api "repos/$REPO_FULL/labels/override-unusable" >/dev/null 2>&1; then - gh api "repos/$REPO_FULL/labels" -f name=override-unusable -f color=d4c5f9 -f description="Holding state: .kanban.yml unreadable, or names an undeclared Status (backend#2324)" >/dev/null + gh api "repos/$REPO_FULL/labels" -f name=override-unusable -f color=d4c5f9 -f description="Holding state: .kanban.yml unreadable, or names an undeclared Status" >/dev/null fi gh api -X POST "repos/$REPO_FULL/issues/$NUMBER/labels" -f "labels[]=override-unusable" >/dev/null @@ -572,6 +579,6 @@ jobs: # visibility marker (Bugbot, .github#157). Only the ensure-label # probe may miss quietly - a 404 there just means create it. if ! gh api "repos/$REPO_FULL/labels/sibling-merge" >/dev/null 2>&1; then - gh api "repos/$REPO_FULL/labels" -f name=sibling-merge -f color=bfdadc -f description="Merged into a sibling feature branch; content ships via the parent PR (backend#1437)" >/dev/null + gh api "repos/$REPO_FULL/labels" -f name=sibling-merge -f color=bfdadc -f description="Merged into a sibling feature branch; content ships via the parent PR" >/dev/null fi gh api -X POST "repos/$REPO_FULL/issues/$NUMBER/labels" -f "labels[]=sibling-merge" >/dev/null From 4581dafa9a071f88b780bbcf11f9b0864b5532ad Mon Sep 17 00:00:00 2001 From: lukasWuttke <54042461+LukasWodka@users.noreply.github.com> Date: Sun, 13 Sep 2026 11:37:37 +0200 Subject: [PATCH 08/12] chore(onboard): add .github/workflows/set-pr-status.yml (content profile) --- .github/workflows/set-pr-status.yml | 47 +++++++++++++++++------------ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/.github/workflows/set-pr-status.yml b/.github/workflows/set-pr-status.yml index 444b171..1d5be08 100644 --- a/.github/workflows/set-pr-status.yml +++ b/.github/workflows/set-pr-status.yml @@ -1,4 +1,4 @@ -# GENERATED FILE -- DO NOT EDIT BY HAND (tracebloc/backend#3591). +# GENERATED FILE -- DO NOT EDIT BY HAND. # # Self-contained copy of the reusable workflow `.github/workflows/set-pr-status.yml` # (blob 953b8bb9bbc8675586987c39bbbd853da18c508c) folded with tracebloc/org-config's own caller of it, @@ -15,6 +15,13 @@ # read-only App installation token; on a fork PR that token cannot be minted # (no secrets), so the checkout fails closed rather than running untrusted input. # +# PUBLIC SURFACE. This file is delivered to a public repo, so its comments carry +# no internal references: each one was replaced with `(internal ref)` by the +# one definition in scripts/public_surface.py (private-repo issue references, +# private repo names, RFC ids, tenant names). A reference anywhere outside a +# comment refuses the render instead of being edited -- it is a defect in the +# source, not a scrub target. +# # Regenerate: python3 scripts/render-self-contained.py (in tracebloc/org-config) # Verify: python3 scripts/render-self-contained.py --check (make selftest-self-contained) # @@ -24,13 +31,13 @@ name: Set PR card Status on project # Reusable workflow. Called from each active repo on PR open / reopen / -# draft-toggle / title-or-body edit (`edited`, added under tracebloc/backend#2556 +# draft-toggle / title-or-body edit (`edited`, added under (internal ref) # so the `closing-ref` job re-runs when the fields it reads change). # Moves the PR's card to the right Status: # - draft PR → In progress # - non-draft → Code review # -# TWO JOBS, and the second one is here on purpose (tracebloc/backend#2364). +# TWO JOBS, and the second one is here on purpose ((internal ref)). # # set-status writes the card's Status (below) # closing-ref checks that a PR whose TITLE names a ticket actually LINKS it @@ -39,7 +46,7 @@ name: Set PR card Status on project # Three constraints, and this file is the only host that satisfies all three: # # 1. It needs a token that can read the PR *and* an issue in ANOTHER repo -- -# almost every house ticket is in `tracebloc/backend`, and nearly every repo +# almost every house ticket is in `(internal ref)`, and nearly every repo # is private. This file already mints an ORG-SCOPED installation token for # the `tracebloc-release-train` App (measured 2026-08-23: `issues: write`, # `pull_requests: write`, `repository_selection: all`), and every one of its @@ -66,7 +73,7 @@ name: Set PR card Status on project on: pull_request: - # `edited` is load-bearing, not decoration (tracebloc/backend#2556). The + # `edited` is load-bearing, not decoration ((internal ref)). The # `closing-ref` job decides its verdict from the PR TITLE and the PR BODY, and # `edited` is the ONLY event GitHub fires when either changes. Without it the # two fields the gate reads are the two fields that can change without @@ -78,20 +85,20 @@ on: # It also makes the remediation usable at all. Retitling or editing a body to # SATISFY the gate did not re-run it either, so a red persisted on a PR that # now complied: 20 sync PRs had to be cleared with 20 manual `gh run rerun` - # calls (backend#2555), because the only in-band re-trigger was closing and + # calls ((internal ref)), because the only in-band re-trigger was closing and # reopening someone else's PR. # - # Same one-word fix, same reason, as `fr-gate-caller.yml` (backend#1945): a + # Same one-word fix, same reason, as `fr-gate-caller.yml` ((internal ref)): a # gate whose verdict depends on a mutable field must re-run when that field # mutates. types: [opened, reopened, ready_for_review, converted_to_draft, edited] -# ONE RUN PER PR WINS, AND IT IS THE NEWEST (backend#2767). +# ONE RUN PER PR WINS, AND IT IS THE NEWEST ((internal ref)). # # Every trigger this file answers can fire twice in quick succession -- a # title fixed straight after a body edit, a ready_for_review immediately # after an edit -- and `edited` made that ordinary rather than rare: the -# 19-PR sweep for backend#2756 armed `edited` on all 20 callers, so what +# 19-PR sweep for (internal ref) armed `edited` on all 20 callers, so what # was latent on one repo is now live fleet-wide. # # Without a group the runs race and the LOSER writes last: an older @@ -156,7 +163,7 @@ concurrency: cancel-in-progress: false jobs: - # ONLY WHILE THE PR IS OPEN (tracebloc/backend#2556). This condition is a + # ONLY WHILE THE PR IS OPEN ((internal ref)). This condition is a # DIRECT CONSEQUENCE of adding `edited` to the callers, and it is not optional. # # Before `edited`, every trigger this workflow had -- opened, reopened, @@ -188,7 +195,7 @@ jobs: fi # Board writes authenticate as the tracebloc-release-train App, not a human's - # PAT (backend#2036). The App's installation budget is separate from any + # PAT ((internal ref)). The App's installation budget is separate from any # person's interactive `gh` usage and does not vanish when someone is # offboarded -- `PROJECTS_KANBAN_TOKEN` was ONE user PAT shared by every # caller in the fleet, both crons, and that person's own shell, and it was @@ -207,11 +214,11 @@ jobs: app-id: ${{ secrets.RELEASE_TRAIN_APP_ID }} private-key: ${{ secrets.RELEASE_TRAIN_APP_PRIVATE_KEY }} owner: ${{ github.repository_owner }} - # SCOPED TO WHAT THIS JOB ACTUALLY DOES (backend#2157). Without these + # SCOPED TO WHAT THIS JOB ACTUALLY DOES ((internal ref)). Without these # it minted the App's ENTIRE permission set -- contents:write, # issues:write, administration:read and the rest -- across every repo # the installation covers, on every PR event in the fleet. Of the four - # mints backend#2157 left, this one has the largest exposure purely + # mints (internal ref) left, this one has the largest exposure purely # because of how often it runs. # # DERIVED FROM THE CALLS BELOW rather than copied from a template: @@ -281,13 +288,13 @@ jobs: sleep 5 done - # FAIL CLOSED (backend#2037). This used to log the miss and `exit 0`, so a + # FAIL CLOSED ((internal ref)). This used to log the miss and `exit 0`, so a # PR that lost the add-to-kanban race stayed at No Status behind a GREEN # check -- nothing surfaced it, and the board's "no card sits at No Status" - # invariant was broken by the workflow that reports it upheld. backend#1950 + # invariant was broken by the workflow that reports it upheld. (internal ref) # lost that race by four seconds and sat unnoticed. # - # THE MEASUREMENT THAT BUDGET WAS HELD OPEN FOR HAS ARRIVED (backend#2731). + # THE MEASUREMENT THAT BUDGET WAS HELD OPEN FOR HAS ARRIVED ((internal ref)). # The previous note kept the retry budget at 5 x 5s on purpose -- "widening # it would hide how often the race is actually lost, and the point of # failing closed is to find that out." The answer came back on 2026-08-27: @@ -353,7 +360,7 @@ jobs: echo "→ PR #$PR_NUMBER → Status=$STATUS_NAME" # ------------------------------------------------------------------------ - # A PR whose TITLE names a ticket must LINK it (tracebloc/backend#2364). + # A PR whose TITLE names a ticket must LINK it ((internal ref)). # # Measured 2026-08-23: `closingIssuesReferences` was 0 on 7 of 7 epic-relevant # merged PRs. The house convention puts the ticket in the TITLE; GitHub creates @@ -410,14 +417,14 @@ jobs: persist-credentials: false # WHY AN APP TOKEN AND NOT `github.token`. The link this reads points at an - # issue in ANOTHER repo -- `tracebloc/backend` for most of the fleet -- and + # issue in ANOTHER repo -- `(internal ref)` for most of the fleet -- and # a repo-scoped GITHUB_TOKEN cannot see it. A node the token cannot read # comes back missing from `nodes` while `totalCount` still counts it, which # the checker reports as "cannot tell" rather than "not linked". That is the # right refusal, but it would be EVERY cross-repo PR's verdict, so the # token has to be the org-scoped one. # - # SCOPED, unlike the mint in `set-status` above (backend#2157): this job + # SCOPED, unlike the mint in `set-status` above ((internal ref)): this job # reads two things and needs nothing else. `set-pr-status.yml` keeps its # `mint-scope` exemption for the unscoped board-write mint above; this mint # does not use it. @@ -430,7 +437,7 @@ jobs: owner: ${{ github.repository_owner }} permission-pull-requests: read permission-issues: read - # NO `contents` scope, on purpose (backend#3240). The gate used to read + # NO `contents` scope, on purpose ((internal ref)). The gate used to read # `baseRepository { defaultBranchRef { name } }` over GraphQL; a Ref is # a contents object, world-readable on a public repo and gated on a # private one, and from 2026-09-06 06:29Z that single field made every From 084b49ff35a9879acbfaf2811ef1c189111b5f90 Mon Sep 17 00:00:00 2001 From: lukasWuttke <54042461+LukasWodka@users.noreply.github.com> Date: Sun, 13 Sep 2026 11:37:38 +0200 Subject: [PATCH 09/12] chore(onboard): add .github/workflows/stale-backlog.yml (content profile) --- .github/workflows/stale-backlog.yml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/stale-backlog.yml b/.github/workflows/stale-backlog.yml index 69f4c67..5da5026 100644 --- a/.github/workflows/stale-backlog.yml +++ b/.github/workflows/stale-backlog.yml @@ -1,4 +1,4 @@ -# GENERATED FILE -- DO NOT EDIT BY HAND (tracebloc/backend#3591). +# GENERATED FILE -- DO NOT EDIT BY HAND. # # Self-contained copy of the reusable workflow `.github/workflows/stale-backlog.yml` # (blob bcb6d3bf15af1d8b1c422f5173d5a6c1b21860a6) folded with tracebloc/org-config's own caller of it, @@ -15,6 +15,13 @@ # read-only App installation token; on a fork PR that token cannot be minted # (no secrets), so the checkout fails closed rather than running untrusted input. # +# PUBLIC SURFACE. This file is delivered to a public repo, so its comments carry +# no internal references: each one was replaced with `(internal ref)` by the +# one definition in scripts/public_surface.py (private-repo issue references, +# private repo names, RFC ids, tenant names). A reference anywhere outside a +# comment refuses the render instead of being edited -- it is a defect in the +# source, not a scrub target. +# # Regenerate: python3 scripts/render-self-contained.py (in tracebloc/org-config) # Verify: python3 scripts/render-self-contained.py --check (make selftest-self-contained) # @@ -24,7 +31,7 @@ name: Close stale backlog issues # REUSABLE, and it had to become one before the bug could be fixed -# (backend#1979 → backend#1597 item 1). +# ((internal ref) → (internal ref) item 1). # # THE BUG: `actions/stale` exempts on LABELS ONLY. It has no concept of the board, # so an item in `North Stars`, `Ready for prod` or `In progress` went stale and @@ -79,13 +86,13 @@ jobs: timeout-minutes: 15 steps: # The board read needs org-project access and the writes need issues:write, - # both of which the tracebloc-release-train App holds (backend#2036). This + # both of which the tracebloc-release-train App holds ((internal ref)). This # workflow is App-native from the start and never had a PAT to migrate off. # `owner:` makes the token ORG-scoped; a repo-scoped one cannot read the # project at all, and this sweep would then skip every issue as UNKNOWN — # silent and safe, but wrong. # - # SCOPED FROM THE START (backend#2157), derived from what the sweep actually + # SCOPED FROM THE START ((internal ref)), derived from what the sweep actually # calls rather than from what the App happens to hold: # # issues: write `issue edit --add-label`, `issue comment`, @@ -94,7 +101,7 @@ jobs: # sweep never writes a board field # # No `pull-requests` — this workflow does not touch PRs, by design - # (backend#1408: it sweeps issues only). No `contents` — the App token is used + # ((internal ref): it sweeps issues only). No `contents` — the App token is used # ONLY as `GH_TOKEN` for the sweep; the `.github` checkout below uses the # workflow token and `persist-credentials: false`. # @@ -104,7 +111,7 @@ jobs: # while only ever closing in one. # # ORG PROJECTS IS UNAFFECTED BY REPO SCOPING -- measured, not assumed: - # backend#2181's verification run (32255581084) wrote the org project with + # (internal ref)'s verification run (32255581084) wrote the org project with # `repositories:` set. That was the load-bearing unknown and it is settled. - name: Mint an installation token id: app-token From af11e5d8fb1c59a6ce453778a23e4e1042e68d20 Mon Sep 17 00:00:00 2001 From: lukasWuttke <54042461+LukasWodka@users.noreply.github.com> Date: Sun, 13 Sep 2026 11:37:39 +0200 Subject: [PATCH 10/12] chore(onboard): add .github/workflows/add-to-kanban.yml (content profile) --- .github/workflows/add-to-kanban.yml | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/.github/workflows/add-to-kanban.yml b/.github/workflows/add-to-kanban.yml index 2a3a432..bbdde83 100644 --- a/.github/workflows/add-to-kanban.yml +++ b/.github/workflows/add-to-kanban.yml @@ -1,3 +1,21 @@ +# GENERATED FILE -- DO NOT EDIT BY HAND. +# +# Public-safe copy of `.github/workflows/add-to-kanban.yml` (blob 2a3a432b3d01516575d5c57b9d0a1b2379db299d) for a PUBLIC repo: +# the same workflow, byte for byte, except that its comments are scrubbed as +# described below. Private repos carry the original; the conformance audit +# compares a public repo's copy against THIS file and a private repo's +# against the original. +# +# PUBLIC SURFACE. This file is delivered to a public repo, so its comments carry +# no internal references: each one was replaced with `(internal ref)` by the +# one definition in scripts/public_surface.py (private-repo issue references, +# private repo names, RFC ids, tenant names). A reference anywhere outside a +# comment refuses the render instead of being edited -- it is a defect in the +# source, not a scrub target. +# +# Regenerate: python3 scripts/render-self-contained.py (in tracebloc/org-config) +# Verify: python3 scripts/render-self-contained.py --check (make selftest-self-contained) + name: Add to engineer kanban on: @@ -15,7 +33,7 @@ jobs: # privilege story covers both credentials in the job rather than just the loud one. permissions: {} steps: - # Board writes authenticate as the tracebloc-release-train App (backend#2036), + # Board writes authenticate as the tracebloc-release-train App ((internal ref)), # not a human's PAT. `owner:` yields an ORG-scoped installation token; a # repo-scoped one cannot write the org project. No fallback to the PAT: a # fallback would let a broken App path keep working silently. @@ -44,7 +62,7 @@ jobs: # comment. If it is wrong the failure is LOUD (see below), which is what # makes trying it cheap. repositories: ${{ github.event.repository.name }} - # Least privilege (backend#2166): without any `permission-*` the token + # Least privilege ((internal ref)): without any `permission-*` the token # carries the App's FULL installation grant. actions/add-to-project needs # THREE scopes, not one: it must RESOLVE the triggering issue/PR node # before it can add it to the board, so it needs read on both content @@ -89,4 +107,3 @@ jobs: with: project-url: https://github.com/orgs/tracebloc/projects/2 github-token: ${{ steps.app-token.outputs.token }} - From fd9a9e973522328aa541f8b99ba666ac71b78244 Mon Sep 17 00:00:00 2001 From: lukasWuttke <54042461+LukasWodka@users.noreply.github.com> Date: Sun, 13 Sep 2026 12:00:22 +0200 Subject: [PATCH 11/12] chore: CLAUDE.md carries no internal references (public repo) --- CLAUDE.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 3346d26..7f8dd9a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,7 +2,7 @@ Repo-specific guidance for Claude Code sessions goes here, above the managed org block: build/test commands, architecture notes, gotchas, -and this repo's default reviewer. Rollout: tracebloc/backend#1602. +and this repo's default reviewer. Rollout: (internal ref). ## tracebloc engineering standards (org-wide) @@ -17,14 +17,14 @@ and this repo's default reviewer. Rollout: tracebloc/backend#1602. ### Branches & PRs - Branch model, **for a repo on the release train**: `develop → staging → main`. Branch off `develop`; every PR targets `develop`. Never open PRs to `staging` or `main` — promotions are the train's job. -- **For a repo not on the train, do not infer the branch model from this file — read `repo-inventory.yml`.** `release_train:` says whether the model above applies at all, and the per-branch `exempt:` anchors record which branches actually exist. This bullet used to enumerate the exceptions by name and **drifted from the inventory on every one of them**: `docs` was called `main`-only while it had been on the train since 2026-08-04 (`release_train: true`, `develop: required`, staging present), and `rfcs` was called `main`-only while it had a `develop` taking merges (measured 2026-08-22, backend#2242 / .github#306). Restating the authority is the defect; pointing at it is the fix. +- **For a repo not on the train, do not infer the branch model from this file — read `repo-inventory.yml`.** `release_train:` says whether the model above applies at all, and the per-branch `exempt:` anchors record which branches actually exist. This bullet used to enumerate the exceptions by name and **drifted from the inventory on every one of them**: `docs` was called `main`-only while it had been on the train since 2026-08-04 (`release_train: true`, `develop: required`, staging present), and `rfcs` was called `main`-only while it had a `develop` taking merges (measured 2026-08-22, (internal ref) / .github#306). Restating the authority is the defect; pointing at it is the fix. - **Trap, recorded in the inventory and caught by no check:** a `develop` created on a non-train repo and left **unprotected** is invisible to the guards — that is the `develop_unprotected_non_train` anchor, and the inventory notes "a `develop` created and left UNPROTECTED is not flagged … no check was going to surface it." So creating one to satisfy the first bullet **forks the repo silently**: PRs split between the new branch and the repo's existing convention, nothing promotes between them, and the two heads diverge until someone reconciles by hand. If a repo appears to lack a `develop`, that is a fact to verify in the inventory, not a gap to fill. - Before starting any task: `git fetch` and branch from the current tip of `develop` — never build on a stale checkout. A branch that lives more than a day gets `develop` merged back in before review. We move fast; stale starts mean silent divergence and duplicated work. - One self-contained change per PR. A few hundred changed lines reviews well; at 1000+ split it. Refactors ship in separate PRs from behavior changes. - Branches are short-lived (aim to merge within a day or two), single-author, and based on `develop` — no stacked PRs on top of other open PRs. - Your branches are yours to clean up. Merged ones now delete themselves server-side, so this is about the rest: run `git reap` (from `tracebloc/org-config/scripts/git-reap`) in your checkouts now and then. It is dry-run by default and only proposes a branch when it can prove the work landed. Nobody else can do this for you — you are the only one who knows whether an *unmerged* branch of yours still matters, and `git branch --merged` will not tell you, because we squash-merge and a squashed branch is not an ancestor of `develop`. -- **"Yours" is the branch you opened the PR for, never the branch whose last commit is yours.** Pushing a review fixup onto someone else's branch makes you its tip-commit author and changes nothing about whose work it is — so a "my branches" list built from `%(authorname)`, or from the tip author in any form, aims your cleanup at other people's work. Measured: two of Shujaat's `client` branches showed up on such a list and were one confirmation step away from `--delete` (backend#2365). If you are building any list that reasons about ownership, call `tracebloc/org-config/scripts/branch_owner.py` rather than re-deriving it; a branch it cannot attribute comes back as `unattributable`, which is the answer to act on, not to fill in. -- Names and commits: `feat/ fix/ docs/ sec/ ci/ chore/` + issue number + short slug (`fix/1234-ingest-timeout`); commit subjects `type(scope): summary`, referencing the ticket (`backend#1234`). **`(scope)` is the component — `mint-scope`, `kanban` — never the ticket number.** A number in a PR title (`sec(2157): …`) is read by `closing-ref` as a reference the body must make good, in one of two forms: `Closes /#N` when this PR really finishes the ticket, or `Part of /#N` when it does not. Both satisfy the check; only `Closes` closes the ticket and moves its card, so never write it for partial work — and a bare `Closes #N` resolves against the repo you are in, which for a `tracebloc/backend` ticket links the wrong issue. Keeping the number in the title is right either way: naming the parent is traceability, not a promise to close it (backend#2616). +- **"Yours" is the branch you opened the PR for, never the branch whose last commit is yours.** Pushing a review fixup onto someone else's branch makes you its tip-commit author and changes nothing about whose work it is — so a "my branches" list built from `%(authorname)`, or from the tip author in any form, aims your cleanup at other people's work. Measured: two of Shujaat's `client` branches showed up on such a list and were one confirmation step away from `--delete` ((internal ref)). If you are building any list that reasons about ownership, call `tracebloc/org-config/scripts/branch_owner.py` rather than re-deriving it; a branch it cannot attribute comes back as `unattributable`, which is the answer to act on, not to fill in. +- Names and commits: `feat/ fix/ docs/ sec/ ci/ chore/` + issue number + short slug (`fix/1234-ingest-timeout`); commit subjects `type(scope): summary`, referencing the ticket (`(internal ref)`). **`(scope)` is the component — `mint-scope`, `kanban` — never the ticket number.** A number in a PR title (`sec(2157): …`) is read by `closing-ref` as a reference the body must make good, in one of two forms: `Closes /#N` when this PR really finishes the ticket, or `Part of /#N` when it does not. Both satisfy the check; only `Closes` closes the ticket and moves its card, so never write it for partial work — and a bare `Closes #N` resolves against the repo you are in, which for a `(internal ref)` ticket links the wrong issue. Keeping the number in the title is right either way: naming the parent is traceability, not a promise to close it ((internal ref)). - When you open a PR: assign yourself and request exactly one reviewer immediately — a PR without a reviewer stalls by construction. You pick the reviewer: whoever knows the code best. There is no per-repo default, and no automation assigns one — branch protection just refuses to merge without a review. - When you are the reviewer: first response within one business day. @@ -37,11 +37,11 @@ and this repo's default reviewer. Rollout: tracebloc/backend#1602. - After opening or pushing to a PR, stay on it: poll CI and Bugbot on the current head and triage every finding the same day — fix it, or reply on the thread saying why not. No silent dismissals. Unresolved threads block the merge and stall the release train's settle stage; cheap now beats expensive later. - A finding that recurs across PRs becomes a rule: add it to `.cursor/BUGBOT.md`, and if it is grep-expressible, to code-quality's house-rules — then stop re-arguing it in comments. - Style and naming rules live in tooling (black/ruff, eslint/prettier, house-rules), never in prose. If a rule matters, encode it; do not restate linter rules in CLAUDE.md files. -- Never commit secrets, tokens, or customer data — not in code, config, tests, issues, or commit messages. gitleaks catches secrets in **code**. Nothing scans PR titles, descriptions or commit messages: the public PII gate that did was retired on 2026-08-06 (backend#1409), so keeping customer names out of PR prose on public repos is on you, not on a check. +- Never commit secrets, tokens, or customer data — not in code, config, tests, issues, or commit messages. gitleaks catches secrets in **code**. Nothing scans PR titles, descriptions or commit messages: the public PII gate that did was retired on 2026-08-06 ((internal ref)), so keeping customer names out of PR prose on public repos is on you, not on a check. ### Engineer kanban -- Every ticket on the board carries a `Status` — no card sits at "No Status". New tickets start in `Backlog`. **Bugs are the exception:** label them `work-type:bug` (the Bug template does it) and automation moves the card straight into `Ready` — defects don't wait for refinement. This holds in every repo, and the exception that used to be written here is gone rather than kept accurate by hand: the labels exist fleet-wide, and `triage-labels.yml` asserts daily that every label the templates apply and the caller fires on exists in every repo declaring that caller. A hand-written exception list drifts on every entry — it named two repos while the inventory said three — so the fix was to empty it (backend#2598). +- Every ticket on the board carries a `Status` — no card sits at "No Status". New tickets start in `Backlog`. **Bugs are the exception:** label them `work-type:bug` (the Bug template does it) and automation moves the card straight into `Ready` — defects don't wait for refinement. This holds in every repo, and the exception that used to be written here is gone rather than kept accurate by hand: the labels exist fleet-wide, and `triage-labels.yml` asserts daily that every label the templates apply and the caller fires on exists in every repo declaring that caller. A hand-written exception list drifts on every entry — it named two repos while the inventory said three — so the fix was to empty it ((internal ref)). - Picking up work: the team coordinates. `Ready` is the refined queue — bugs excepted, per the line above — and the first choice when it's stocked; pulling from `Backlog` is normal when refinement hasn't caught up — say what you're taking. - Merging to `develop` moves the card to `On dev` automatically; there is no dev-side review. - Functional review happens once, on staging: when it passes, comment `/fr-pass` on the PR or drag the card to `Ready for prod`. Self-signoff is allowed. From ce52c45c045bba3c2f65159effffef6b6e397abe Mon Sep 17 00:00:00 2001 From: lukasWuttke <54042461+LukasWodka@users.noreply.github.com> Date: Sun, 13 Sep 2026 12:00:23 +0200 Subject: [PATCH 12/12] chore: .cursor/BUGBOT.md carries no internal references (public repo) --- .cursor/BUGBOT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cursor/BUGBOT.md b/.cursor/BUGBOT.md index c49e348..6bf8d50 100644 --- a/.cursor/BUGBOT.md +++ b/.cursor/BUGBOT.md @@ -3,5 +3,5 @@ What Bugbot should know before reviewing a diff in THIS repo: the stack, the conventions that are not enforced by a linter, and the defect classes that have recurred here. Per-repo by design -- see `.cursor/BUGBOT.md` in -tracebloc/backend for the shape. Presence is asserted by the conformance +(internal ref) for the shape. Presence is asserted by the conformance audit (repo-inventory.yml `quality_files`); content is yours.