ci: grade only open pull requests against the linked-issue policy - #144
Kartikey1306 wants to merge 9 commits into
Conversation
93f3e12 to
3708afb
Compare
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
3708afb to
9368a0d
Compare
srpatcha
left a comment
There was a problem hiding this comment.
Review — ebuild#144 "ci: grade only open pull requests against the linked-issue policy"
head: 9368a0d author: Kartikey1306 ci: pending
Verdict: The one commit this PR owns (9368a0d, .github/workflows/linked-issue.yml, +6/−0) is correct and does not weaken the gate — if: github.event.pull_request.state == 'open' stops a body edit on a merged PR from grading a tree nobody can change, and leaves the open-PR path untouched. I verified the premise and the parsed structure myself rather than accepting the PR body's table. The problem is reach, not correctness: the same caller is byte-identical in 19 repositories, not the three this batch touches.
Findings
| # | Severity | File:line | Finding | Recommended fix |
|---|---|---|---|---|
| 1 | Medium | .github/workflows/linked-issue.yml:14 |
The guard is being pasted into 3 of the 19 repos that carry this caller. I hashed origin/master:.github/workflows/linked-issue.yml across the working root: 19 repos, all sha256:120e9f40a521…, byte-identical (eAI, eApps, eBoot, eBrowser, ebuild, eCAD-Hardware-Products, eDB, eFirmware, eIPC, embeddedos-org, embeddedos-org.github.io, eNI, eOffice, eos, eos-aero, EoSim, eosllm, EoStudio, www.embeddedos.org). The other 16 keep grading merged and closed PRs on every body edit — the exact defect this PR exists to remove. The PR body says "the caller is byte-identical in each" of three repositories; it is byte-identical in nineteen. |
Put the guard on jobs.linked-issue in the shared reusable workflow embeddedos-org/.github/.github/workflows/linked-issue-policy.yml instead. A called reusable workflow evaluates github.event.* against the caller's event, so the expression works unchanged there and fixes all 19 consumers from one place. The uses: pin is already propagated org-wide by Dependabot (6 open bump PRs today), so the pin bump is mechanical. If the guard must stay caller-side, say so here and open the remaining 16 — leaving 16 repos on the broken behaviour is not a finished fix. |
| 2 | Low | PR scope (not the commit) | Stacked on #132, and mergeable is MERGEABLE. Merging as-is lands #132's diff too: 14 files, +188/−16, across ebuild/packages/recipe.py, ebuild/plugins/__init__.py, .gitattributes, scorecard.yml, auto-assign.yml and four test files — under a ci: title with a CI-only review. Only mergeStateStatus: BLOCKED prevents that; nothing mechanical does. Lower severity than the eBoot sibling because nothing carried here touches a trust boundary. |
Do not merge before ebuild#132. Land #132, rebase, and let this drop to its one commit. #132's content was reviewed by this pipeline at this exact head — see reports/ebuild-132-43b03374.md; it is not re-reviewed here. |
| 3 | Low | PR body, line 1 | "Review 43b0337..3708afb for this change" — 3708afb does not exist in this repository (git cat-file -t 3708afb → Not a valid object name). The head is 9368a0d. A reviewer following the instruction literally gets an error. The same defect is in eBoot#125 (cbc064b) and eos#154 (7a1d1e7); none of the three end shas resolve in any of the three repos. |
Use 43b0337..9368a0d, or drop the sha and say "the single commit at the head of this branch". |
| 4 | Low | PR body, Verification table | Four rows read PASS with no command output, which .ai/reviewer.md and the review brief (§5) treat as the finding regardless of whether the claim is true. Recorded for the missing evidence only — I re-ran all four against this repository and they hold. Note that the same table in the sibling eos#154 does not hold; see that report. |
Paste the command and its output, not a table of verdicts. |
Architecture conformance
Conforms. Master design §21 places CI templates in the Infrastructure tier, and this change is a workflow-level if on a governance check — no import, no link line, no manifest entry, no runtime dependency, so §5.1's direction-of-dependency law is untouched. §9/§9.2 make ebuild the developer control plane; nothing here alters the CLI, the dependency graph or the build surface. The one architectural tension is Finding 1: §21 assigns CI templates to Infrastructure, yet this puts policy semantics into 19 product-repo callers where they can drift. That gap in the design text is written up as a proposal in proposals/2026-09.md (2026-09-14 — "Shared CI policy: the caller/reusable-workflow contract is undefined").
Proposed changes
- Move the guard up one level, in
embeddedos-org/.github:then bump thejobs: linked-issue: name: Policy / Linked Issue # pull_request_target fires on `edited` for closed and merged PRs too. # A merged PR cannot be changed to satisfy the policy. if: github.event.pull_request.state == 'open' runs-on: ubuntu-latest
uses:pin in the callers. Behaviour-identical for open PRs in all 19 repos, and it removes the copy from each. - Keep this PR's caller-side guard only if (1) is rejected — and then open the other 16.
- Fix the review range in the body to
43b0337..9368a0d. - Merge #132 first; rebase this onto it so the PR is its one commit.
Not checked
- CI is pending, not failing. At bundle time (roughly 4 minutes after the PR opened) all ten
Test (Python 3.10/3.11/3.12 × ubuntu-22.04/macos-latest/windows-2022)legs andAnalyze (Python)werependingwith 0s elapsed. I did not wait for them and I am not scoring them either way. Everything that had finished was green, includingpolicy / Policy / Linked Issue(6s) andSimulation Sanity Gate.mergeStateStatus: BLOCKED. - I did not execute the workflow. No GitHub Actions run can be triggered from here, so the guard's runtime behaviour on a real
edited-on-merged event is unverified by execution. What I did verify:- Structure — parsed the file at
9368a0dwithyaml.safe_loadand asserted on the parsed document:jobsis exactly['policy'],ifis"github.event.pull_request.state == 'open'"and sits on the job,usesstill pins@92cb596c…,with.policy_refunchanged, trigger types still[opened, edited, reopened, synchronize],permissionsunchanged. PASS on ebuild, eBoot and eos; all three resulting files hash identically (fafeb8d17c7b). - The premise —
gh run list --workflow "Linked issue policy" --status failureshows exactly 11 failing runs on 2026-09-14 in this repository (20:25:19–20:25:45Z). I resolved every head branch to its PR and checked its state: #66, #67, #94, #95, #97, #98, #99, #102, #106 MERGED; #100, #101 CLOSED. All 11 are merged or closed — the body's claim is correct for ebuild. - Not redundant with the upstream bump — the newer policy commit
186aef0dthat Dependabot is proposing org-wide contains no state guard either, so this fix is not already upstream.
- Structure — parsed the file at
- Effect on branch protection not verified. I did not read branch-protection settings, so whether
policy / Policy / Linked Issueis a required context — and how a skipped job is scored — is unconfirmed. It does not affect open PRs, where the guard is true and the job runs as before. - The ebuild working tree is dirty (4 files, reported by the sync step) and was left untouched. Everything above was read from
origin/masterand from a fetched read-only ref; no checkout, stash or reset was performed. The clone was therefore never at this PR's tree, so no build or test was run against it locally. - #132's content is not re-reviewed here, per the brief's rule against repeating a point already made; see
reports/ebuild-132-43b03374.md.
Automated architecture review of 9368a0de262b — scheduled, model claude-opus-5, checked against the EmbeddedOS Master Design v2.0. Advisory only: this reviewer never approves, requests changes, or merges. Reply here to discuss or push back — a wrong finding is a bug worth reporting.
|
Finding — the guard belongs in the reusable job, not in 3 of 19 callers: agreed, and done at the source: embeddedos-org/.github#9 puts Stacked-merge risk: agreed that only The review range: the SHAs stopped resolving because the branch was re-triggered with a no-content push after the body was written. The body now says "the single commit at the head of this branch", which survives that. Verification table without output: replaced with the commands and their output. Nothing pushed to this branch; the content is the same one commit. |
9368a0d to
20f69dc
Compare
|
Restacked onto #132's current head Verified at No review to re-request — this PR had no approval. Land #132 first, as the body says. |
srpatcha
left a comment
There was a problem hiding this comment.
Review — ebuild#144 "ci: grade only open pull requests against the linked-issue policy"
head: 20f69dc author: Kartikey1306 ci: pass — 31 checks green, none failing, Create GitHub Release skipped by design
Verdict: Follow-up on the restack onto #132's new head f4788f2. This PR's own commit is
byte-identical to the one reviewed at 9368a0de (git diff 9368a0de 20f69dc8 -- .github/workflows/linked-issue.yml is empty; the whole 9368a0d→20f69dc8 delta is
tests/ebuild/test_package_recipe.py | 6 ++++++, which belongs to #132). Two of the four
prior findings are resolved, one is addressed at the right level but not landed, one is
unchanged and accepted. CI is now fully green where it was pending. Nothing new to find in
the commit itself.
Follow-up on the previous review
| Prior # | Sev | Status | Evidence at this head |
|---|---|---|---|
| 1 | Medium (P2) | Addressed at the right level, not yet landed — still open | The author moved the guard into the reusable workflow, which is exactly the recommended fix: embeddedos-org/.github#9 "policy: grade only open pull requests against the linked-issue policy" touches .github/workflows/linked-issue-policy.yml (+8) and tests/community/test_linked_issue.py (+29). But it is state: OPEN, mergedAt: null, mergeStateStatus: UNSTABLE. I re-hashed origin/master:.github/workflows/linked-issue.yml across the working root: 19 repos, all sha256:120e9f40a521…, and grep -c "pull_request.state == 'open'" is 0 in every one of them (eos-health does not carry the file). The defect is still live in all 19 until #9 merges and the pins are bumped. |
| 2 | Low (P3) | Acknowledged, unchanged | Still stacked: 9 commits between origin/master and this head, of which 8 are #132's. mergeable: MERGEABLE, and only mergeStateStatus: BLOCKED prevents a merge from landing #132's diff under a ci: title. The author's answer — that the pipeline reviewed the base at this exact head and the real fix is a merge-queue rule, not a per-PR guard — is reasonable and I accept it. reports/ebuild-132-f4788f2c.md exists, so the base is reviewed at f4788f2. |
| 3 | Low (P3) | Resolved | The body's first line now reads "Review the single commit at the head of this branch for this change: one file, .github/workflows/linked-issue.yml, +6/−0" and explains why the sha range was dropped. No unresolvable sha remains in the body. |
| 4 | Low (P3) | Resolved | The verdict table is gone; the body now carries two commands with output. I re-ran both — see below; both hold. One nit, not a finding: the first block's "output" is a prose summary ("19 runs on 2026-09-14; 11 distinct merged/closed branches…"), not the literal sort -u output the $ line would produce. The second block's ok is literal. |
Review of the new commits on their own merits
There are none belonging to this PR. The single commit 20f69dc is 9368a0d replayed onto
f4788f2, verified byte-identical in the only file it touches. f4788f2 itself is #132's
content and was reviewed by this pipeline at that exact head; per the brief it is not
re-reviewed here.
Findings
| # | Severity | File:line | Finding | Recommended fix |
|---|---|---|---|---|
| 1 | Medium (P2) | .github/workflows/linked-issue.yml:14 |
Carried forward, now in progress. The guard is caller-side in this repo while 19 repos carry the unguarded caller byte-identically. The correct fix exists as embeddedos-org/.github#9 but is unmerged, so nothing is fixed anywhere yet. |
Land .github#9, bump the uses:/policy_ref pin here (both currently @92cb596c…), and then either drop this caller-side guard or keep it explicitly as belt-and-braces. If #9 stalls, this PR is the only thing fixing 1 of 19 repos and the other 18 need the same commit. |
| 2 | Low (P3) | PR scope, not the commit | Carried forward and accepted. Merging this before #132 lands #132's 8 commits under a ci: title. |
Land #132 first, as the body says. |
No new findings. The change itself is correct: if: sits on jobs.policy, not on a step —
verified against the parsed document, which matters because a step-level if would still
start the job and report a status — and the trigger types, uses: pin, policy_ref and
permissions are unchanged, so nothing is weakened for an open PR.
The guard does not suppress a check anyone can still act on. I resolved every branch with a
failing Linked issue policy run on 2026-09-14 to its PR state: 11 are MERGED or CLOSED (#66,
#67, #94, #95, #97, #98, #99, #101, #102, #106, #100) and 5 are OPEN (#123, #124, #125, #133,
#141). The five open ones keep failing with this guard in place, which is correct — #123 in
particular is a live PR this pipeline has findings open against. The body says "6 open"; it is
5 at the time of this review, and the run count has moved from 19 to 46 as the day went on.
Both are timestamp drift on a moving counter, not an error in the material claim, which is
that all 11 non-actionable failures are on merged or closed PRs. That is exact.
Architecture conformance
Conforms. §21 places CI templates in the Infrastructure tier; this is a workflow-level
if on a governance check — no import, no link line, no manifest entry, no runtime dependency,
so §5.1's direction-of-dependency law is not engaged. §9/§9.2 make ebuild the developer
control plane; nothing here alters the CLI, the dependency graph or the build surface.
The architectural tension behind finding 1 — §21 assigns CI templates to Infrastructure, yet
the policy's semantics live in 19 product-repo callers where they drift — was written up on
2026-09-14 in proposals/2026-09.md ("Shared CI policy: the caller/reusable-workflow contract
is undefined"). No new proposal appended: .github#9 is the design working as the existing
proposal recommends, and nothing at this head reveals a further gap.
Proposed changes
1. Land embeddedos-org/.github#9. It is the fix for all 19 repos; this PR is
the fix for one. It is currently UNSTABLE — clear that first.
2. Land ebuild#132, rebase this, and let it drop to its one commit.
3. Bump uses:/policy_ref here from 92cb596c once #9 is in, and say in this
PR whether the caller-side guard stays or goes.
4. Optional, one line: make the first verification block show the actual
branch list `sort -u` prints rather than a count of it.
Verification performed for this review
The ebuild checkout has a dirty working tree (TASKS.md, ebuild/cli/integration.py,
tests/ebuild/test_integration_initramfs_security.py modified, smart-sensor/ untracked) and
was not touched — no worktree, checkout, stash or reset. The PR head was not present
locally, so it was fetched read-only into refs/autoreview/pr144, and everything below ran
against git archive 20f69dc8 | tar -x into a temporary directory outside the repository.
| Check | Result |
|---|---|
git diff 9368a0de 20f69dc8 -- .github/workflows/linked-issue.yml |
empty — the PR's own commit is unchanged since the last review |
git diff --stat 9368a0de 20f69dc8 |
tests/ebuild/test_package_recipe.py | 6 ++++++ — #132's content only |
git show --stat 20f69dc8 |
one file, .github/workflows/linked-issue.yml, +6/−0 |
ruff 0.16.5 check . |
PASS — "All checks passed!" |
pytest 9.1.1 tests/ -q (CPython 3.12, deps click/pyyaml/ninja from pyproject.toml) |
PASS — 683 passed, 1 skipped in 5.62s. Exactly the numbers the author's comment claims |
Parsed-structure assertion on linked-issue.yml |
jobs: ['policy']; if on the job = "github.event.pull_request.state == 'open'"; no step-level if; uses …@92cb596c773496ec4df76717e8acf0e6b7700f73; policy_ref same; types [opened, edited, reopened, synchronize]; permissions {contents: read, issues: read, pull-requests: read} |
All 16 workflow files parse with a jobs map |
PASS, 0 bad |
sha256 of origin/master:.github/workflows/linked-issue.yml across the working root |
19 repos, all 120e9f40a521…; guard count 0 in all 19 |
gh pr view 9 --repo embeddedos-org/.github |
OPEN, mergedAt: null, mergeStateStatus: UNSTABLE, touches linked-issue-policy.yml (+8) and tests/community/test_linked_issue.py (+29) |
Failing Linked issue policy branches on 2026-09-14, resolved to PR state |
16 distinct branches: 11 MERGED/CLOSED, 5 OPEN. The premise holds |
CI on this head (checks.txt) |
31 pass, 0 fail, incl. policy / Policy / Linked Issue (6s), CodeQL, Analyze (Python), 9 Test (3.10/3.11/3.12 × ubuntu/macos/windows) legs, 11 EoSim targets, CI Gate, Simulation Sanity Gate. Create GitHub Release skipping, by design on a PR |
| PR metadata | mergeable: MERGEABLE, mergeStateStatus: BLOCKED, reviewDecision: REVIEW_REQUIRED |
Not checked
- The workflow was not executed. No GitHub Actions run can be triggered from here, so the
guard's runtime behaviour on a realedited-on-merged event remains verified by structure
and premise, not by observing a suppressed run. The same limitation as the previous review. - Effect on branch protection still not verified. I did not read branch-protection
settings, so whetherpolicy / Policy / Linked Issueis a required context — and how a
job skipped by a falseifis scored against a required context — is unconfirmed. It does
not affect open PRs, where the guard is true and the job runs as before. embeddedos-org/.github#9was not reviewed. Only its state, base, files and line counts
were read viagh pr view. Its test (tests/community/test_linked_issue.py) and the
mutation evidence the author describes in the comment thread are unverified here; #9 is a
different repository and not in this run's manifest. ItsmergeStateStatus: UNSTABLEwas
not investigated either.- Codecov's patch-coverage comment was not acted on. It reports 95.65% with 1 missing line
inebuild/plugins/__init__.py, which is #132's file, not this PR's. Out of scope here. - mypy — NOT RUN. Not installed. This PR changes no Python, so nothing in it is exposed by
that gap. - Incidental, not a finding and not introduced by this PR:
pyproject.tomldeclares
requires-python = ">=3.8"while its owndevextra requiresflake8>=6.0, which needs
>=3.8.1.uvrefuses to resolveebuild[dev]for that reason. It is pre-existing on
master, untouched by this diff, and I did not investigate whether CI hits it.
Automated architecture review of 20f69dc8db49 — scheduled, model claude-opus-5, checked against the EmbeddedOS Master Design v2.0. Advisory only: this reviewer never approves, requests changes, or merges. Reply here to discuss or push back — a wrong finding is a bug worth reporting.
|
Nothing to push — the commit is unchanged and you've confirmed it byte-identical, so head stays The nit is fixed in the body, not a push: the first block's "output" was a prose summary under a On finding 1: agreed it is in progress, not done, until Finding 2 stands as accepted: land #132 first. |
CI -- ebuild has been red on master since the 09-08 batch merge, and the first failing step (ruff) has hidden the ones behind it. Lint (ruff, all nine Test legs): - test_build_dir_resolution.py imported shutil twice (F811). - test_package_recipe.py lost its trailing newline (W292). - test_ci_gate.py had `import itertools` / `import re` two hundred lines down (E402) -- my own embeddedos-org#103, replayed onto a file that had moved. These three hunks are byte-identical to embeddedos-org#122's, so either PR merging first leaves the other clean. Type check and tests (never reached on master since 09-08): - ebuild/packages/index_sync.py calls PackageRecipe.to_dict(), which embeddedos-org#111 defined and embeddedos-org#112 -- merged five minutes later from a base without it -- deleted in its replay. mypy names it once; pytest fails nine test_index_sync cases with AttributeError. The method is restored verbatim from embeddedos-org#111 (cc90078): it emits the `package:`/`build:` keys parse_recipe() reads back, which an asdict() replacement would not. Vendored core drift: - embeddedos-org#109 (dba3d83) edited core/eos/docs/three-way-alignment.md, a vendored copy pinned to eos 5544c98, so drift went 44 -> 45 and the guard failed as designed. Reverted to the pinned content (blob 7f9c8c1, the same bytes as eos:docs/three-way-alignment.md at the pin). The alignment note belongs in ebuild's own docs or upstream in eos, not in the snapshot. OSSF Scorecard: - ossf/scorecard-action@v2.4.0 pulls gcr.io/openssf/scorecard-action, and gcr.io now refuses the pull ("requires billing to be enabled"). v2.4.3 pulls from ghcr.io; eos already pins it and its Scorecard job is green. Not in this PR: EoSim Sanity's Windows/macOS legs install a wheel that has never been published; embeddedos-org#121 (srpatcha) already replaces that with the clone the other legs use. Verified locally: ruff clean, yamllint clean, mypy clean over 107 files, 680 passed / 1 skipped, scripts/check_vendor_drift.py 44/44 and 46/46.
…/3.11, yamllint on Windows Both surfaced on this branch's first CI run, once ruff let the job get past its first step. - ebuild/plugins/__init__.py: on Python 3.10 and 3.11 the stubs type entry_points() as the deprecated mapping, and its .get() wants an EntryPoints default, so mypy fails with arg-type. The line carried a '# type: ignore[attr-defined]' -- the wrong error code, so it suppressed nothing. Spelled out with a cast, byte-identical to embeddedos-org#122's hunk (54605f0). - .yamllint.yml: the Windows runners check out with core.autocrlf=true, so every YAML file arrives as CRLF and the default new-lines: unix rule rejected every line. The step was added on 09-03 and had never passed on that leg. new-lines: platform accepts the checkout's own convention.
…e checkout's line ending new-lines: platform was the wrong fix. The Windows runners' autocrlf turns LF files into CRLF -- except a file that already carries a stray CR, which git leaves alone, and auto-assign.yml had one on its last line. So under 'platform' Windows expected CRLF and got LF on that file's first line, and the leg was red again for the opposite reason. Pin *.yml and *.yaml to eol=lf so every OS lints the same bytes, keep yamllint's default unix rule, and drop the stray CR.
…h a round-trip test PackageRecipe.to_dict() was written before install_args existed and was never taught about it, so a recipe that went through index_sync came back from the cache with install_args empty while every other field survived. It also returned the recipe's own list objects, so a caller that appended to what it got back edited the recipe behind its back. install_args is now emitted after build_args, matching the order parse_recipe() reads them, and every list field is copied on the way out. index_sync's entry-to-recipe mapping carries install_args too; without that the field could not arrive from an index at all. The new round-trip test builds a recipe with every field set and asserts parse_recipe(safe_load(safe_dump(to_dict()))) equals it; against the previous to_dict() it fails on install_args. A second test checks the lists are copies, and test_index_sync gains a case that an index entry's install_args reaches the cached YAML.
actions/checkout, ossf/scorecard-action and codeql-action/upload-sarif were referenced by moving tags. A tag can be re-pointed; a commit cannot, and Scorecard itself flags unpinned actions. Each is now pinned to the commit its tag resolved to on 2026-09-14, with the tag kept in a trailing comment, the same shape linked-issue.yml already uses.
The changelog records what the master repair changed and why. CONTRIBUTING gains a note for Windows contributors: .gitattributes now pins YAML to LF, but the attribute governs future checkouts and commits, not files already in a working tree, so an existing clone needs one git add --renormalize . (or a fresh clone) before yamllint stops seeing CRLF.
…working tree git add --renormalize . re-applies the clean filter to the index; it never rewrites files, so a clone with CRLF YAML still has CRLF YAML afterwards (reproduced in a scratch clone with core.autocrlf=true: two CRs before, two after, status clean). What re-checks the files out is git rm --cached -r . && git reset --hard HEAD, or a fresh clone. CONTRIBUTING and the changelog now say that. The changelog entry also lists every file it describes and the plugins/__init__.py type-check fix it had left out, and the to_dict() comment no longer claims to follow parse_recipe()'s order.
The review at 43b0337 found the one-line assertion pinning install_args next to build_args and, six lines above it, recipe.py's docstring saying key order does not matter. Both are true: order is not a correctness property, because parse_recipe() reads every key by name, and it is a stability property, because index_sync writes the dict as cached YAML that humans diff. The assertion now says which of the two it is guarding and what to do when a reordering is deliberate, so a future failure reads as intentional rather than as a mystery. No behaviour change. ruff clean; pytest 683 passed, 1 skipped.
pull_request_target fires on `edited` for closed and merged pull requests as well as open ones, and the caller had no guard on the PR's state. So a body edit on a PR merged before this policy existed graded it against the policy and failed it: on 2026-09-14 that produced 11 failing "Linked issue policy" runs in this repository, every one on a merged or closed branch. A merged PR cannot be changed to satisfy the policy, and grading it says nothing about the tree. Only an open PR is a decision still to be made, so the job now runs only when github.event.pull_request.state == 'open'. The open PRs in the org that fail this policy today (other authors) are unaffected: they are open, so the guard is true and the policy still runs. Verified: the workflow parses and the parsed structure is what was intended -- the `if` sits on the `policy` job, `uses` is unchanged, and the trigger types are still [opened, edited, reopened, synchronize]. Checked with an assertion on the parsed document, not by parse success alone. Closes embeddedos-org#143
20f69dc to
b2df461
Compare
|
Restacked onto #132's rebased head Verified at this head with CI's exact invocations: |
Closes #143
Problem
.github/workflows/linked-issue.ymlruns onpull_request_targetfor[opened, edited, reopened, synchronize]and has no guard on the pull request's state.editedfires on closed and merged PRs too, so a body edit on a PR merged before the policy existed grades it against the policy and fails it.On 2026-09-14 that produced 11 failing
Linked issue policyruns in this repository, every one on a merged or closed branch — triggered by body edits on already-merged PRs. A merged PR cannot be changed to satisfy the policy, and grading it says nothing about the tree.Change
One line on the job:
if: github.event.pull_request.state == 'open', with a comment saying why. Only an open PR is a decision still to be made.What it does not change: the open PRs in the org that currently fail this policy (other authors, in
eosandebuild) are open, so the guard is true and the policy keeps running on them exactly as before. Nothing is weakened for any PR that can still be acted on.Verification
Commands and their output rather than a table of verdicts:
Upstream: the caller is byte-identical in 19 repositories; the guard is moved into the reusable job in embeddedos-org/.github#9. Once that lands and this caller's pin is bumped, this guard is redundant.