Skip to content

gate: nothing fails when a GA'd major's release page still describes itself as a pre-release — the gap that let v17 and v16 both ship with stale status #8892

Closed

Description

@os-zhuang

scripts/check-release-notes.mjs verifies that every released major has a curated, navigable page. It does not verify that the page says the release happened. That gap has now produced the same defect twice:

Both times CI was fully green. The defect is invisible to every existing gate, so it is only ever caught when someone happens to read the page — which is exactly the failure mode a ratchet exists to remove.

Maintainer authorized filing this on 2026-08-15 after reviewing #8882: 「立卡」.

What to build

A gate that fails when a major has a GA (non-prerelease) release and its release page or index entry still describes the train as unreleased.

Two assertions, per GA'd major:

  1. content/docs/releases/v<major>.mdx — the release-status blockquote must not carry pre-mode framing (is currently published as, preparing to ship, pre-mode, nothing reaches the latest tag, Until \changeset pre exit`, a bare .0.0-rc.N` presented as the current version).
  2. content/docs/releases/index.mdx — that major's entry must not end in a pre-release parenthetical ((current series: <major>.0.0-rc.N, pre-release)).

Three design constraints — these are where this gate will go wrong

(a) The GA predicate must exclude prereleases, and the existing helper does not. check-release-notes.mjs's releasedMajors() uses:

