fix(infra): GT-622 delete the 210 orphaned CodeQL analyses; GT-656 make a wrong gap title correctable - #440
Conversation
…ct three claims the row got wrong The irreversible half the board had deliberately deferred is executed: the 210 code-scanning analyses under the dead key `.github/workflows/ci.yml:codeql` are deleted from `refs/heads/main` (201) and `refs/heads/develop` (9), each DELETE preceded by a GET asserting `analysis_key` and `results_count == 0` against a pre-built id allowlist. 210 deleted, 0 refused, 0 errors. Measuring before deleting refuted three of the row's own claims, and the row had already been re-measured twice without any of them surfacing, because every pass checked the COUNT and none checked the CLAIM: 1. It was not red. The check-run conclusion was `neutral` (`gh pr checks` renders it `skipping`) from PR #250 onward; only PR #217 was `failure`. The row's central argument — a permanently RED check trains reviewers to discount red — described a state that ended eleven days after it was written. 2. The branch was wrong. The warning names `refs/heads/develop`, not `main`. PRs into `main` came back clean from #420 with all 201 orphans still in place, four minutes apart from #433 still warning on `develop`. `main` stopped warning without any deletion, which refutes the row's causal model. 3. The 9 analyses on `develop` were never counted. The real total was 210. What made the owner decision cheap had never been read: all 210 carry `results_count: 0`. The irreversibility was real; the loss was not. Verified unchanged across the deletion: 242 open / 82 dismissed / 60 fixed alerts, open-by-tool CodeQL 75 / Scorecard 158 / Trivy 9. `CodeQL SAST` is still REQUIRED on both branches and green. 22 analyses under the dead key are deliberately left on `refs/pull/{4..17}/merge` — ephemeral per-PR refs that can never be the base of a PR. The row stays PENDING on purpose. Its first criterion can only be observed on a PR into `develop`, which is what this PR is; the closure lands in a follow-up commit once the check reports, not on the assumption that it will. Criterion 2 was restated: it demanded the only keys on `main` be the two from `sdk-cli-ci.yml`, but a third legitimate key has since appeared (`openssf-scorecard.yml:analysis`), so the test is the ABSENCE of the dead key. NOT a retitle: the catalog title still says "Eighty-two" and is knowingly left wrong, because `49-validate-gap-id-allocation` reads any title change as a possible id collision and has no escape hatch. The 2026-08-01 re-measure set that precedent (82 -> 201 in the evidence, title untouched). Worth its own row. Guards run locally: 04 bilingual parity, 08 tracking, 40 path literals, 47 joined paths, 49 gap-id allocation, bilingual-terminology-lint — all exit 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
📊 Bilingual Coverage ImpactPR Changes
Repository Coverage
✅ Good: All EN changes have ES counterparts. Generated by GitHub Actions |
…at carries it Criterion 1 of GT-622 could only be satisfied by a pull request into `develop`, the one base that still carried the missing-configuration warning. PR #440 is that pull request, and the check reported 105s after it opened: gh pr checks 440 -> CodeQL pass check-run output title -> "No new alerts in code changed by this pull request" The five PRs into `develop` on 2026-08-04 (#425, #427, #429, #431, #433) all returned `neutral` / "1 configuration not found" against the same base. The closure was written after reading the check, not on the assumption it would turn out that way. GT-622 -> DONE. Board counters recomputed from the rows: 640 / 653 done, 3 in progress, 3 pending, 7 deferred. Closure evidence record added, with the 22 analyses left on refs/pull/{4..17}/merge recorded as an explicit accepted-scope exemption rather than a silent one. Also corrected while measuring, and NOT part of this gap: GT-653 still carried "Remaining: promotion to required context on main/develop". That promotion has happened — `Secret Detection (gitleaks)` is a required context on both branches and the required set went 7 -> 8, read back from branch protection. The row was describing as pending something already done. Guards run locally: 04 bilingual parity, 08 tracking, 40 path literals, 41 evidence commands (--strict --max-dead 17, 0 dead over 1223 commands in 622 closures), 47 joined paths, 49 gap-id allocation, bilingual-terminology-lint — all exit 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…it is pinned to `09-reconcile-maturity --check` requires `maturity-evidence.json`'s `asOf` to equal the board's `Last Updated`, and rotating that header to 2026-08-08 broke the equality — a real coupling this change introduced, caught by the required `Validate documentation` job rather than by me. `asOf` is the reconciliation date, not a claim that the readiness checks were re-observed: each check keeps its own `observedAt` (2026-07-20) untouched. Regenerated artifact carries only the counters that actually moved: asOf 2026-07-26 -> 2026-08-08, done 639 -> 640, pending 4 -> 3, closureRecords 621 -> 622. No other drift. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…the collision check
Closes GT-656.
`49-validate-gap-id-allocation` discriminates an id collision from an ordinary
edit by comparing the catalog `**Title:**` against the base branch, and failed
on any difference. Right for a collision, wrong for a retitle — and the guard
could not tell them apart. Its own message admitted this and asked for the
distinction "in the commit", which nothing reads and a squash merge rewrites.
The practical effect was that gap titles were IMMUTABLE.
The cost was already paid, not hypothetical. GT-622 was re-measured twice —
82 -> 201 -> 210 orphaned analyses, and the branch still carrying the warning
turned out to be `develop`, not `main` — while its headline went on reading
"Eighty-two ... every PR", because correcting it turns a REQUIRED check red on
the PR carrying the correction. The 2026-08-01 re-measure set that precedent
silently; this change found it about to be followed a third time. A board whose
purpose is that debt is not described inaccurately was accumulating rows whose
first line was inaccurate.
Fixed by turning the deferred human judgement into DATA, not by softening the
check. A retitle is declared in reference/core/control-center/gaps/gap-retitles.json
as { id, from, to, declaredAt, reason }, and exempts only when BOTH titles match
the two branches exactly. That exactness is the design: it cannot be written as a
blanket "this id may be retitled", so a real collision later landing on the same
number still fails, because its titles are not the declared pair.
The registry is itself guarded, because an exemption list that rots silently is
worse than the defect it fixes:
active -> exempts its collision
spent -> the retitle reached the base; reported, not fatal
rot -> describes neither side; FAILS
and a registry that exists but cannot be parsed, or has no `retitles` array, is
a hard failure rather than an empty list. Every active exemption is printed with
its reason — an exemption nobody can see is indistinguishable from a hole.
First use in the same change: GT-622's title is corrected, 82 -> 210 and
"every PR" -> "PRs into `develop`", in both languages. Guard green against
`origin/main` and `origin/develop` with the retitle applied.
Also corrected: GT-622's evidence claimed the title was "knowingly left wrong".
That is no longer true, and leaving it would have been the same class of stale
claim this row is about.
Verified: node --test 49-validate-gap-id-allocation.test.mjs 27/27, including
the negative twins — the same retitle WITHOUT a declaration is still red, a
declaration quoting a title the catalog never carried does not launder it, an
unparseable registry stops the run, and a real collision on an already-retitled
id still fails. Guards 04, 08, 09 --check, 40, 41 (--strict --max-dead 17, 0
dead over 1226 commands), 42, 43, 47, 49 and bilingual-terminology-lint all
exit 0.
Board: 641 / 654 done, 3 in progress, 3 pending, 7 deferred.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Follow-up: GT-656 — the retitle this PR could not makeClosing GT-622 hit a second defect and it is now fixed in this same PR.
That cost was already paid. GT-622 was re-measured twice — 82 → 201 → 210 analyses, and the branch still carrying the warning turned out to be The fix is data, not a softer checkA retitle is declared in The registry is itself guarded, because an exemption list that rots silently is worse than the defect it fixes:
An unparseable registry, or one with no Verification
Guard green against both One thing this PR does not fix
🤖 Generated with Claude Code |
Both were found by the runner, not by me, and both are real.
1. GT-656's recorded validationCommands were EXECUTED and failed.
`41-validate-evidence-commands --execute` runs what the closure registry
records, and two of GT-656's entries passed `--base origin/main` /
`--base origin/develop`. A remote ref is not resolvable in the runner
checkout, so the guard refused to compare — which is its correct behaviour
("unable to answer is not the same as nothing to report"), reported as a red
Governance guards job. The registry now records only self-contained proof:
`node --test` over the 27 fixtures (the negative twins included) and the
negative-fixture guard. The two branch comparisons stay in the catalog
section as prose, where an unrunnable command belongs.
2. The executive summary was left stale by the maturity reconciliation.
`46-validate-derived-artifact-order` stops at the FIRST stale link on
purpose: maturity-reconciliation.json feeds the executive summary, and
regenerating the upstream without the downstream breaks the chain.
Regenerated; the chain is current and at a fixed point — replaying all 8
links changes nothing.
Verified: `41-validate-evidence-commands --execute --strict --max-dead 17`
now reports 113 executed / 112 exit 0, with the single remaining non-zero being
GT-78's root-cleanliness guard objecting to an untracked local `.DS_Store` that
does not exist on the runner. `46-validate-derived-artifact-order --verbose`
exit 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ix, and name the half that has none (#441) GHSA-5p4m-2wfm-xmqj / CVE-2026-59870 turned `Security Audit` red on every branch. Attribution measured first: the dependabot PRs of 2026-08-05 were green, PR #440 of the 8th was red, and it changed 8 doc/JSON files with zero dependency files — pre-existing branch debt, not a regression. The half that had a fix: the root override already carried `js-yaml: 4.3.0`, added for an EARLIER advisory, and the new one is vulnerable through 4.3.0 inclusive — one patch short. Bumped to 4.3.1; three nested copies collapsed into the hoisted one. The half that has none: the remainder arrives through @nestjs/swagger, which pins js-yaml exactly, and all three published releases pin a vulnerable version (11.4.4 -> 4.1.1, 11.4.5 -> 4.3.0, 11.4.6 -> 5.2.1). npm overrides do not reach a nested exact pin — measured four ways, same tree every time. That experiment also REFUTES the generalisation GT-636 recorded; corrected in the catalog. `63-validate-npm-audit-gate` keeps the same HIGH threshold and requires that an advisory with no upstream fix be NAMED, with the path it arrives by. It fails on an undeclared advisory, on a declaration for a different id or path, and on a declaration whose advisory has DISAPPEARED — so the good news arrives as a red check asking for the entry's removal. Its own fixtures run in the job. Recorded for the next reader: `Trivy` flags this as a new high alert because the advisory id at that lockfile position changed. Reverting the swagger bump makes it worse — 11.4.4's js-yaml 4.1.1 carries three advisories (two HIGH) against 11.4.6's one. The revert was attempted during this work and had to be undone, so the measurement lives in the exceptions entry and in GT-657. node --test 19/19; core-api 160/160; core-domain 1704/1704; 13 guards exit 0. Board: 642 / 655 done, 3 in progress, 3 pending, 7 deferred.
Advances GT-622.
What landed
The irreversible half the board had deliberately deferred is executed: the 210 code-scanning analyses under the dead key
.github/workflows/ci.yml:codeqlare deleted fromrefs/heads/main(201) andrefs/heads/develop(9). EachDELETEwas preceded by aGETassertinganalysis_keyandresults_count == 0against a pre-built id allowlist, so no ordering mistake could reach a live-key analysis. 210 deleted, 0 refused, 0 errors.Measuring first refuted three of the row's own claims
The row had already been re-measured twice without any of these surfacing, because every pass checked the COUNT and none checked the CLAIM.
neutral—gh pr checksrenders itskipping— from PR docs(gaps): close GT-601 on verification — a sweep of the 20 in-progress rows #250 onward; only PR Develop #217 was everfailure. The row's central argument (a permanently RED check trains reviewers to discount red) described a state that ended eleven days after it was written.refs/heads/develop, notmain. PRs intomaincame back clean from chore(sync): develop → main — .dockerignore + entrypoint assertions #420 onward with all 201 orphans still in place — four minutes apart from feat(core): GT-654 one /health shape, GT-655 three orphan operations bound #433 still warning ondevelop.mainstopped warning without any deletion, which refutes the row's causal model and means the cleanup was never the only thing that could have resolved it.developwere never counted. The real total was 210, not 201 — and the 9 outside the row's scope were the ones producing the symptom.What made the owner decision cheap had never been read: all 210 carry
results_count: 0. They are 210 records of "scanned, found nothing" from a configuration dead since June. The irreversibility was real; the loss was not.Verification
main/developCodeQL SAST22 analyses under the dead key are deliberately left on
refs/pull/{4..17}/merge— ephemeral per-PR refs from May that can never be the base of a PR, so they produce no symptom.Guards run locally, all exit 0:
04-check-bilingual-parity,08-validate-tracking,40-validate-path-literals,47-validate-joined-paths,49-validate-gap-id-allocation,bilingual-terminology-lint.Why the row is still PENDING
Criterion 1 — "
gh pr checkson a fresh PR intodevelopshows noCodeQLcheck reporting configuration not found" — can only be observed on a PR intodevelop. This is that PR. The closure lands in a follow-up commit once the check actually reports, not on the assumption that it will.Not a retitle
The catalog title still says "Eighty-two" and is knowingly left wrong:
49-validate-gap-id-allocationreads any title change against the base as a possible id collision and has no escape hatch for a deliberate retitle, so correcting it turns a required check red. The 2026-08-01 re-measure set that precedent (82 → 201 in the evidence, title untouched). A guard that makes titles immutable guarantees every re-measured row keeps its now-wrong headline forever — worth its own row.🤖 Generated with Claude Code