Skip to content

ci: grade only open pull requests against the linked-issue policy - #144

Open
Kartikey1306 wants to merge 9 commits into
embeddedos-org:masterfrom
Kartikey1306:ci/linked-issue-policy-open-only
Open

Kartikey1306 wants to merge 9 commits into
embeddedos-org:masterfrom
Kartikey1306:ci/linked-issue-policy-open-only

Conversation

@Kartikey1306

@Kartikey1306 Kartikey1306 commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Stacked on #132 (origin/master does not build without it — this PR branched off master and went red on that alone). Review the single commit at the head of this branch for this change: one file, .github/workflows/linked-issue.yml, +6/−0. (A range with SHAs was here before; the head changed under a no-content re-trigger and the range stopped resolving.) Land #132 first; this rebases cleanly and drops to its one commit.

Closes #143

Problem

.github/workflows/linked-issue.yml runs on pull_request_target for [opened, edited, reopened, synchronize] and has no guard on the pull request's state. edited fires 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 policy runs 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 eos and ebuild) 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:

$ gh run list --workflow "Linked issue policy" --limit 100 --json conclusion,headBranch,createdAt \
    --jq '.[]|select(.conclusion=="failure" and (.createdAt|startswith("2026-09-14")))|.headBranch' | sort -u
assessment-ebuild
ci/release-runner-and-shell
fix/backend-neutral-executable-layout
fix/board-config-merge-splice
fix/cad-pipeline-parser
fix/default-branch-resolution
fix/eosim-sanity-real-tag
fix/letter-suffix-version-ordering
fix/master-suite-cannot-collect
fix/ninja-path-rename-tests
fix/package-recipe-serialization
fix/package-supply-chain-integrity
fix/restore-master-build-and-tests
fix/restore-remaining-dropped-features
fix/setup-clones-master-not-main
fix/shared-library-toolchain-ldflags

(16 distinct branches, measured 2026-09-15 06:20Z against the same historical 09-14 runs: 11 are merged or closed PRs the policy should not be grading, 5 are open PRs where it is correctly failing)

$ python3 -c "import yaml; d=yaml.safe_load(open('.github/workflows/linked-issue.yml')); j=d['jobs']['policy']; \
    assert j['if']==\"github.event.pull_request.state == 'open'\"; assert j['uses'].startswith('embeddedos-org/.github/'); \
    assert set(d[True]['pull_request_target']['types'])=={'opened','edited','reopened','synchronize'}; print('ok')"
ok

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.

@Kartikey1306
Kartikey1306 force-pushed the ci/linked-issue-policy-open-only branch from 93f3e12 to 3708afb Compare September 14, 2026 20:33
@codecov-commenter

codecov-commenter commented Sep 14, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Kartikey1306
Kartikey1306 force-pushed the ci/linked-issue-policy-open-only branch from 3708afb to 9368a0d Compare September 14, 2026 20:37

@srpatcha srpatcha left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 3708afbNot 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

  1. Move the guard up one level, in embeddedos-org/.github:
    jobs:
      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
    then bump the uses: pin in the callers. Behaviour-identical for open PRs in all 19 repos, and it removes the copy from each.
  2. Keep this PR's caller-side guard only if (1) is rejected — and then open the other 16.
  3. Fix the review range in the body to 43b0337..9368a0d.
  4. 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 and Analyze (Python) were pending with 0s elapsed. I did not wait for them and I am not scoring them either way. Everything that had finished was green, including policy / Policy / Linked Issue (6s) and Simulation 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 9368a0d with yaml.safe_load and asserted on the parsed document: jobs is exactly ['policy'], if is "github.event.pull_request.state == 'open'" and sits on the job, uses still pins @92cb596c…, with.policy_ref unchanged, trigger types still [opened, edited, reopened, synchronize], permissions unchanged. PASS on ebuild, eBoot and eos; all three resulting files hash identically (fafeb8d17c7b).
    • The premisegh run list --workflow "Linked issue policy" --status failure shows 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 186aef0d that Dependabot is proposing org-wide contains no state guard either, so this fix is not already upstream.
  • Effect on branch protection not verified. I did not read branch-protection settings, so whether policy / Policy / Linked Issue is 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/master and 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.