for (const m of text.matchAll(/^##\s+(\d+)\.\d+\.\d+/gm))

That pattern is unanchored at the end, so ## 17.0.0-rc.0 also matches and yields major 17. Harmless for the existing check (a page should exist during the RC window too) but actively wrong here: reusing it would demand that v18's page claim to be released the moment 18.0.0-rc.0 publishes — inverting the defect. This gate needs its own predicate: a ## <major>.<minor>.<patch> heading in packages/spec/CHANGELOG.md with no prerelease suffix. Consider whether releasedMajors() should be split into releasedMajors() / gaMajors() rather than duplicated.

(b) Do not scan the whole page. v17.mdx contains hundreds of legitimate rc.N mentions — the entire Landed since 17.0.0-rc.0 … rc.6 history, better-auth 1.7.0-rc.2, pin-chain enumerations. A naive page-wide grep for rc. is all false positives and would be reverted within a week. Scope the scan to the status blockquote (the first > block after the frontmatter — where both v16 and v17 put the claim) plus the single index.mdx line for that major.

(c) Prove it catches the real defect. The gate must go red against the v16 page as it stands today. Sequencing: #8886 fixes v16 and may land first — if it has, verify against the pre-fix ref (git show <ref>:content/docs/releases/v16.mdx) rather than concluding the gate works because everything is green. A gate whose only evidence is "green on a clean tree" has not been tested. Verify against v17 pre-#8888 as a second positive.

House conventions

  • Self-test first, like its siblings: check:role-word and check:docs-audit-scope both run --self-test before the real check. Follow that shape.
  • Wire into .github/workflows/lint.yml, where check:release-notes (line ~541) and check:role-word (line ~293) already run.
  • Whether this is a new script or an extension of check-release-notes.mjs is the implementer's call — argue it in the PR. Extending keeps one CHANGELOG parse; splitting keeps each gate's failure message specific.

Out of scope

Fixing v16 (that is #8886) and re-checking v17 (already landed in #8888). This card is the gate only. If the gate is red on main because #8886 has not landed yet, say so in the PR and coordinate — do not fix the page here, and do not weaken the gate to make it pass.

Re-check

git fetch origin main
git show origin/main:scripts/check-release-notes.mjs        # current gate: page EXISTS, not page IS CORRECT
git show origin/main:content/docs/releases/v16.mdx | sed -n '14,22p'   # the live positive
git grep -n "check:release-notes" origin/main -- .github/workflows

Activity

  1. added
    pm:queueReady for the PM dispatch loop
    domain:devxDomain lane — seat card indexed by label:pm:seat
    on Aug 15, 2026
  2. added theissue type on Aug 15, 2026
  3. os-project-manager commented on Aug 15, 2026

    @os-project-manager
    Collaborator

    ⛔ Do not dispatch this card until its scope decision is made — the instance set is larger than it looks

    From the domain:devx seat (#6023). ⚠️ This card is not blocked on #8886 alone, which is what this seat previously assumed and recorded. Correcting that here so it does not get acted on.

    What I got wrong

    This seat held this card back behind #8886 / PR #8912 with the reasoning: "the gate must not land before the stale page it would go red on." The reasoning is right. The instance set was wrong — I treated v16 as the only stale page because it was the only one anyone had noticed.

    Measured on origin/main @ 85f5e78, 2026-08-15T16:29Z

    page says last tag
    v9.mdx:6 published at 9.0.0 9.11.0 ❌
    v12.mdx:6 published at 12.0.0 12.6.0 ❌
    v13.mdx:6 published at 13.0.0 13.0.0 ✅
    v14.mdx:6 current: 14.5.0 14.8.0 ❌ (and index.mdx already says final release: 14.8.0 — page and index disagree)
    v15.mdx no status line 15.1.1 ➖

    ⇒ Merging #8912 will not make main safe for this gate. Landed as a naive all-majors check, it goes red on v14, v12 and v9 on day one. A red main is shared damage every lane pays for, so this has to be decided before implementation, not discovered by CI.

    The three options, and the trap

    Filed in full as #8916, summarised:

    ⚠️ C is the one most likely to be reached for and least likely to be right by default. A brand-new gate whose baseline starts with three entries ships pre-compromised, and this repo's own experience is that a gate baselined at birth gets baselined again. It is defensible only if someone states positively why those three pages should stay stale.

    Dispatch conditions for whoever takes this

    1. ⛔ Do not implement before picking A, B or C deliberately, and record which in the PR body with the reason.
    2. ⚠️ The gate's own text must say what it is scoped to — an intentional limitation documented only inside the implementation is indistinguishable from a bug to everyone who does not read the implementation. (Same principle the grading on check:cross-package-test-inputs does not see a new URL(…, import.meta.url) seed, so an undeclared cross-package read passes green #8698 made mandatory.)
    3. Prove it by ablation, not by a green run: point it at a deliberately stale fixture page and confirm it goes red for the right reason. A gate for "nothing fails when X" that has never been seen failing is the exact shape this repo keeps rediscovering.

    ⛔ Still not dispatched from this seat. Card stays pm:queue, unassigned, labels untouched.


    Generated by Claude Code

  4. os-project-manager commented on Aug 15, 2026

    @os-project-manager
    Collaborator

    Triage cross-ref (routing information, not a state change): #8916 measured three more stale release pages (v9/v12/v14) and records an A/B/C fork this gate's design must pick deliberately — landing this gate unscoped goes red on those three pages the day it merges. The dispatch prompt for this card must name #8916.


    Generated by Claude Code

  5. os-project-manager commented on Aug 16, 2026

    @os-project-manager
    Collaborator

    ✅ Scope decision made — by the maintainer, and it is none of A/B/C exactly

    Maintainer, 2026-08-15, verbatim, untranslated:

    v14 之前的版本都不用管

    This is what the card was held for. It resolves the scope question with a principled cutoff rather than either extreme I offered.

    The settled scope

    The gate covers v14 and later. Pages for majors before v14 are explicitly out of scope — their staleness is an accepted state, ⛔ not a baselined defect.

    ⚠️ That distinction is the whole reason this is better than the options I put up:

    • It is not option A (current series only). A would have left v14.mdx claiming current: 14.5.0 while index.mdx says final release: 14.8.0 — the site contradicting itself on one screen.
    • It is not option C (land with a three-entry baseline). ⛔ Nothing is baselined. A brand-new gate does not ship pre-compromised, and no "known wrong" is recorded for a future agent to learn from.
    • It is a bounded B: exactly one page needs fixing first (v14.mdx), not three.

    ⛔ Dispatch conditions — now concrete

    1. Scope the gate to v14+. ⚠️ State the cutoff in the gate's own failure text, with the reason. An intentional limitation documented only inside the implementation is indistinguishable from a bug to everyone who does not read the implementation — the principle the check:cross-package-test-inputs does not see a new URL(…, import.meta.url) seed, so an undeclared cross-package read passes green #8698 grading made mandatory, and it applies with full force to a gate that deliberately ignores four pages.
    2. Sequencing, load-bearing: docs(releases): v9, v12 and v14 status lines are stale against their own last tags — three more instances of the class #8892 is about to gate #8916's v14 fix lands FIRST. The gate would go red on v14.mdx the day it lands otherwise, and a red main is shared damage every lane pays for. ⚠️ The v14 fix is content/docs/releases/ — release-owned, so it is a separate docs-only PR, ⛔ never folded into this gate's PR.
    3. Prove it by ablation, ⛔ not by a green run. Point it at a deliberately stale fixture page and confirm it goes red for the right reason. A gate for "nothing fails when a GA'd major's page still says pre-release" that has never been seen failing is precisely the shape this repo keeps rediscovering — and it is the shape the sibling card registry-canary structurally cannot catch remote-template breakage — it scaffolds only blank and never runs npm run build; it was green over the #7644 defect #8678 is being fixed for right now.
    4. ⚠️ Decide and state how the gate reads "what actually shipped". Tags are the authority (git tag --list '@objectstack/spec@<major>*') — that is what docs(releases): record the 16.0.0 GA cut and the closed v16 line #8912 used and what this seat verified against. ⛔ Do not derive it from the page's own prose, which is the thing under test.

    Boundary caveat, so it does not get lost

    I read 「v14 之前」 as v13 and earlier, i.e. v14 is in scope. Recorded on #8916 with the reasoning and flagged as a one-word correction if the intent was "v14 and earlier" — in which case the cutoff here moves to v15 and #8916 closes with no work. ⛔ Do not implement the cutoff from this comment alone if #8916 has since been corrected; read it first.

    Card stays pm:queue, unassigned. Dispatchable once #8916's v14 fix has merged.


    Generated by Claude Code

  6. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 16, 2026
  7. os-project-manager commented on Aug 16, 2026

    @os-project-manager
    Collaborator

    Claim: PM loop round 3
    Session: session_011RB4waLuNbdruCo6X9oobm
    Branch: claude/issue-8892-ga-release-page-status-gate
    Worktree: objectstack-issue-8892
    Domain: domain:devx
    File surface: a new gate script under scripts/ · package.json script entry · .github/workflows/lint.yml wiring. ⛔ No content/docs/releases/ edits of any kind (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: opus
    Serial constraints cleared: none blocking. #8664 (PR #8944) and #8754 (PR #8945) are ACCEPTed and awaiting merge; #8945 adds a different new script plus a lint.yml step and a package.json entry — ⚠️ see the collision note below. #8678 (cloud) is in scripts/publish-smoke.sh.

    ⛔ SUPERSEDES my comment 5305270294 — the cutoff is v16, not v14

    Maintainer, 2026-08-15, verbatim, untranslated, in order:

    v14 之前的版本都不用管

    then, superseding it:

    只负责 v16 以后的,需要的话之前的版本删除也可以的

    and confirming the boundary explicitly:

    v14 也不用管

    ⇒ The gate covers v16 and later. v15 and earlier are out of scope entirely. ⛔ My earlier comment on this card said "v14 and later" — that was based on the first ruling and is wrong now. ⛔ Do not implement from it. I am leaving it visible rather than editing, so the correction is legible.

    #8916 is closed not planned as a consequence — v9/v12/v14 staleness is an accepted state, ⛔ not a defect and ⛔ not a baseline entry.

    ✅ The prerequisite is gone — this card is dispatchable now

    Both in-scope pages are already correct, verified on origin/main just now:

    page status line index entry last tag
    v16.mdx:16 Release status: 16.0.0 is released. (final release: 16.1.0) 16.1.0 ✓
    v17.mdx:16 Release status: 17.0.0 is released. (current series: 17.0.0, released 2026-08-14) 17.0.0 ✓

    (v16 fixed by PR #8912, v17 by PR #8882, both merged today.) ⇒ A correctly-scoped gate is green on today's main with nothing to fix first.

    ⛔⛔ TWO MEASURED HAZARDS THAT WOULD MAKE THIS GATE WRONG ON DAY ONE

    I hit both while verifying the table above. Neither is hypothetical.

    1. sort -V is NOT semver-aware — it ranks a prerelease ABOVE the release

    $ printf '%s\n' '17.0.0-rc.6' '17.0.0' | sort -V
    17.0.0
    17.0.0-rc.6      ← sorted LAST
    

    ⇒ A gate that picks "the latest tag for this major" with sort -V | tail -1 gets 17.0.0-rc.6 and concludes v17 is still a prerelease — going red on a page that is correct, which is the precise inverse of this gate's job. In semver 17.0.0-rc.6 < 17.0.0. Use a real semver comparison, and pin it with a --self-test case containing a prerelease.

    2. git tag --list in an incomplete clone silently under-reports

    My local clone lists only rc.0, rc.1, rc.2, rc.5, rc.6 for v17 — no 17.0.0, and no rc.3/rc.4 either. git ls-remote --tags origin shows all of them including @objectstack/spec@17.0.0. The clone was incomplete, not the tag missing.

    ⇒ In a shallow or tag-less CI checkout, a tag-based gate concludes v17 never went GA and goes red on a correct page. Guard the instrument: either ensure tags are fetched (fetch-depth: 0 / explicit tag fetch) and assert it — e.g. fail loudly if the tag set for a major is empty — or derive from a source that does not depend on checkout depth. ⛔ An empty tag list must never be read as "nothing shipped".

    ⚠️ Both hazards are the same family and it is the family this repo keeps paying for: the instrument was not measuring what it appeared to measure. I caught each only by checking against a second source. Build that check into the gate rather than trusting either reading.

    Zone 1 — Ruled. ⛔ Not re-litigable.

    1. Scope: v16+. ⚠️ State the cutoff in the gate's own failure text, with the reason. A deliberate limitation documented only inside the implementation is indistinguishable from a bug to everyone who does not read the implementation — the principle the check:cross-package-test-inputs does not see a new URL(…, import.meta.url) seed, so an undeclared cross-package read passes green #8698 grading made mandatory, and it binds hardest on a gate that ignores five pages on purpose.
    2. ⛔ Nothing is baselined. No entry for v9/v12/v13/v14/v15. A new gate does not ship pre-compromised; out-of-scope and known-broken-but-tolerated are different states and only the first applies here.
    3. ⛔ Do not touch content/docs/releases/. It is release-owned; this is a code PR. Both in-scope pages are already correct, so there is nothing to fix — if you find otherwise, report it, do not edit.
    4. Prove it by ablation, ⛔ not by a green run. Point it at a deliberately stale fixture page (a v16-or-later page reverted to pre-release wording) and confirm it goes red for the right reason, then restore byte-identically. A gate for "nothing fails when a GA'd major still says pre-release" that has never been seen failing is the exact shape this repo keeps rediscovering — and the sibling card registry-canary structurally cannot catch remote-template breakage — it scaffolds only blank and never runs npm run build; it was green over the #7644 defect #8678 is in flight for that same shape right now.

    ⚠️ Collision note — read before wiring

    PR #8945 (#8754, ACCEPTed, awaiting merge) also adds a new scripts/ gate, a package.json script entry, and a lint.yml step. Different script file, but the same two shared files. ⇒ Branch from current main, and if #8945 lands first, merge origin/main and re-check your lint.yml / package.json hunks before pushing. ⛔ Do not resolve a conflict by dropping its entry.

    Gates

    ⚠️ I could not pre-derive your set — the deliverable is a file that does not exist yet. Run node scripts/pm/dispatch-gates.mjs <your real changed files> on the actual diff, run what it names, report the set. Wiring into lint.yml pulls the .github family (check:required-contexts, check:workflow-status-functions, check:shard-attestation, check:node-version). Any edit ⇒ check:nul-bytes. Judge by exit status, ⛔ not by grepping for ✗.

    scripts/ + workflows are not published package sources ⇒ skip-changeset.


    Generated by Claude Code

  8. os-project-manager commented on Aug 16, 2026

    @os-project-manager
    Collaborator
    {
      "issue": 8892,
      "status": "done",
      "branch": "claude/issue-8892-ga-release-page-status-gate",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/8950",
      "premise_still_valid": true,
      "summary": "New gate scripts/check-release-page-status.mjs + check:release-page-status script entry + a lint.yml step after the Release-notes drift guard. For every GA'd major from v16 on it asserts (1) the release page's status blockquote does not make a present-tense claim of unreleasedness AND does state a released-assertion, and (2) the index.mdx entry's status field presents no prerelease. Premise re-confirmed independently on origin/main a8189aef4, not inherited: v16.mdx:16 and v17.mdx:16 both read 'Release status: N.0.0 is released.', index reads '(final release: 16.1.0)' and '(current series: 17.0.0, released 2026-08-14)' — the gate is green on today's main with no prerequisite fix. Zone 1 fully honoured: SCOPE_FLOOR_MAJOR=16 as a hole-free '>=' (self-test asserts no holes across v6..v40), SCOPE_NOTE with the verbatim maintainer ruling printed on BOTH the failure and OK paths, zero baseline / zero exception list, and NO content/docs/releases/ file edited — the four ablations reverted pages out of git history and every one was restored byte-identically (sha256 verified, git status empty). Both hazards are neutralised structurally, not carefully: the gate never orders versions (set membership only, so sort -V has no surface), and the instrument is the in-tree CHANGELOG cross-checked against packages/spec/package.json, with git tags used only in the direction that cannot be wrong (a tag that exists proves a release shipped; an absent tag concludes nothing). Hazard 2 reproduced independently in this container's clone — `git tag --list '@objectstack/spec@17*'` yields rc.0/1/2/5/6 with NO 17.0.0, while ls-remote shows 17.0.0 exists — and the gate's own OK line on that clone reads 'corroborated by 1 local GA tag(s)' while still passing v17 correctly, which is the guard working. Two notes for the PM, neither blocking: (a) the platform appended a SECOND attribution footer to the PR body at create time (session-URL form, duplicated) — platform behaviour, not another actor, left as-is; (b) the labeler applied `dependencies` to a PR whose only package.json change is a `scripts` entry — possibly by design (any package.json touch), so I did not file it and did not remove another actor's label; flagging for your judgement.",
      "tests": "All local. Union re-run AFTER the final commit, at `git rev-parse --short HEAD` = 36dfb441f on a clean tree, judged by exit status: check:nul-bytes, check:node-version, check:required-contexts, check:shard-attestation, check:workflow-status-functions, check:type-check-coverage, check:release-notes, check:release-page-status, check:pm-dispatch-gates — 9/9 PASS (exit 0). Gate set derived on the REAL diff via `node scripts/pm/dispatch-gates.mjs .github/workflows/lint.yml package.json scripts/check-release-page-status.mjs`, which named node-version, release-page-status, required-contexts, shard-attestation, type-check-coverage, type-check-debt, workflow-status-functions (+ nul-bytes by the any-edit convention). Additions beyond the prompt's named .github family: check:type-check-coverage (run, PASS) and check:release-notes (not derived; run anyway to confirm the sibling gate is unaffected, PASS). check:type-check-debt derived but NOT run — its --re-measure spawns tsc across the workspace and this diff adds no package and touches no tsconfig/typecheck script/ledger entry, so it cannot move a raw error count; its read-only half passed. Root-only deps installed (`pnpm install --filter . --ignore-scripts`, 1s) because the three .github-family gates import `yaml`. ABLATION (Zone 1 #4), four legs, each against a REAL historical file out of git history rather than a synthetic fixture, each restored with `git checkout HEAD --` and verified byte-identical by sha256 + empty `git status` before the next: (A) v17.mdx at the pre-fix ref => RED exit 1, 6 problems — signals preparing-to-ship, latest-published-prerelease, nothing-reaches-latest-tag, until-pre-exit, ships-through-pre-mode, plus the missing released-assertion; v16 and index untouched. (B) v16.mdx at the pre-fix ref => RED exit 1, 2 problems — currently-published-as plus, independently, the missing released-assertion. (C) index.mdx at the pre-fix ref with pages left correct => RED exit 1, 3 problems — v16 prerelease-version, v17 prerelease-word + prerelease-version. (D) the whole content/docs/releases/ directory as it stood on 2026-08-13 (both stale pages live, CI green) => RED exit 1, 11 problems, ALL confined to v16.mdx(2)/v17.mdx(6)/index.mdx(3). Leg D doubles as the cutoff proof: at that same ref v9.mdx said 'published at 9.0.0' (tag 9.11.0), v12.mdx 'published at 12.0.0' (tag 12.6.0), v14.mdx 'current: 14.5.0' (tag 14.8.0) — all measurably stale, ALL correctly unreported, so nothing out-of-scope was swept in and nothing was baselined. META-ABLATION on the self-test itself (a self-test that cannot fail is this defect one layer up): defanging the preparing-to-ship signal => self-test RED exit 1 on exactly the two page/RED assertions naming it; adding a naive 'any rc.N mention' signal => self-test RED exit 1 on all three page/GREEN + scan-scope assertions AND the live run went red on the CORRECT v16 page. Both halves discriminate. REPORTED HONESTLY AGAINST THE TEMPLATE'S PRESUMPTION: my first meta-ablation was a NO-OP, not a pass — changing the blockquote line-join separator changed nothing because the following whitespace collapse re-joins regardless, so the mutation never reached the assertion and proved nothing; the two above were run instead. Control-character self-scan (`grep -naP '[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]'`) over all three changed files: clean, beyond check:nul-bytes passing. Labels read back AFTER the write: ci/cd, size/l, dependencies, skip-changeset — the three bot labels survived the union write. Branched from a8189aef4; origin/main re-fetched at push time and unchanged, so PR #8945 had not landed and no merge was needed — the PR body carries the resolution instruction in case it lands first.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  9. os-project-manager commented on Aug 16, 2026

    @os-project-manager
    Collaborator

    ✅ ACCEPT — PR #8950

    Verified against the tree, ⛔ not against the report.

    check reading
    changed files 3 — scripts/check-release-page-status.mjs (new, +887) · .github/workflows/lint.yml (+12) · package.json (+1)
    ⛔ content/docs/releases/ edits 0 ✓ — the release-owned fence held
    scope floor SCOPE_FLOOR_MAJOR = 16 ✓
    cutoff stated in the gate ✓ SCOPE_NOTE carries the verbatim ruling 「只负责 v16 以后的,需要的话之前的版本删除也可以的」 and is printed on both the failure and OK paths
    baseline / exception list none ✓ — nothing pre-compromised

    Both hazards were closed structurally, which is better than what I asked for

    I asked for a correct semver comparison. What landed is better: the gate never orders versions at all. Set membership only, so the sort -V trap has no surface to exist on.

    ⚠️ I nearly mis-flagged this. My grep for sort -V|sort(|localeCompare|semver returned 8 hits, which reads as a contradiction of that claim. Looking at them: six are comments documenting the trap, and the other two are [...majors].sort((a, b) => a - b) — sorting integer majors, where a - b is exact and prereleases do not appear. The count was not the answer; the location was. (Third time today that a hit count nearly produced a wrong verdict.)

    Hazard 2 is closed by direction rather than by care: the instrument is the in-tree CHANGELOG cross-checked against packages/spec/package.json, with git tags used only in the direction that cannot be wrong — a tag that exists proves a release shipped; an absent tag concludes nothing.

    And it proved that under the failure condition, not in theory. The dev's own container reproduced the exact defect I hit: git tag --list '@objectstack/spec@17*' yields rc.0/1/2/5/6 with no 17.0.0, while ls-remote shows it exists. On that clone the gate's OK line reads "corroborated by 1 local GA tag(s)" — degraded corroboration — and still passes v17 correctly. That is the guard working, observed, not asserted.

    The ablation is the strongest I have reviewed in this lane

    Four legs, each against a real historical file pulled out of git history rather than a synthetic fixture, each restored and verified byte-identical (sha256 + empty git status) before the next:

    • A — v17.mdx at its pre-fix ref ⇒ RED, 6 problems, v16/index untouched.
    • B — v16.mdx pre-fix ⇒ RED, 2 problems.
    • C — index.mdx pre-fix with both pages correct ⇒ RED, 3 problems.
    • D — the whole content/docs/releases/ directory as it stood on 2026-08-13, when both stale pages were live and CI was green ⇒ RED, 11 problems, all confined to v16/v17/index.

    ⚠️ Leg D doubles as the cutoff proof, and that is the part I would have forgotten to ask for. At that same ref v9.mdx said published at 9.0.0 (tag 9.11.0), v12.mdx 12.0.0 (tag 12.6.0), v14.mdx current: 14.5.0 (tag 14.8.0) — all measurably stale, all correctly unreported. So the gate is shown to catch and shown not to over-reach, from one measurement.

    Meta-ablation — the check I did not think to require

    a self-test that cannot fail is this defect one layer up

    Two legs, both discriminating: defanging a signal ⇒ self-test red on exactly the assertions naming it; adding a naive "any rc.N mention" signal ⇒ self-test red on the GREEN-page assertions and the live run went red on the correct v16 page.

    The honesty I want on the record

    my first meta-ablation was a NO-OP, not a pass — changing the blockquote line-join separator changed nothing because the following whitespace collapse re-joins regardless, so the mutation never reached the assertion and proved nothing

    ⇒ It caught its own mutation not reaching the assertion, reported it as proving nothing, and ran two real legs instead. That is the exact discipline — a mutant must be verified to test the failure you think it tests — applied to itself, unprompted.

    The two flagged notes — both correctly left alone

    1. A duplicated attribution footer was appended to the PR body by the platform at create time. Platform behaviour, not a second actor. ⛔ No action; ⛔ do not "clean it up" and risk touching a body another process writes.
    2. The labeler applied dependencies to a PR whose only package.json change is a scripts entry. Plausibly by design (any package.json touch). ⛔ Correctly not filed and not removed — removing another actor's label without knowing its rule is how label churn starts. I agree with the judgement; leaving as-is.

    Next: confirming the gate job conclusions on #8950, then ready → auto-merge → MERGED. ⚠️ It branched from a8189aef4 before #8945 landed, and #8945 also edits lint.yml + package.json. The PR body carries the resolution instruction; I will re-check those two hunks before arming.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

domain:devxDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatch

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions