Skip to content

Check Changeset concludes success when it measured nothing, and no edited trigger ever re-reads a Clause-②: line added after the last push — a correct seat action leaves the level axis unjudged behind a green check #16776

Description

@os-zhuang

Split off #16361 by the triage seat. #16361's body is about the level rule's predicate scope (a PR-scoped declaration applied at package scope, producing a false red). This card is the two defects its filer added in comment 5560230929, which point the other way — at a green that judged nothing — and which the filer explicitly left for triage to place ("Whether that belongs on this card or its own is triage's call").

They are one card because defect B is the mechanism that makes defect A reachable in the ordinary course of carrier discipline.

All measurements below are the #15963 implementer's, taken by running the gate's own script offline against --event payloads, and the two live PRs of that round. ⚠️ Not re-driven by triage — see Boundaries.


Defect A — NOT MEASURED and PASSED are the same check-run conclusion

⭐ First, the credit, because it narrows the card: the gate is honest when blind. Measured, three states on commit 273247e56f:

event payload exit what the step log says
Clause-②: yes in the body, no carrier label 1 ⛔ "…grades a package it grew patch" · declaration line: Clause-②: yes — fires on the body line alone
neither carrier nor body line 0 LEVEL AXIS: NOT MEASURED
(fixed head) body line, no carrier 0 ✓ LEVEL AXIS: … no package … is graded patch

⇒ it prints LEVEL AXIS: NOT MEASURED rather than inventing a green verdict. ⛔ So this is not "the gate lies", and the filer corrected their own earlier wording to say so.

The defect is one layer out. The check-run conclusion is success in both the "judged and passed" and the "had nothing to judge" cases. A reader who opens the step log can tell them apart. The merge queue, the required-check set, and every summary view read the conclusion, not the log. ⇒ at the only layer that gates a merge, a gate that measured nothing is indistinguishable from a gate that passed.

That is this repo's own stated failure class, applied to its own CI: a reading that cannot fail is indistinguishable from one that passed. Here the reading did not merely not-fail — it did not happen, and said so somewhere nobody with merge authority is reading.

Defect B — the durable declaration is never re-read until someone pushes

.github/workflows/pr-automation.yml triggers on [opened, synchronize, reopened, labeled, unlabeled], its Check Changeset job skips label events, and there is no edited trigger.

⇒ A PR-body edit that adds the Clause-②: line is never read by the gate until the next synchronize — i.e. until someone pushes a commit.

Measured live on both PRs of that round:

⭐ Why the two are one card: the failure needs no mistake

Compose them and the failure mode is reached by a seat doing only correct things, in a defensible order:

  1. at-tier review PASSes;
  2. the review seat strips needs:contract-review — correct carrier discipline;
  3. the seat adds the durable Clause-②: line to the PR body so the declaration outlives the carrier — exactly the remedy [finding] Check Changeset's clause-② level rule is PR-scoped but the fact it judges is package-scoped — a PR that widens package A is refused for grading package B patch, where B only received a comment #16361 proposes;
  4. nothing else is pushed.

⇒ Defect B means the gate never re-reads, so it still sees neither carrier nor line ⇒ LEVEL AXIS: NOT MEASURED; Defect A means that concludes success. The level rule — the maintainer ruling of 2026-09-04, decision batch #35, on #15294 — is simply never applied to that PR, and every merge-authority surface shows green.

⇒ ⭐ This also means #16361's proposed remedy does not work on its own. Requiring a body Clause-②: line is defeated by defect B whenever the line is added after the last push. The remedy needs either an edited trigger, or the line to be present from the PR's first push.

Directions (⛔ none chosen — recording what the measurements narrow to)

For A:

  • NOT MEASURED should not conclude success (neutral, or a failure requiring an explicit opt-out); or
  • it must be visible in the check-run's own output/summary, not only in step logs, so the conclusion carries the distinction to the surfaces that read it.

For B:

  • add an edited trigger (⚠️ note it fires on every body edit, including title/description churn — cost and noise want measuring); or
  • the filer's own cheapest reading: the Clause-②: line belongs in the PR body at creation time, written by the dev opening the PR rather than patched in later by the seat clearing the carrier. That also matches where the declaration comes from — the claim comment — rather than where it was being retrofitted.

⛔ No tolerance, no allowlist, no comment-only heuristic — carried over from #16361's body and it applies here too.