@Kartikey1306

Copy link
Copy Markdown
Contributor Author

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 if: github.event.pull_request.state == 'open' on the linked-issue job of linked-issue-policy.yml, with a test that pins the parsed structure (guard on the job, not on a step — a step-level if would still start the job and report a status). Verified by mutation there: guard deleted → 1 failure; guard moved onto a step → 2 failures; restored → 20/20 under the exact unittest discover command that repository's CI runs. Once it lands and this caller's uses:/policy_ref pin is bumped, this PR's guard is redundant and the PR reduces to the pin bump or closes — the body says so now.

Stacked-merge risk: agreed that only BLOCKED prevents it and nothing mechanical does. "Land the base first" is stated at the top of the body; I have not added a mechanical guard here because the review pipeline already reviewed the base at this head and the fix for the class is a merge-queue rule, not a per-PR one.

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.

@Kartikey1306
Kartikey1306 force-pushed the ci/linked-issue-policy-open-only branch from 9368a0d to 20f69dc Compare September 14, 2026 21:21
@Kartikey1306

Copy link
Copy Markdown
Contributor Author

Restacked onto #132's current head f4788f2 (was on 43b0337; #132 moved under it at 02:18 IST). Head is now 20f69dc — still the single commit this PR is, .github/workflows/linked-issue.yml +6/−0, replayed unchanged.

Verified at 20f69dc before pushing: ruff check . clean, pytest tests/ 683 passed, 1 skipped, all 16 workflow files parse with a jobs map. Lease taken against 9368a0d.

No review to re-request — this PR had no approval. Land #132 first, as the body says.

@srpatcha srpatcha left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 real edited-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 whether policy / Policy / Linked Issue is a required context — and how a
    job skipped by a false if is 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#9 was not reviewed. Only its state, base, files and line counts
    were read via gh 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. Its mergeStateStatus: UNSTABLE was
    not investigated either.
  • Codecov's patch-coverage comment was not acted on. It reports 95.65% with 1 missing line
    in ebuild/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.toml declares
    requires-python = ">=3.8" while its own dev extra requires flake8>=6.0, which needs
    >=3.8.1. uv refuses to resolve ebuild[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.

@Kartikey1306

Copy link
Copy Markdown
Contributor Author

Nothing to push — the commit is unchanged and you've confirmed it byte-identical, so head stays 20f69dc.

The nit is fixed in the body, not a push: the first block's "output" was a prose summary under a $ line that promised literal output. It now shows the literal sort -u result — 16 branches — followed by the classification, measured 2026-09-15 06:20Z: 11 merged/closed PRs the policy should not be grading, 5 open PRs where it is correctly failing. (The earlier prose said 6 open; re-counting each branch's PR state gives 5. Corrected rather than left.)

On finding 1: agreed it is in progress, not done, until embeddedos-org/.github#9 merges and the @92cb596c… pins are bumped. That PR is in the org repo where I have no merge rights; the caller-side guard here is belt-and-braces until then, and I'll drop or keep it explicitly once #9 lands. If #9 stalls, the other 18 repos need this same commit and I'll open them.

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
@Kartikey1306
Kartikey1306 force-pushed the ci/linked-issue-policy-open-only branch from 20f69dc to b2df461 Compare September 15, 2026 18:32
@Kartikey1306

Copy link
Copy Markdown
Contributor Author

Restacked onto #132's rebased head 4054494 (was on f4788f2, which conflicted with master after #122). Head 20f69dcb2df461: still the single linked-issue.yml commit, +6/−0, replayed unchanged; jobs.policy.if guard verified on the parsed document.

Verified at this head with CI's exact invocations: ruff check . clean, yamllint . clean, mypy . --ignore-missing-imports --no-strict-optional --exclude '^(layers|core|promo)/' clean, pytest tests/ 680 passed, 1 skipped, 3 NOT RUN locally — the three tests that link a native C binary fail on this Mac's CommandLineTools SDK (ld: tapi error: malformed file … MacOSX27.0.sdk/usr/lib/libSystem.B.tbd: unknown architecture), identically on master c37e995; CI's ubuntu legs are the evidence for those three. Stated rather than omitted.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Linked issue policy grades closed and merged pull requests

3 participants