Repository navigation
Conversation
…in REQUIRED_CONTEXTS The console-pin job no longer carries the console filter term in its job-level if: a first step reads the filter verdict once, every step that costs anything is step-gated on it, and an unaffected run concludes success with a NOT BUILT notice and step summary instead of skipped. The filter contract is kept one level down (anything but an explicit 'false' builds; merge_group widens to 'true'). The registry row returns ahead of its Settings half, with an authorized field that says approved-not-applied, and the tombstone is rewritten. Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx Co-authored-by: Claude <noreply@anthropic.com>
Round 1 moved the filter verdict from the job-level if into a first step that wrote it to a step output (steps.scope.outputs.affected). That verdict is shell-computed, so no declaration reader in the repo can follow it without trusting the shell, and a pin-only diff stopped deriving check:console-sha / check:console-injection. Every step now carries the filter term in the contract's own spelling (needs.filter.outputs.console != 'false'); the one step an unaffected run executes has the exact complement and writes the NOT BUILT notice and step summary. The job-level if stays !cancelled() alone, so the job still concludes on every run. Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx Co-authored-by: Claude <noreply@anthropic.com>
A job that must conclude on every run cannot carry its filter term in its job-level if (a false job if concludes skipped), so it carries it on each step instead. Read only at job level, such a job resolved to no population, and a pin-only diff derived neither check:console-sha nor check:console-injection. stepFilterPopulations reads a job whose own if is absent or !cancelled() alone step by step: each step whose if passes the same job-level whitelist (jobFilterOutputRefs, unchanged) contributes that population to the checks that step runs. The job-filtered tail walks the gated steps plus the job's other conditional ones, so a step whose if restates the population's own term is not counted as conditional, and the rest are still sized. Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx Co-authored-by: Claude <noreply@anthropic.com>
Fixture cases for a job whose filter term sits on its steps: the population resolves and reaches only the gated step's check; a step with no if, an inverted step, an AND with a refused term and a job-level if carrying another term are all refused; the job-filtered tail lists a step that restates the population term and sizes the rest. A live case pins that the Console Pin Gate population is read off its steps. The four live console cases are unchanged. Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx Co-authored-by: Claude <noreply@anthropic.com>
…nsole-pin-conclusion-every-pr
…ster Its job now concludes on every run (own if: !cancelled() alone, the console filter term on each step), so a skipped Console Pin Gate is no longer by design and reads as exit 4 like any other unrostered name. The measured 39-run head stays verbatim: its skipped Console Pin Gate is now the one unexpected skip (18 expected, exit 4). A derived copy with that one row concluding success carries the OK-path cases and the CLI exit-0 case. Two roster cases pin the absence and tie it to the live job's own if: carrying no filter output. Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx Co-authored-by: Claude <noreply@anthropic.com>
…sides of the click AGENTS.md's merge-queue sentence and the pm-dispatch readings ledger both state the required set. Console Pin Gate is registered in REQUIRED_CONTEXTS and blocks only once the maintainer adds it in Settings, so both now say seven block and an eighth joins on that click; "those seven" becomes "those eight" where the sentence means the names the registry pins. Both files stay at their line ceilings: the new words fill slack in an existing line and no text moved between lines. check-required-contexts: two comments re-worded for the step-level filter term and for the whole-file literal-scan residual. Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Sep 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #17673
Clause-②: no
Step 1 of ruling #18900 item ⑤ (comment 5727134555):
Console Pin Gatereports a conclusion on every PR (asuccesson an unaffected one), and it is enrolled inREQUIRED_CONTEXTS. Step 2 is adding it to the required set in Settings → Rulesets. That is the maintainer's click after this lands, and nothing here does it.Design: the filter term moves from the job onto its steps
console-pin's ownif:is now!cancelled()alone, so the job always runs and concludes. A job-levelif:that is false concludesskipped, and branch protection countsskippedas passing. That was the tombstone's cause.needs.filter.outputs.console != 'false'. Only an exact'false'skips a step, so a deadfilterjob still builds. Both halves of THE FILTER CONTRACT are kept, andmerge_groupstill widens the output to'true'.if:is the complement (== 'false'), and it writes a NOT BUILT notice and a step summary. Thatsuccessis the filter's verdict, not a build.steps.scope.outputs.affected). The repo's declaration readers cannot read that without trusting the shell, and that is what broke the dispatch-gates derivation. Each step'sif:now reads the filter output directly. The rest of round 1's design is kept.The three required-path reds round 1 found, and how each is addressed
check:required-contexts: the set-naming census needsplatform-readings.mdto name the eighth context. It now does (see below).check:pm-expected-skips:Console Pin Gateis removed from the skip-by-design roster, so a skipped one now exits 4. The measured 39-run head is kept verbatim, and itsConsole Pin Gateskip is now its one unexpected skip. A derived copy, with that one row concludingsuccess, carries the OK-path cases. Two new cases tie the roster's absence to the live job's ownif:.dispatch-gates: a job's path population was read only from its job-levelif:, so a pin-only diff stopped derivingcheck:console-sha/check:console-injection. The new rule (stepFilterPopulations): a job whose ownif:is absent or!cancelled()alone is read step by step. When a step'sif:passes the unchanged job-level whitelist, that step's checks get the population. The job-filtered tail walks the same steps. The 4 live console cases are unchanged. 12 new fixture cases and 1 live case pin the step-level shape.The instruction files stay true on both sides of the click
AGENTS.md: "seven block (eight once Settings addsConsole Pin Gate)". Where the sentence means the names the registry pins, "those seven" becomes "those eight".platform-readings.md: "objectstack 七个(Console Pin Gate已登记,入 Settings 即第八)".CI on this PR
ci.ymlis in theconsolefilter, so this PR gets an AFFECTED run:Console Pin Gatebuilds. ⛔ This PR does not exercise the unaffected leg (NOT BUILT,success) live. The conclusion read on this head is recorded in the os-dev-report on #17673.Verification (head d134f4c, after one merge of
origin/mainat 2cf9db7)node scripts/check-required-contexts.mjs: exit 0, 8 names pinned. Its--self-test: exit 0, 169 assertions.check-expected-skips --self-test: exit 0, 107 cases. Before this change it was 1 of 99 red.check-skill-line-ratchet: exit 0.AGENTS.mdis 1116 lines against a ceiling of 1116, andplatform-readings.mdis 469 against 469.dispatch-gates .objectui-sha: base 43e17b8 derives both console gates. Round 1's head fb32a5e derives neither. This head derives both again, via "CI job filter for 'Console Pin Gate'".check:workflow-status-functions,check:workflow-step-name-quoting,check-step-collectors,check-self-test-workflow-commands,check-ci-filter-parity,check:pm-skill-id-lint,check:pm-governed-proseandcheck:nul-bytesall exit 0. actionlint is not installed here (NOT MEASURED).dispatch-gates --self-test, the ablation that shows the new cases red on the job-level-only derivation, and the--commandssweep with--ranreconciliation. Their readings are in the os-dev-report onConsole Pin Gatenever runs on apackages/**change — so the one instrument AGENTS.md names for "did this removal break the pinned sibling?" is structurally absent on exactly the diffs that rule governs #17673.Landing
This PR touches governed surfaces:
AGENTS.md(Tier H) and.claude/**(Tier S). It lands only by the maintainer's hand or after an authorized approval, and it stays draft. There is no changeset because no published package changes (ci.yml,scripts/**and two instruction files).Generated by Claude Code