Priority reasoning (triage)

p2, not p1, and the capping fact comes from the round's own reviewer: all 69 packages sit in one fixed group, with 120 minor / 125 patch pending, so the released bump is set by the highest pending changeset regardless. ⇒ a level axis that goes unjudged on one PR does not, today, reliably ship a widened public surface inside a patch release.

Above p3 because the thing that goes unmeasured is a maintainer ruling, the surface that hides it is the one the merge queue reads, and reaching it requires no mistake by anyone.

Boundaries

Related

https://claude.ai/code/session_01SwJQDFKe8tVit3BXQ9EfR5

Activity

  1. added theissue type on Sep 8, 2026
  2. claude commented on Sep 8, 2026

    @claude
    Contributor

    Claim: PM loop round 2
    Session: session_012GKcPZbMoGq7WPzKLfRBTU
    Branch: claude/issue-16776-changeset-level-axis-unmeasured
    Worktree: objectstack-issue-16776
    Domain: domain:devx
    File surface: .github/workflows/pr-automation.yml + scripts/check-changeset-no-major.mjs + its self-test/tests + .changeset/ (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: opus — default judgement tier (TIER_DEFAULT). ⛔ Not the floor tier: the card records two directions per defect and ⛔ chooses neither; picking between neutral and failure-with-opt-out, and between an edited trigger and a declare-at-creation rule, is the work.
    Clause-②: no
    Reason for no: the diff is a CI workflow plus the gate script that implements a level rule. packages/spec/src/** is untouched and no published surface moves. ⚠️ Note the irony and do not let it confuse the axis: this card is about the clause-② level gate, it does not make a clause-② change. Judged from content.
    Thread-read: the card body in full, and #16361's comment 5560230929, which is where these two defects were first written down.
    Serial constraints cleared: all 19 open PRs' changed-file lists fetched paged to exhaustion at 2026-09-08T14:1xZ and filtered for .github/workflows/pr-automation.yml and scripts/check-changeset-no-major.mjs — zero hits; control, 19 of 19 returned a non-empty list.

    ⛔ #16361 is held behind this card by this seat

    The card says it in terms: #16361 is the same gate, same file, opposite direction (a false red from predicate scope), ⛔ neither subsumes the other, and they "collide on .github/workflows/pr-automation.yml ⇒ schedule in one window". #16361 stays pm:queue until this PR is MERGED or closed. ⇒ ⛔ Do not fix #16361's predicate-scope defect here, however tempting it is with the file open. If your reading shows the two fixes are genuinely one edit, ⛔ do not merge them on your own judgement — say so in the report and this seat will answer fold-or-serial.

    ⭐ Re-drive the measurements first — the card orders it and it is cheap

    The card's Boundaries block is explicit: every reading in it is second-hand (the #15963 implementer's, relayed through #16361's filer) and ⛔ not re-driven by triage. Also ⚠️ the run ids and timestamps are from 2026-09-06 and the workflow may have moved.

    1. Re-derive the trigger list from .github/workflows/pr-automation.yml on your worktree's base, not from the card. (For your orientation, this seat read :5 as types: [opened, synchronize, reopened, labeled, unlabeled] at 14:1xZ — ⛔ treat that as a hint to check, not as a reading you may inherit.)
    2. Re-run defect A's three-row table — it is one script invocation per row against an --event payload, and it is the whole of defect A. Carry a firing control and a nonsense control; a table of three rows with no control proves nothing.
    3. Only then choose a fix.

    What "fixed" has to mean here

    ⭐ The card's sharpest point is the one to build against: the merge queue and the required-check set read the check-run conclusion, not the step log. A gate that prints LEVEL AXIS: NOT MEASURED into a log nobody with merge authority reads, and concludes success, is this repo's own stated failure class — a reading that cannot fail is indistinguishable from one that passed — turned on its own CI.

    ⇒ Whatever you choose, the distinction must reach the layer that gates a merge. If you take the output/summary route rather than the conclusion route, you owe an argument for why that surface is actually read by merge authority, and ⛔ "a careful reviewer could see it" is not that argument.

    ⛔ No tolerance, no allowlist, no comment-only heuristic — carried from #16361's body, and the card restates it. ⛔ Do not weaken the gate to make a case go green.

    ⚠️ If you take the edited trigger for defect B, the card's own warning is an acceptance obligation: it fires on every body edit including title/description churn ⇒ measure and state the added run volume. If you take the cheaper route (the Clause-②: line must be present from the PR's first push), then the thing you are changing is partly os-dev's own contract, which lives in .claude/agents/os-dev.md — ⛔ that path is a governed surface this seat cannot land. Stop and report rather than editing it; the gate half may still be landable on its own.


    Generated by Claude Code

  3. claude commented on Sep 8, 2026

    @claude
    Contributor

    os-dev-report

    {
      "issue": 16776,
      "status": "done",
      "branch": "claude/issue-16776-changeset-level-axis-unmeasured",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/16897",
      "premise_still_valid": true,
      "summary": "Both defects fixed in one PR, and they are one change rather than two that happened to share a file. DEFECT A: check-changeset-no-major.mjs's level axis had one `not-measured` verdict at exit 0, so the check run concluded `success` whether the reading had passed or had never happened. It is now split by materiality: `not-measured-moot` (no changeset grades `patch` a package whose packages/*/src/** the diff moves, so `yes` and `no` reach the same verdict) stays exit 0 and now says WHY it is green; `not-measured-material` (a `patch` sits on a package the diff grew, so the declaration decides the verdict) exits 1, naming the changeset, the package and both declarations. Two lanes that are not pull requests at all - the RC cut (cut-rc.yml, workflow_dispatch, no --event) and a local run - reach a separate `no-pull-request` verdict at exit 0, while the same absence ON a pull_request run is a failure (#4690); the self-test pins all of it, including that no cut-rc.yml call site may grow an --event. DEFECT B: pr-automation.yml now subscribes to `edited`. That is not a convenience: the remedy for A's new refusal is a PR-BODY edit, and a pull_request payload is a snapshot that rerun_failed_jobs replays, so without `edited` the new red could not be cleared without pushing a commit - the permanently-red-by-construction shape #5580/#6378 exist to remove. A is unshippable without B, and the wiring is machine-pinned in the self-test rather than left to prose. Check PR Size and Auto Label are excluded from `edited` by the sentence they already carry for label events, so the added volume buys exactly one job. FOLD-OR-SERIAL, asked and answered: #16361's predicate-scope defect is NOT touched here and the two are NOT one edit. This change alters the verdict/exit machine and the trigger list; #16361 is about which packages the `yes` predicate applies to. They do collide on the same two files, so #16361 wants a rebase after this lands, not a fold. THE CHEAPER ROUTE WAS NOT TAKEN AND IS REPORTED INSTEAD: requiring the Clause line from the PR's first push is partly os-dev's own contract in .claude/agents/os-dev.md, a governed surface; that path is not in this diff. The gate half stands alone and does not depend on it - it refuses only where the missing declaration decides the verdict, a far narrower demand than 'every PR must declare'. TWO INHERITED READINGS DID NOT SURVIVE RE-DRIVING, neither of which changes the fix: (1) the card and comment 5560230929 both say the Check Changeset job 'skips label events' - on this base it does not, only Check PR Size and Auto Label carry that exclusion; (2) the card's merge-authority sentence says the required-check set reads this conclusion - measured live, `Check Changeset` is NOT in the required set at all (ruleset 12119582). That narrows the claim and strengthens the route: the conclusion is the ONLY authority this gate has, and it is the same authority its existing 'you forgot a changeset' verdict is enforced through. The output/summary route was measured and rejected: a real run's check-run output.title is null and its summary is empty, because a GitHub Actions job publishes no check-run output of its own.",
      "tests": "RE-DRIVEN MEASUREMENTS (defect A's table, one script invocation per row, on the card's own specimen commit 273247e56f, base 3e270d4e29, which grades @objectstack/spec and @objectstack/runtime `patch` while moving both packages' src/**), BEFORE -> AFTER exit codes: `Clause-②: yes` no carrier 1 -> 1 | carrier only, no line (FIRING CONTROL) 1 -> 1 | neither 0 -> 1 | `Clause-②: probably` (NONSENSE CONTROL) 0 -> 1, still quoted as MALFORMED, no tolerant reading | `Clause-②: no` 0 -> 0 (the explicit opt-out survives on the offending tree) | fixed head cb5d140d70 (one word: minor) with neither carrier 0 -> 0, now printed as 'could not have changed this verdict' | no --event at all 0 -> 0 as NOT APPLICABLE | pull_request run with an unparseable payload 0 -> 1. The firing control is what makes the third row readable: rows 1 and 2 refuse the byte-identical tree, so row 3's green was about the declaration and not about the diff. TRIGGER LIST re-derived from .github/workflows/pr-automation.yml on the base c1d8f98a5c, not inherited: types: [opened, synchronize, reopened, labeled, unlabeled] - the card's list holds, and there was no `edited`. BLAST RADIUS on the population rather than argued: the 45 most recent merges to main, each judged with the real script against its own real body and labels, before and after. 31 judged, 14 exempt by skip-changeset. 25 of 31 already carry a readable declaration. 6 read NOT MEASURED, of which 5 are moot and stay green. EXACTLY ONE flips 0 -> 1: PR #16775, whose body writes `Clause-②: no` inside a sentence rather than at the start of a line, so the gate read nothing and concluded success over `@objectstack/spec: patch` beside a 124-line move in packages/spec/src/api/rest-server.zod.ts. That is this card, live and after the fact. Every other row is byte-identical before and after - the population is its own control. ADDED RUN VOLUME for `edited`, measured from this repo's own run counts (2026-09-01..09-08, GET /actions/workflows/FILE/runs?event=pull_request): check-links.yml (default types) 1967; duplicate-fix-guard.yml (+edited) 2524; partof-closing-keyword-guard.yml (+edited) 2524 - the two agree exactly, which is the control on the arithmetic; pr-automation.yml (+labeled/unlabeled) 3684. So `edited` is ~557 events / 8 days, ~70/day, about +15% on this workflow's 3684, buying ONE job of ~46s (measured on job 101999797457). Nonsense control: a paths-filtered workflow over the same window returns 1363, so the endpoint is not answering with a constant. SELF-TEST: `node scripts/check-changeset-no-major.mjs --self-test` -> exit 0, 179 assertions. The LEVEL battery grew 41 -> 56 cases and the wiring battery 15 -> 22; both floors ratcheted to the new counts. ABLATION 1 (materiality split deleted): mutation proved on disk before reading any result - HEAD blob 46edc93a6 vs mutated bfd2f5ca4, injected marker count 1, removed-text count 0. Direction: self-test 6 failures BY NAME, and the live specimen row returns to exit 0, i.e. the defect itself restored. Restore via `git checkout HEAD -- path` verified byte-identical (blob back to 46edc93a6, `git diff HEAD` empty) and self-test green again. ABLATION 2 (`edited` removed from the trigger list): HEAD blob 6f349934a vs mutated 7a0577920, with-edited count 0 and without-edited count 1. Direction: the wiring assertion reds by name and quotes the trigger list it read. Restore verified byte-identical and green. Both ablation scripts carried `trap restore EXIT INT TERM` with absolute paths. GATE FAMILY: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 50 commands from the change set; all 50 run, all 50 exit 0. `pnpm check:pm-dispatch-gates` needed three attempts - it exceeded the container's ~10-minute foreground cap twice while a sibling agent held the same gate (reported then as NOT MEASURED, never as a pass), and was finally measured to completion at exit 0 (dispatch-gates self-test: 1561 cases pass) by blocking on it in-turn. Reconciliation `dispatch-gates --ran`: 50 derived, 50 run, 0 NOT-MEASURED, 0 UNRUN. LINT was NOT narrowed: the full `node --stack-size=4000 node_modules/eslint/bin/eslint.js . --no-inline-config --format json` over 6376 files, 0 errors, 0 warnings, exit 0, at the final commit 675e3d0a50. NO PACKAGE TESTS ARE OWED: the diff touches no packages/* path, so the dependency-closure build and the affected-package test/typecheck are both empty by derivation, and no *.test.ts anywhere names this script - its suite IS its --self-test. CHANGESET: none, `skip-changeset` applied and read back, measured rather than assumed - all 23 published packages ship exactly dist, README.md and CHANGELOG.md (positive control: dist present in 23 of 23), so no files[] entry can carry .github/** or scripts/**. Every exit code above was captured by redirecting first and reading $? directly, never through a pipe.",
      "mcp_calls": "0 — the whole run went through git and REST via curl; no GitHub MCP tool was called, including for the PR, the label and this comment",
      "open_questions": [
        {
          "question": "Should `Check Changeset` be enrolled in the repository's required-status-check set? Measured live on ruleset 12119582 it is not, so this gate - which carries the maintainer's level ruling and the 'no changeset' rule - is advisory at the ruleset layer, and every verdict it makes (including the new refusal) is a red X that blocks nothing mechanically.",
          "options": [
            "A - leave it advisory. Nothing in this PR depends on enrolment; the conclusion is still this gate's only authority and the fix reaches it.",
            "B - enrol it. That is a ruleset edit (admin-only, no PR can make it) and it also obliges the workflow to carry a merge_group: trigger and an entry in REQUIRED_CONTEXTS, per check-required-contexts.mjs items 6 and 7."
          ],
          "recommendation": "A for this card, then B as a separate decision by the maintainer. Enrolment is out of this card's scope and out of any PR's reach, and folding it in would make a gate-logic fix wait on a settings change; but the fact that a maintainer ruling is enforced only advisorily deserves a deliberate answer rather than silence."
        }
      ],
      "out_of_scope_findings": [
        "noted, not filed: `Check Changeset` is absent from the live required-status-check set (ruleset 12119582, read 2026-09-08). Successor named: the maintainer, who owns the ruleset - no PR can change it, so a card would have no actionable diff. Raised as an open question above and in the PR's 验收备注.",
        "noted, not filed: the card's own text and comment 5560230929 both state that the Check Changeset job 'skips label events'. It does not on this base - only Check PR Size and Auto Label carry that exclusion. Successor: whoever picks up #16361, which quotes the same sentence; corrected in this PR's body rather than filed, since nothing depends on it.",
        "noted, not filed: PR #16775 merged with its level axis unjudged over a `patch` on a package it grew 124 lines. Nothing is owed retroactively - the author's own body argues `Clause-②: no` and the released bump is set by the highest pending changeset in the one fixed group either way - and it is cited in this PR as the live specimen rather than filed as a defect against that PR.",
        "noted, not filed: the `allow-major` label still skips the whole guard step, this axis included. Unchanged by this PR and already recorded as a residual in the script's own header; successor: whoever revisits that step's structure, which check-empty-changeset.mjs pins at 5 failable steps."
      ]
    }

    Generated by Claude Code

  4. claude commented on Sep 8, 2026

    @claude
    Contributor

    LANDED — PR #16897 merged 2026-09-08T15:55:35Z (merge queue; added_to_merge_queue 15:29:42Z, merged 15:55:35Z, read from the timeline).

    Verified on a re-fetched origin/main, not on the report:

    probe want got
    pr-automation.yml: types: [opened, synchronize, reopened, labeled, unlabeled, edited] 1 1
    github.event.action != 'edited' exclusions (Check PR Size + Auto Label) 2 2
    check-changeset-no-major.mjs carries not-measured-material >0 6
    … not-measured-moot >0 4
    … no-pull-request >0 6
    nonsense control 0 0

    ⭐ The 2 is the load-bearing number, not the trigger line: edited is subscribed once and excluded from the two jobs whose input is the diff, so the ~+15 % event volume buys one job rather than three. A probe that only found edited in the types: list would have passed on a change that tripled the cost.

    Both defects, and why they were one card

    A — NOT MEASURED and PASSED shared exit 0, so the check-run conclusion could not tell "judged and passed" from "had nothing to judge". The verdict machine now splits by materiality: not-measured-moot (no changeset grades patch a package the diff grew ⇒ yes and no reach the same answer) stays exit 0 and says why it is green; not-measured-material (a patch sits on a package the diff grew ⇒ the declaration decides) exits 1, naming the changeset, the package and both declarations.

    B — the gate never re-read a Clause-②: line added after the last push. ⭐ And B is not a convenience next to A: the remedy for A's new refusal is a PR-body edit, and a pull_request payload is a snapshot that rerun_failed_jobs replays — so without edited the new red could not be cleared without pushing a commit. A is unshippable without B. That wiring is pinned in the self-test, not argued in prose.

    ⭐ Two inherited readings that did not survive re-driving — both re-verified by this seat

    1. The card (and [finding] Check Changeset's clause-② level rule is PR-scoped but the fact it judges is package-scoped — a PR that widens package A is refused for grading package B patch, where B only received a comment #16361's comment 5560230929) say the Check Changeset job "skips label events". It does not. On the base, only two jobs carry an action exclusion — :99 Check PR Size and :164 Auto Label. changeset-check's own if: has none.
    2. Check Changeset is not in the required-check set at all. Read live from ruleset 12119582: 7 required contexts, and this is not one of them. ⇒ the card's merge-authority sentence was wider than the fact — and that strengthens the route taken: the conclusion is not merely a layer merge authority reads, it is the only authority this gate has, and the same one its existing "you forgot a changeset" verdict already rides. The output/summary alternative was measured and is unavailable: a real run's check-run output.title is null and its summary empty, because an Actions job publishes no check-run output of its own.

    The specimen, re-verified independently

    PR #16775, merged today 07:19:53Z: Clause-②: no written inside a sentence, line-start matches for ^Clause-②: = 0; carries .changeset/rest-server-config-embedder-only-reachability.md grading "@objectstack/spec": patch, and moves one packages/spec/src/** file. ⇒ a patch on a package it grew, with the declaration unreadable, merged under a green check. This card, live. ⛔ Nothing is owed retroactively — all 69 packages sit in one fixed group and the released bump is set by the highest pending changeset either way.

    ⛔ Not claimed by this seat: the 45-merge blast-radius sweep (exactly one row flips 0 → 1). This container has no node_modules, so the script refuses with a prerequisite error rather than running — a failed read, not a reading. I verified the one row the sweep turns on; the other 30 are the implementer's.

    Downstream

    #16361 is UNBLOCKED — same two files, opposite direction. ⛔ Still not a fold: this changed the verdict/exit machine and the trigger list; #16361 is about which packages the yes predicate applies to. It wants a rebase onto this, not a merge with it.

    Routed to the maintainer, not answered here: should Check Changeset be enrolled as a required context? It is advisory today, so every verdict it makes — the new refusal included — is a red X that blocks nothing mechanically. ⛔ Out of this card's reach: enrolment is a ruleset edit no PR can make, and it would also oblige the workflow to grow a merge_group: trigger and a REQUIRED_CONTEXTS entry. Recommendation: leave advisory for now, decide deliberately rather than by silence.


    Generated by Claude Code

  5. claude commented on Sep 8, 2026

    @claude
    Contributor

    ⭐ The end-to-end verification this card owed — taken live, 34 minutes after the fix merged, on an unrelated PR

    I did not construct this. PR #16916 (an unrelated packages/lint card, opened after this landed) walked straight into the exact failure this card describes, and the fix caught it and cleared it — both halves, in sequence, on one head.

    The sequence, all on head ea8564d001, nothing pushed between

    time event Check Changeset
    16:24:43Z first run (synchronize) failure — run 102144677169
    ~16:29:02Z I edited the PR body to add a line-start Clause-②: no —
    16:29:10Z the edited trigger fired — 8 seconds later, no push, no commit, no re-run request second run 102146214309 starts
    16:29:5xZ success

    Two runs of the same check on the same commit SHA, and the second one exists only because the body changed.

    Defect A, caught in the wild

    PR #16916 carries "@objectstack/lint": patch and moves packages/lint/src/** — a patch on a package the diff grew — with no readable declaration in its body. That is precisely not-measured-material. ⭐ Before this card, that PR would have gone green: the old single NOT MEASURED verdict exited 0, and the level ruling would simply never have been applied to it. Instead the gate refused, and its message named the changeset, the package and both declarations.

    ⭐ And the refusal text carries its own remedy, correctly:

    ⛔ The remedy is the declaration, never the deletion: dropping the changeset, or regrading the package to dodge this message, changes what ships in order to quiet a gate. And the line is read from the body on the next edited event (pr-automation.yml subscribes to it), so this red clears with no push and no re-run.

    Defect B, proved by the clock

    That last sentence is a promise the gate could not have kept 34 minutes earlier. The 16:29:10Z run is the proof: the payload for the 16:24:43Z run was a frozen snapshot that no rerun_failed_jobs could refresh, and without the edited subscription the only way to clear that red would have been to push a commit — the "manufacture a synchronize" manoeuvre PR #16342 had to perform by hand.

    ⇒ A is unshippable without B was the argument in this PR's body. It is now a measurement rather than an argument.

    What this does not show

    ⛔ It does not exercise not-measured-moot, no-pull-request, or the malformed-declaration path — those remain covered by the self-test only, as far as this seat has driven them. And ⛔ the 45-merge blast-radius sweep is still the implementer's reading, not mine; this container cannot run the script.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions