Skip to content

ci: finish the EoSim fix — a tag that exists, and no wheel anywhere - #129

Merged
srpatcha merged 8 commits into
embeddedos-org:masterfrom
Kartikey1306:fix/eosim-remaining-wheel-and-version
Sep 8, 2026
Merged

srpatcha merged 8 commits into
embeddedos-org:masterfrom
Kartikey1306:fix/eosim-remaining-wheel-and-version

Conversation

@Kartikey1306

@Kartikey1306 Kartikey1306 commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #127 so this branch is not red for the unrelated test_crypto_ed25519_loworder reason. Review the second commit.

Simulation Test and EoSim Sanity are both red on master. #106 fixed this class in eosim-sanity.yml but did not reach every site — there were two more, and they fail for two different reasons.

1. simulation-test.yml pins a tag that does not exist

EOSIM_VERSION: "0.1.0"

EoSim has no v0.1.0 tag — its releases run v1.0.0 to v3.0.1 — so every run failed at the clone:

fatal: Remote branch v0.1.0 not found in upstream origin

Bumped to 1.5.0, the release marked Latest and the one eosim-sanity.yml already pins.

2. eosim-sanity.yml still installs a wheel on two legs

ERROR: HTTP error 404 while getting
  .../releases/download/v1.5.0/eosim-1.5.0-py3-none-any.whl

No EoSim release ships a wheel at any version, so a version bump alone could never have fixed these two — that is why they survived #106. The other three jobs in the same workflow already install from a clone; the Windows and macOS legs were missed. Converted to the identical clone + pip install -e.

Verified against the real remote, not inferred from the error text

wheel URL                       ->  HTTP 404
git ls-remote --tags | v0.1.0   ->  0 matches
git ls-remote --tags | v1.5.0   ->  1 match

clone v1.5.0 + pip install -e   ->  rc 0
eosim --version                 ->  eosim, version 2.0.0
eosim doctor                    ->  rc 0

Both files still parse as YAML (3 and 6 jobs respectively).

One oddity worth recording rather than hiding: the v1.5.0 tag reports its version as 2.0.0. That is EoSim's own inconsistency, not a mis-pin — v1.5.0 is what its releases page marks Latest, and it installs and runs cleanly.

…removed

`CI — eos` and `Python Unit Tests` are red on master (769191a), and both
fail for one reason:

    these suites exist in tests/ but no add_executable() in
    tests/CMakeLists.txt builds them, so they never run:
    ['test_crypto_ed25519_loworder.c']

3aa8644 (embeddedos-org#93, "remove duplicate test targets from tests/CMakeLists.txt")
removed all four lines that build and register
test_crypto_ed25519_loworder. It was not a duplicate — there was exactly
one registration before that commit, and it took it.

What stopped running is the suite that guards embeddedos-org#101: Ed25519 rejecting
low-order public keys. A low-order key makes every term of the
verification equation collapse to the identity regardless of the
message, so a signature of all zeros verifies against any content at
all. The fix is still in services/crypto/src/ed25519_verify.c and still
correct; nothing has been checking it since embeddedos-org#93 merged, and nothing
would have noticed if a later change had removed it too.

Restored verbatim from 3aa8644^, in its original position before
test_crypto_sha512. No other file changes.

The guard that caught this is test_cmake_test_registration.py, added
recently. It did exactly its job — this is the first thing it found.

Verified:
  test_cmake_test_registration.py    -> 5 passed (1 failed on master)
  pytest tests/                      -> 15 passed (14 passed 1 failed on master)
  test_crypto_ed25519_loworder       -> 5/5 tests passed
  ctest                              -> 39/39 passed (master builds 38)
`Simulation Test` and `EoSim Sanity` are both red on master. embeddedos-org#106 fixed
this class in eosim-sanity.yml but did not reach every site.

simulation-test.yml still pins EOSIM_VERSION: "0.1.0". EoSim has no
v0.1.0 tag — its releases run v1.0.0 to v3.0.1 — so every run failed at
the clone:

    fatal: Remote branch v0.1.0 not found in upstream origin

Bumped to 1.5.0, the release marked Latest and the one eosim-sanity.yml
already pins.

eosim-sanity.yml still installs a wheel on its Windows and macOS legs:

    ERROR: HTTP error 404 while getting
    .../releases/download/v1.5.0/eosim-1.5.0-py3-none-any.whl

No EoSim release ships a wheel, so that URL 404s at any version — the
version bump alone could never fix these two. The other three jobs in
the same workflow already install from a clone; these two were missed.
Converted to the same clone + `pip install -e`.

Verified, against the real remote rather than from the error message:

    wheel URL                       -> HTTP 404
    git ls-remote --tags | v0.1.0   -> 0 matches
    git ls-remote --tags | v1.5.0   -> 1 match
    clone v1.5.0 + pip install -e   -> rc 0
    eosim --version                 -> eosim, version 2.0.0
    eosim doctor                    -> rc 0

(The v1.5.0 tag reporting version 2.0.0 is EoSim's own inconsistency,
not a wrong pin — v1.5.0 is what its releases page marks Latest.)

Both files still parse as YAML. Stacked on the embeddedos-org#127 registration fix so
this branch's CI is not red for an unrelated reason.

@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 — eos#129 "ci: finish the EoSim fix — a tag that exists, and no wheel anywhere"

head: 57e5f38 author: Kartikey1306 ci: pass (25 pass, 2 skipping — but neither workflow this PR fixes ran; see finding 4)

Verdict: Both diagnoses are correct and I confirmed them against the real remote — there is no v0.1.0 tag, and no EoSim release ships a Python artifact at any version. The two wheel-install sites this touches are the only two left in the repo, so the class is genuinely closed. But the replacement pin is not a version pin: EOSIM_VERSION: "1.5.0" resolves to a commit that calls itself four different versions, and the workflow's only version assertion is a hardcoded literal that cannot detect it. The body's closing note calls this "EoSim's own inconsistency" and sets it aside; it is load-bearing for the change being made.

What I verified against the remote

gh api repos/embeddedos-org/EoSim/tags            -> v3.0.1 v3.0.0 v2.0.0 v1.5.0 v1.4.0 v1.3.1
                                                     v1.3.0 v1.2.0 v1.1.0 v1.0.2 v1.0.1 v1.0.0
                                                     v0.2.0-book production-ready
  no v0.1.0                                       -> the simulation-test.yml fix is necessary and right
gh api .../releases  (13 releases, all assets)    -> promo .mp4 x13, manifest.json x2, EoSim-guide.pdf
  no wheel, no sdist, at any version
https://pypi.org/pypi/eosim/json                  -> HTTP 404
gh api .../releases/latest                        -> v1.5.0   (the author's pin rationale is correct)

And by installing both candidate tags here (uv pip install -e, rc=0 for each):

tag v1.5.0 tag v3.0.1
commit 7dec3460 b297ec26
commit date 2026-05-27 2026-05-16
commit subject feat: production-ready v1.4.0 — chore(release): v3.0.1 — unifie…
pyproject.toml:7 (the installed dist version) 3.0.1 3.0.1
eosim/__init__.py __version__ 3.0.1 2.0.0
eosim --version eosim, version 2.0.0 eosim, version 2.0.0

So v1.5.0 is the newest tag by commit date, tags a commit whose own message says v1.4.0, declares 3.0.1 to pip, and reports 2.0.0 from the CLI. The tag namespace is not ordered and does not describe its contents.

Findings

# Severity File:line Finding Recommended fix
1 High .github/workflows/simulation-test.yml:44 (EOSIM_VERSION: "1.5.0"); eosim-sanity.yml:20 1.5.0 is a label, not a version. The table above is the evidence: that tag installs a dist declaring 3.0.1, from a commit dated after v3.0.1's and whose message claims 1.4.0. v2.0.0, v3.0.0 and v3.0.1 are self-consistent in pyproject.toml; v1.5.0 is the one that is not, and it is the one both workflows now pin. A reader of EOSIM_VERSION: "1.5.0" will believe eos is simulated against EoSim 1.5.0. It is not, and no amount of re-reading the workflow reveals that. §9.2 requires "reproducible lockfiles/manifests for production builds"; this is the CI equivalent and it is not reproducible in any sense that survives EoSim retagging. Pin the commit, not the name: git clone --filter=blob:none https://…/EoSim.git /tmp/EoSim && git -C /tmp/EoSim checkout <sha>, with EOSIM_COMMIT: 7dec3460cba76083b6645eb4a867e39aa2af97df (today's v1.5.0) or b297ec26544cfdab55fe13105265604e2d772293 (today's v3.0.1) and a comment saying which tag it corresponded to and when. Do not simply switch to v3.0.1 — its __version__ is 2.0.0, so it is only marginally less confusing. Reinstate a tag pin once EoSim's tags mean something.
2 High .github/workflows/eosim-sanity.yml:113-120, 129-136 After this merges, nothing in the org exercises a published EoSim artifact — and none exists to exercise. Verified: 13 releases, zero wheels, zero sdists, and eosim is not on PyPI (404). §17 makes EoSim an adoption primitive — "Discover -> Install -> ebuild run --sim", "first simulated application in minutes, not hours" — and §39's success state has an independent developer install the SDK and run EoS in simulation. A developer following that path today cannot: their only route is git clone at a tag, which is what these two jobs are being converted to. The conversion is the correct immediate move (a 404 is not a useful red), but it removes the last signal that would have surfaced the real defect, which is .ai/reviewer.md's "a verification whose result is discarded" — not to be rounded down. It is also §10 exactly: "repositories should not be the dependency API." eos consumes EoSim by git URL because EoSim publishes no component. Not fixable in this repo, so land this and record the debt in the same breath: (a) open an EoSim issue to build and attach a wheel + sdist per release, or publish to PyPI, with release.yml doing it; (b) keep one job — or a new eosim-release-artifact check — that asserts the published artifact exists and installs, so its absence stays visible instead of becoming green; (c) note in the PR body that the wheel path is now untested org-wide, not merely fixed.
3 Medium eosim-sanity.yml:115, 131 (eosim --version) The "Verify installation" assertion cannot detect a wrong install. eosim --version is a hardcoded literal — eosim/cli/main.py:49, @click.version_option(version="2.0.0", prog_name="eosim"), repeated at eosim/api/server.py:29 — so it prints 2.0.0 from both candidate tags and would print it from any future one. That is why the mis-pin in finding 1 is invisible, and why the body could record eosim --version -> 2.0.0 as an oddity rather than as a failed pin. A version check that returns a constant is a check that has not run. Assert the number pip actually installed: python -c "import importlib.metadata as m; assert m.version('eosim') == '$EOSIM_EXPECTED', m.version('eosim')". That reads dist metadata from pyproject.toml, which is the only version the pin controls. Separately, an EoSim issue to single-source __version__ and stop hardcoding it in cli/main.py and api/server.py.
4 Medium simulation-test.yml:3-6; eosim-sanity.yml:3-6 This PR cannot be validated by CI, and was not. Both workflows are on: schedule + workflow_dispatch — no pull_request trigger — so neither Simulation Test nor EoSim Sanity appears anywhere in this head's checks.txt (27 entries, neither present). The 25 green checks say nothing about the change. All evidence for the fix is the author's local runs, which is honest but is not the same as the job passing. Run both via workflow_dispatch on fix/eosim-remaining-wheel-and-version and link the two run URLs in the body before merge — that is the only pre-merge proof available. Longer term, add on: pull_request: paths: ['.github/workflows/eosim-sanity.yml', '.github/workflows/simulation-test.yml'] so a change to these files tests itself.
5 Low eosim-sanity.yml:113, 129 /tmp/EoSim is hard-coded in the two jobs that run on windows-latest and macos-latest. The Windows job sets no shell:, so it gets the runner default pwsh, where /tmp/EoSim resolves drive-relative rather than to a real temp directory. It works today by accident of that resolution. The three jobs already using a clone (lines 38, 69, 97) are all ubuntu-latest in at least one matrix leg, so this is the first time the path crosses to Windows. Use the variable GitHub provides for this: ${{ runner.temp }}/EoSim in both new jobs. Correct on all three runners and one token longer.
6 Low eosim-sanity.yml:114, 130 pip install -e installs the clone editable. Nothing here needs editability, and an editable install is further from what a developer does than a plain one — which matters in a workflow whose purpose is to prove the install works. It also makes the dist metadata read in finding 3 depend on the clone staying in place. pip install /tmp/EoSim (no -e). Matches the three existing clone jobs only if they are changed too; if consistency with them is preferred, leave it and change all five in one follow-up.
7 Low tests/CMakeLists.txt:93-97 Carries #127's test_crypto_ed25519_loworder registration. Declared up front in the body ("Stacked on #127 … Review the second commit"), which is the right way to do it, but it is a fifth PR touching that anchor alongside #127, #125, #118 and #126. Merge #127 first, then rebase this and drop the hunk. No change needed now.

Credit where due: the body separates the two failures by cause, states that a version bump alone could never have fixed the wheel legs, and records the version oddity instead of burying it. Findings 1 and 3 extend that note rather than contradicting it.

Architecture conformance

Conforms as a change; surfaces a real deviation elsewhere.

  • §21 Tier 1 — Foundation is eos, eBoot, ebuild, EoSim. Both files are CI configuration in eos; nothing points up a tier, no runtime dependency is added, and eBuild is not bypassed. The diff itself is clean under §5.1.
  • §17, EoSim as an adoption primitive — this is where the deviation is. §17's target is "first simulated application in minutes, not hours" and its flow is Discover -> Install -> ebuild run --sim. With no wheel, no sdist and no PyPI entry, the Install step in that flow does not exist for anyone outside the org; a shallow git clone at a tag is the only route, and it is the route this PR standardises on. Finding 2.
  • §10, "repositories should not be the dependency API", and .ai/platform.md's first non-negotiable — "a consumer depends on a component with a version range, never on a git URL". eos's simulation CI depends on EoSim by git URL at a mutable tag. That is a consequence of §11's Registry not yet carrying EoSim rather than a choice made here, but this PR is the place it becomes the settled arrangement in five jobs.
  • §23.1/§23.2 and .github/STANDARDS.md "Tag scheme" — "All canonical product repos tag releases as vMAJOR.MINOR.PATCH (SemVer)". EoSim satisfies the syntax and violates the intent: v1.5.0 tags a commit dated after v3.0.1's, calling itself v1.4.0, declaring 3.0.1. §23.2's compatibility contract governs formats but says nothing about a tag matching the artifact it tags, which is the gap that let this through — see the proposals appended for 2026-09.
  • Weakened checks — finding 2 is the honest reading of this diff under .ai/reviewer.md. Nothing is disabled and no assertion is deleted, but the last two jobs that referenced a published artifact stop doing so, and the check that replaces them cannot fail for the reason the old one did. Recorded as High rather than rounded down, with the caveat that the pre-existing state (a permanent 404) was not a working check either.

Proposed changes

  1. Change the pin to a commit SHA with a comment recording which tag it was and when (finding 1). One line per file, no behaviour change beyond becoming honest.
  2. workflow_dispatch both workflows on this branch and link the runs in the body (finding 4). This is the only pre-merge evidence obtainable and it also proves finding 1's replacement pin.
  3. ${{ runner.temp }}/EoSim in the two new jobs (finding 5).
  4. Add the importlib.metadata assertion to the two new jobs (finding 3).
  5. Add to the body: the published-wheel path is now untested across the org, and no publishable artifact exists (finding 2).
  6. Then merge, after #127, dropping the tests/CMakeLists.txt hunk (finding 7).
  7. Open in EoSim: publish a wheel + sdist per release (finding 2); single-source __version__ and stop hardcoding 2.0.0 in cli/main.py:49 and api/server.py:29 (finding 3); reconcile or delete the v1.5.0 tag (finding 1).

I opened no fix PR, deliberately, despite two High findings. Finding 1's fix is a one-line change to EOSIM_VERSION — in the exact file and line this open PR exists to change, so a fix PR would collide with it head-on, and the brief forbids touching a branch belonging to an existing PR. Finding 2 is not fixable in eos at all; it needs EoSim to publish something. Finding 3 is EoSim's code.

Not checked

  • The workflows were never executed. No workflow_dispatch run, no act, no local GitHub Actions runner. I verified the YAML's inputs — tags, releases, PyPI, install — not the jobs.
  • The Windows and macOS legs specifically. Finding 5 is reasoned from GitHub's documented default shell for windows-latest (pwsh) and drive-relative path resolution; I have no Windows or macOS host and did not observe either job. I cannot say the current /tmp/EoSim fails — my claim is only that it is accidental.
  • Installs were done with uv pip install -e into a uv venv, not pip (python3 -m venv is unusable on this host — no ensurepip). Both tags returned rc=0 and a working eosim --version. The workflows use pip; I did not reproduce their exact installer.
  • eosim list, eosim doctor and eosim simulate were not run for the tags — only --version. The author reports doctor rc=0; unverified here.
  • simulation-test.yml's 11-platform matrix and the nested-simulation / nested-guest-install jobs were read for their install lines only. Whether they pass once the clone succeeds is unknown, and is the more likely next failure — a tag that exists is necessary, not sufficient.
  • I did not diff v1.5.0 against v3.0.1 beyond a file-level diff -rq, which showed substantially different trees (android/, coverage files present only in v1.5.0). Which tag is functionally better for eos is unexamined; finding 1 recommends a SHA precisely because I cannot answer that.
  • EoSim was skipped by this run's sync as a dirty working tree (179 files), so I read it only from fresh clones in /tmp and from the GitHub API — never from the local checkout.
  • Whether Simulation Test / EoSim Sanity are required checks for merge was not determined; mergeStateStatus is BLOCKED and I did not establish what blocks it.

Automated architecture review of 57e5f38333dd — 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.

…he workflow test itself

Answers the review on embeddedos-org#129. The two diagnoses in the previous commit hold --
there is no v0.1.0 tag and no EoSim release ships a Python artifact -- and
this addresses what the replacement pin did not.

Finding 1 (High) -- `EOSIM_VERSION: "1.5.0"` is a label, not a version.
Re-verified against the remote rather than taken from the review:

  tag      commit    committed    commit subject             pyproject  __init__
  v1.5.0   7dec3460  2026-05-27   "production-ready v1.4.0"    3.0.1      3.0.1
  v3.0.1   b297ec26  2026-05-16   "v3.0.1 — unified ..."       3.0.1      2.0.0

v1.5.0 is the release GitHub marks Latest and the newest tag by commit date,
tags a commit whose own message claims v1.4.0, and installs a dist declaring
3.0.1. A reader of `EOSIM_VERSION: "1.5.0"` would believe eos is simulated
against EoSim 1.5.0. It is not, and nothing in the file would reveal that.

Both workflows now pin `EOSIM_COMMIT` to the full SHA that tag resolves to
today, with the table above in the env block and the date it was checked.
Not v3.0.1 instead: its `__init__.py` says 2.0.0, so it is only marginally
less confusing. A SHA cannot be moved under us; the comment says to go back to
a tag once EoSim's tags mean something.

Finding 3 (Medium) -- `eosim --version` cannot detect a wrong install.
EoSim hardcodes it (`eosim/cli/main.py:49`,
`@click.version_option(version="2.0.0")`), confirmed by reading that file at
v1.5.0, so it prints 2.0.0 from every tag -- which is exactly why the previous
commit could record the version oddity as a curiosity rather than as a failed
pin. All three sites now also assert `importlib.metadata.version("eosim")`
against `EOSIM_EXPECTED_DIST`, which is the only version the commit pin
controls.

Finding 4 (Medium) -- this PR could not be validated by CI and was not: both
workflows were schedule- and dispatch-only, so neither appeared in this head's
checks and all 25 green ones were other workflows. Added
`pull_request: paths:` on both files listing both files, so a change to either
now runs both. `workflow_dispatch` on the fork is not available to me --
GitHub resolves the workflow on the fork's default branch and returns 404 --
so this trigger is the evidence that is actually obtainable, and it applies to
every future change to these files rather than to this one only.

Finding 2 (High) -- after this, nothing in the org exercises a published EoSim
artifact, and none exists. Verified independently: 13 releases whose assets
are promo .mp4 files, a manifest.json and EoSim-guide.pdf; no wheel or sdist
at any tag; `https://pypi.org/pypi/eosim/json` returns 404. Converting to a
clone is right -- a permanent 404 is not a useful red -- but it would also
make the gap green and invisible, which is the "verification whose result is
discarded" shape.

So `published-artifact-watch` runs on every execution, checks the releases and
PyPI, and says out loud that the packaging debt is open. It cannot fail the
workflow, deliberately: it is a tracking signal, not a gate on someone else's
repo. It emits a `::notice::` the day an artifact appears, which is when it
should be deleted and the installs pointed at it. The debt is also stated in
the PR body rather than left implied, and raised against EoSim.

Finding 5 (Low) -- `/tmp/EoSim` was hardcoded in the two jobs that run on
windows-latest and macos-latest, where the Windows job sets no `shell:` and
gets pwsh. Now `${{ runner.temp }}/EoSim` everywhere.

Finding 6 (Low) -- dropped `-e`. Nothing needs an editable install, it is
further from what a developer does in a workflow meant to prove the install
works, and it made the dist-metadata assertion depend on the clone staying
put. Changed at all five sites, not two, so they are consistent.

Also, while in this file: `sanity-gate` had the fail-open shape --
`needs:` five jobs, tested `install-validate` alone, then printed "All EoSim
sanity checks passed". Replaced with the `toJSON(needs)` body, which cannot
fall out of step with `needs:`, and the new job is included in it.

Verified:
  ctest                                       39/39 PASS
  pytest tests/                               15 passed
  both workflows parse, and structurally:
    pull_request paths list this file           both
    EOSIM_VERSION gone from every code line     both
    EOSIM_COMMIT is a full 40-char sha          both
    no /tmp/EoSim literal, no `pip install -e`  both
    every `git clone --filter` has a matching `checkout --detach`
    three importlib.metadata assertions
    sanity-gate needs == every other job in the file
  the SHA resolves: refs/tags/v1.5.0 -> tag object 978f215f -> commit
    7dec3460cba76083b6645eb4a867e39aa2af97df

  NOT RUN: neither workflow. `workflow_dispatch` on the fork returns 404
  because GitHub resolves it on the fork's default branch. The
  `pull_request: paths:` trigger should make both run on this PR for the
  first time -- that will be the first execution either has ever had, and I
  will report what it shows rather than predicting it.

Finding 7 (Low): still stacked on embeddedos-org#127; the tests/CMakeLists.txt hunk goes
when that lands.

Refs embeddedos-org#129
@Kartikey1306
Kartikey1306 force-pushed the fix/eosim-remaining-wheel-and-version branch from 55066f6 to 731331d Compare September 3, 2026 17:16
@Kartikey1306

Copy link
Copy Markdown
Contributor Author

Addressed — and one thing this PR now makes visible rather than fixes

Thank you, this was a good catch on the pin. I re-verified every remote claim independently rather than taking the table on trust, and it all reproduces:

gh api repos/embeddedos-org/EoSim/tags        -> no v0.1.0
gh api .../releases (13, all assets)          -> promo .mp4, manifest.json, EoSim-guide.pdf
                                                 no wheel, no sdist, any tag
curl -s -o /dev/null -w '%{http_code}' \
     https://pypi.org/pypi/eosim/json         -> 404
refs/tags/v1.5.0 -> tag 978f215f -> commit 7dec3460cba76083b6645eb4a867e39aa2af97df
tag commit committed commit subject pyproject __init__
v1.5.0 7dec3460 2026-05-27 "production-ready v1.4.0" 3.0.1 3.0.1
v3.0.1 b297ec26 2026-05-16 "v3.0.1 — unified …" 3.0.1 2.0.0

Finding 1 — pinned by SHA in both files, with that table and the check date in the env block. Not v3.0.1 instead: its __init__.py says 2.0.0, so it is only marginally less confusing.

Finding 3 — you are right that this is why my own note read as a curiosity rather than a failed pin. @click.version_option(version="2.0.0") at eosim/cli/main.py:49, confirmed at that tag. All three sites now assert importlib.metadata.version("eosim") against EOSIM_EXPECTED_DIST.

Finding 4 — I could not get a workflow_dispatch run: GitHub resolves the workflow on the fork's default branch and returns 404. So instead both files carry pull_request: paths: listing both files. That is weaker as evidence for this change and stronger for every change after it, and it should mean these two workflows run on this PR for the first time in their history. I will report what they show rather than predict it.

Finding 2 — recorded, not fixed, and I want to be plain about it. After this merges, nothing in the org exercises a published EoSim artifact, because none exists. Converting to a clone is the right immediate move, but it also turns a permanent red into a green that checks nothing — which is the shape .ai/reviewer.md is about.

So there is now a published-artifact-watch job that checks the releases and PyPI on every run and says out loud that the debt is open. It cannot fail the workflow, deliberately — it is a tracking signal, not a gate on another repo's release process — and it emits a ::notice:: the day an artifact appears, which is when it should be deleted and the installs pointed at it.

Findings 5 and 6 done (${{ runner.temp }}, and -e dropped at all five sites, not two). Finding 7 stands — the hunk goes when #127 lands.

One thing beyond the findings. While in this file: sanity-gate declared needs: on five jobs, tested install-validate alone, then printed "All EoSim sanity checks passed". Same fail-open shape you raised on eBoot#81/#90. Replaced with the toJSON(needs) body, which cannot fall out of step with needs:.

Still open, in EoSim, not here

  1. Publish a wheel + sdist per release, or to PyPI — release.yml doing it. Until then §17's Discover → Install → ebuild run --sim has no Install step for anyone outside the org.
  2. Single-source __version__; stop hardcoding 2.0.0 in cli/main.py:49 and api/server.py:29.
  3. Reconcile or delete the v1.5.0 tag.

I have not opened those, since I do not have write access to EoSim — happy to if that is useful, or they may be better raised by a maintainer.

@Kartikey1306

Copy link
Copy Markdown
Contributor Author

Diagnosis of the 25 red checks on 731331d4, since I opened this PR and the failures split into two unrelated causes.

First, the pull_request trigger in 731331d4 is the right call and it changes what the earlier green meant. Before it, eosim-sanity.yml was schedule- and dispatch-only, so my two earlier commits on this branch never ran the workflow they edit. Those green checks were other workflows. That is the same "a check that does not run is not a check" pattern this PR exists to fix, one level up, and it is why the failures only appear now.

Cause 1 — inherited from eBoot, not this PR

Cross-compile ARM64 kernel, Full-stack integration summary and the other build-side jobs fail on:

eBoot/include/eos_image.h:135: error: 'eos_image_header_t' has no member named 'reserved'

eBoot master does not compile. #87 pinned reserved[] while #57 split it into tlv_len/tlv_hash; both merged conflict-free. Repair is eBoot#97 (green: ctest 21/21, low-order probe 0/2048, RFC 8032 vectors still accepted). Nothing to do here — these clear when #97 lands.

Cause 2 — real, and mine to have missed

Nested Simulation (*) and Guest OS Install (*) fail differently:

FileNotFoundError: [Errno 2] No such file or directory:
  '/opt/hostedtoolcache/Python/3.12.14/x64/lib/python3.12/site-packages/platforms'

eosim/cli/main.py sets PLATFORMS_DIR = <site-packages>/platforms, but the package ships only eosim/platforms/__init__.py — nothing installs a top-level platforms/ into site-packages, and an editable install puts nothing there at all. So converting these jobs from a (404ing) wheel to pip install -e fixes the install and then trips over this immediately after.

eBoot already solved this in #81, and the step is load-bearing rather than incidental:

SITE_PACKAGES=$(python -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])')
cp -r /tmp/eosim-data/platforms "$SITE_PACKAGES/"

— .github/workflows/eosim-sanity.yml:66 and :96 on eBoot master. eos's copy of this workflow has no equivalent, which is why the sanity legs I converted now fail past the install step. The same applies to the Guest OS Install jobs.

Worth knowing while you are in here: eosim list prints (0) while discover_platforms() on the same directory returns 149, and it exits 0 — so it will not fail a job, but it is not evidence of anything either. That is EoSim's bug, not ours.

I am not pushing to this branch since you are working it — flagging so the platforms step does not have to be rediscovered.

The first real execution of these workflows -- which the pull_request trigger
added in the previous commit made possible -- failed, and showed the next
blocker behind the missing v0.1.0 tag:

    FileNotFoundError: [Errno 2] No such file or directory:
      '/opt/hostedtoolcache/Python/3.12.14/x64/lib/python3.12/site-packages/platforms'

on all three Guest OS Install legs and all seven Nested Simulation platforms.

platforms/ is data, not package data: eosim/cli/main.py sets PLATFORMS_DIR to
<site-packages>/platforms while the wheel ships only
eosim/platforms/__init__.py. None of the five jobs that run eosim copied it,
so none of them could ever have worked. A tag that exists was necessary and
not sufficient, exactly as the review said.

  Worth recording: this is also what the dropped `pip install -e` was
  accidentally papering over in the jobs that had a copy elsewhere. With an
  editable install eosim.__file__ points into the clone, so PLATFORMS_DIR
  landed beside the checked-out platforms/ by luck. A plain install is the
  right thing and it made the real dependency visible.

install-validate went green in that run and the tracking job reported the
packaging debt as intended; the failures were confined to the jobs that
actually boot a platform.

Verified:
  both workflows parse; all five eosim-running jobs now copy platforms/
  the run that produced the error: 33783625398 (EoSim Sanity), first
  execution this workflow has ever had

Refs embeddedos-org#129
Second real execution, after the platforms/ fix: ubuntu and macOS now pass
Install & Validate; all three windows-latest legs fail.

    Install & Validate (windows-latest, Python 3.12)
      #   FileNotFoundError: .../site-packages/platforms
      ##[error]Process completed with exit code 1

The give-away is the leading `#` in that line: pwsh echoed my comment as a
command. install-validate is a matrix over ubuntu/windows/macos and set no
`shell:`, so on the Windows legs it got the runner default, where
`VAR=$(...)`, `cp -r` and a leading `#` are all wrong. windows-sanity had
the same gap.

`shell: bash` on the six run steps in the two Windows-capable jobs. This is
the same defect the review raised as finding 5 for the hardcoded /tmp path --
${{ runner.temp }} fixed where the clone goes, and this fixes what interprets
the script.

Worth stating plainly: none of this was visible before the pull_request
trigger. Two runs have now found two blockers behind the missing v0.1.0 tag --
platforms/ never copied in any job, and bash steps running under pwsh -- in a
workflow that had never executed once. The trigger is doing more work than the
pin.

Verified:
  parses; no run step in a windows-capable job is left without a shell
  run 33784349071: ubuntu + macOS Install & Validate green, windows red
    with the error above

Refs embeddedos-org#129
Third run. EoSim Sanity is green -- 23/23 jobs, the first green run that
workflow has ever had. Simulation Test has one failure left,
`Cross-Platform (windows-latest)`, and it is the same defect I fixed in
eosim-sanity.yml one commit ago and did not apply here:

    Cross-Platform (windows-latest)  Install EoSim from source
      # fails with FileNotFoundError.
      ##[error]Process completed with exit code 1

pwsh echoing a `#` comment as a command. The cross-platform matrix includes
windows-latest and its two run steps set no `shell:`.

Refs embeddedos-org#129
@Kartikey1306

Copy link
Copy Markdown
Contributor Author

Finding 4, answered — both workflows are green, for the first time in their history

You said the only pre-merge proof available was to actually run these. workflow_dispatch from a fork returns 404 (GitHub resolves the workflow on the fork's default branch), so I added pull_request: paths: instead — listing both files, so a change to either runs both. That is weaker evidence for this change and stronger for every change after it.

It also did what you predicted a run would do: a tag that exists was necessary and not sufficient. Four runs, three more blockers, none of them visible by reading.

run result what it found
1 both fail FileNotFoundError: .../site-packages/platforms on all 3 Guest OS legs and all 7 Nested Simulation platforms
2 both fail ubuntu + macOS green; all 3 windows-latest legs fail
3 EoSim Sanity green (23/23) Simulation Test still red on Cross-Platform (windows-latest)
4 both green —

Blocker 2 — platforms/ was copied by none of the five jobs. eosim/cli/main.py sets PLATFORMS_DIR to <site-packages>/platforms while the package ships only eosim/platforms/__init__.py. Worth noting why this surfaced now: the -e you asked me to drop in finding 6 was accidentally papering it over — with an editable install eosim.__file__ points into the clone, so PLATFORMS_DIR landed beside the checked-out platforms/ by luck. A plain install is the right thing and it made the real dependency visible.

Blocker 3 — bash steps under pwsh. install-validate is a matrix over ubuntu/windows/macos and set no shell:; so did windows-sanity, and later cross-platform in the sibling workflow. The tell in the log is pwsh echoing a # comment as a command. This is your finding 5 one layer down: ${{ runner.temp }} fixed where the clone goes, shell: bash fixes what interprets the script.

The runs

published-artifact-watch ran green in both and reported the debt as intended.

Still red, and not this PR

EoS Full-Stack Simulation fails on every open eos PR. It checks out embeddedos-org/eBoot at ref: master and builds it, and eBoot's master does not compile. eBoot#94 repairs it; nothing can be done from here.

Not run

The 11-platform matrix in simulation-test.yml beyond what these runs covered, and whether eosim run produces correct output rather than merely exiting 0. Green here means the jobs complete, not that the simulation is right.

@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 — eos#129 "ci: finish the EoSim fix — a tag that exists, and no wheel anywhere"

head: 731331d author: Kartikey1306 ci: fail (22 red, all one cause introduced here)

Verdict: The install half is fixed and now proven by CI rather than asserted — all nine Install & Validate legs, Windows Sanity and macOS Sanity are green for the first time in this workflow's history, and the SHA pin plus the dist-metadata assertion are the right answers to findings 1 and 3. The pull_request: paths: trigger did what it was meant to do: it ran the workflows and showed what the previous round could not see. What it shows is that dropping -e broke eosim run on every platform — 22 jobs across the two workflows now fail with the same traceback.

That change was made on my predecessor's finding 6, which asked for a plain install. That finding was wrong and I am withdrawing it. The reasoning ("an editable install is further from what a developer does") was right about intent and wrong about this package: editable is currently the only mode in which EoSim works at all.

Findings

# Severity File:line Finding Recommended fix
1 High .github/workflows/eosim-sanity.yml:122,152,177,204,232; simulation-test.yml:53,84 pip install <path> instead of pip install -e <path> makes eosim run impossible. EoSim's eosim/cli/main.py:14 computes EOSIM_ROOT = Path(__file__).parent.parent.parent and PLATFORMS_DIR = EOSIM_ROOT / "platforms". platforms/ is a top-level directory of 199 files, not part of the eosim package; pyproject.toml has [tool.setuptools.packages.find] include = ["eosim*"] and there is no MANIFEST.in at the pinned commit, so a non-editable install ships none of it and EOSIM_ROOT resolves to site-packages. Measured on the pinned tree: editable layout → EOSIM_ROOT=<clone>, platforms/ present with 150 entries; installed layout → EOSIM_ROOT=<site-packages>, platforms/ absent. That is exactly the CI failure, on all 22 jobs: FileNotFoundError: [Errno 2] No such file or directory: '/opt/hostedtoolcache/Python/3.12.14/x64/lib/python3.12/site-packages/platforms' at _find_platform → PLATFORMS_DIR.iterdir(). Seven Nested Simulation, three Guest OS Install, EoSim Sanity Gate, eleven Simulate (…) and Simulation Gate. Restore pip install -e at all five sites, with a comment saying why editable is load-bearing — otherwise the next reviewer removes it again for the same good-sounding reason I did. Then raise the real defect against EoSim: platforms/ must move under eosim/ (or be declared as package data with a MANIFEST.in + include-package-data), and PLATFORMS_DIR must resolve through importlib.resources, not __file__.parent.parent.parent. Until that lands, a plain pip install of EoSim cannot work for anyone.
2 High .github/workflows/eosim-sanity.yml:143 ("Validate all platform configs": eosim list && eosim doctor); simulation-test.yml:56 ("Validate platform": eosim list) The validation step passes on an installation with zero platforms. Run directly against the pinned code in a non-editable layout: eosim list prints Available platforms (0): and an empty table, and returns 0. eosim doctor likewise — both are in an && chain and the job is green. That is why nine Install & Validate legs are green while every job that actually simulates is red, and why the PR body can record eosim doctor -> rc 0 as evidence of a working install. eosim/cli/main.py:45 builds PlatformRegistry(str(PLATFORMS_DIR)) over a directory that does not exist and reports success. A step named "Validate all platform configs" that validates none and exits 0 is the fail-open shape .ai/security.md puts first — a verification that could not run must fail, not pass. This one is inside this PR's own job, and it is what let a broken install look validated. Assert non-emptiness, not exit status. eosim list --format json and check the array is non-empty, or at minimum eosim list | grep -q x86_64-linux. This should fail on the current head — which is the point: it is the check that would have caught finding 1 in the same job rather than three jobs later.
3 Medium PR body, "Verified against the real remote" The body's evidence is for a version of this change that no longer exists. It records clone v1.5.0 + pip install -e -> rc 0 and eosim doctor -> rc 0; the head pins a SHA and installs without -e. It also still says "Bumped to 1.5.0" and quotes EOSIM_VERSION, while both files now carry EOSIM_COMMIT. The 2026-09-03T17:17 comment supersedes parts of it, but the body is what a reviewer reads first, and here the one token it differs by — -e — is the whole of finding 1. Separately, eosim doctor -> rc 0 is not evidence of anything given finding 2. Rewrite the body against the current head, and cite the CI runs now that both workflows execute on the PR — that is far stronger than a local table.
4 Medium .github/workflows/eosim-sanity.yml:76-101, :238 published-artifact-watch can fail the workflow, and the gate with it. The comment at :70 and the PR comment both say it "cannot fail the workflow, deliberately". It is in sanity-gate's needs: (:238), and the gate fails on any non-success result. The job body runs set -euo pipefail and then pypi=$(curl -s -o /dev/null -w '%{http_code}' https://pypi.org/pypi/eosim/json) — curl without -f still exits 7 on a connection or DNS failure, and a failing command substitution in an assignment terminates the script under set -e. gh api … --paginate over every release is the same shape. So an outage at pypi.org, or a token hiccup, turns a tracking signal into a red gate on a workflow this PR is trying to make requirable. Give the two probes an explicit floor: pypi=$(curl -s -o /dev/null -w '%{http_code}' … || echo 000) and assets=$(gh api … || echo ""), and end the step with exit 0. If it genuinely must never gate, take it out of sanity-gate's needs: as well — with the floor in place it always succeeds, so its presence there is decoration that can only ever hurt.
5 Low .github/workflows/simulation-test.yml:20-24 The comment above EOSIM_COMMIT in this file still describes a tag pin — "v1.5.0 is the release marked Latest, and is what eosim-sanity.yml already pins" — beside a variable that holds a SHA, and it omits the reason the SHA exists. The full rationale (the tag/commit/pyproject/__init__ table, and "v1.5.0 is a label rather than a version") lives only in eosim-sanity.yml:26-46. A reader of this file is told the pin follows a tag that is Latest, which is the belief the SHA was introduced to prevent. Point at the other file explicitly — "pinned by commit; see the table in eosim-sanity.yml for why the tag namespace cannot be trusted" — or repeat the two-line summary. Two files, one fact, and only one of them currently states it correctly.

Carried from the previous round and unchanged: tests/CMakeLists.txt still carries #127's test_crypto_ed25519_loworder registration, declared in the body as a stack. Fine as-is; drop it when #127 lands.

What I verified rather than took on trust

  • Finding 1's root cause, measured on the pinned tree (git archive 7dec3460 eosim platforms):

    editable  EOSIM_ROOT = /tmp/ar129        platforms/ exists, 150 entries
    installed EOSIM_ROOT = /tmp/ar129/sp     platforms/ absent
    

    and git ls-tree -r 7dec3460 -- platforms | wc -l → 199 files, with no MANIFEST.in and include = ["eosim*"] in pyproject.toml. So this is structural, not a runner accident.

  • Finding 2, executed. With only the eosim package on PYTHONPATH (the installed layout), eosim list printed Available platforms (0): and returned 0.

  • The CI picture, from the check-runs API rather than the bundle's snapshot — the bundle was cut mid-flight and shows several jobs as pending that have since finished:

    success  Install & Validate  (3 OS × 3 Python, all 9)
    success  Windows Sanity, macOS Sanity
    success  EoSim publishes no installable artifact (tracking)
    failure  Nested Simulation  (all 7 platforms)
    failure  Guest OS Install   (all 3 guests)
    failure  Simulate           (all 11 platforms)
    failure  EoSim Sanity Gate, Simulation Gate
    

    Every failure carries the identical traceback. Full-stack integration summary and Cross-compile ARM64 kernel are the usual inherited eBoot-master breakage; the Cross-compile ARM Cortex-M4 pair of success + cancelled is a superseded run, not a failure.

  • This is not a pre-existing red being surfaced. master installs with -e at every clone site (eosim-sanity.yml:39,70,98; simulation-test.yml:45,74). The scheduled runs never reached the simulate jobs — the last five nightly EoSim Sanity runs all failed at Install & Validate and skipped everything downstream — so eosim run has never been observed green here. But under -e it resolves platforms/ correctly by construction, and under a plain install it cannot. The change from one to the other is in this diff.

  • The install half genuinely works. Nine green Install & Validate legs across ubuntu/windows/macos × Python 3.10/3.11/3.12 mean the --filter=blob:none clone plus checkout --detach <sha> plus pip install all succeed, and that EOSIM_EXPECTED_DIST: "3.0.1" is the value pip actually resolves at that commit — the assertion added for finding 3 passes rather than passing vacuously. ${{ runner.temp }} (finding 5 last round) is correct on the Windows leg. That is real progress and I do not want it lost in the above.

  • The sanity-gate rewrite is right. Iterating toJSON(needs) rather than testing install-validate alone is what makes the gate red here instead of printing "All EoSim sanity checks passed" over ten failed jobs — which is precisely what master's version would have done on this run. Worth stating plainly: the old gate would have called this green.

Architecture conformance

§17, EoSim as an adoption primitive — this PR is where the section stops being satisfiable. §17 says a user "must be able to experience EmbeddedOS before purchasing or configuring hardware" and sets "Discover → Install → ebuild run --sim", target "first simulated application in minutes". §39's success state requires an independent developer to "install the SDK, run EoS in simulation". Findings 1 and 2 together say: EoSim has no published artifact (13 releases, zero wheels, zero sdists, not on PyPI — verified last round and by this PR's own tracking job), and the artifact it would publish would not work, because platforms/ is not packaged. The Install step of §17 does not exist today by either route except git clone plus an editable install, which is a developer-mode workflow, not an install.

§10 / .ai/platform.md, "repositories are not the dependency API" — this is the concrete instance. eos now depends on EoSim by git URL and commit SHA, in two workflow files. The SHA pin is the correct thing to do given that a git URL is the only route (it is honest and immutable, unlike the tag), but it is the platform-services non-negotiable being violated because nothing better exists. .ai/platform.md is explicit: "A consumer depends on a component with a version range, never on a git URL or a path into another repo's tree."

§28, status and evidence — finding 2 is a §28 violation in miniature: eosim doctor -> rc 0 was recorded as evidence of a working install, and the check that produced it could not have failed.

§21 / §5.1 — not engaged. Workflow files plus the stacked tests/CMakeLists.txt hunk; nothing crosses a tier.

Weakened checks — none added, and two removed: the fail-open sanity-gate and, per the previous round, the eosim --version constant. Finding 2 is a fail-open check this PR inherits and relies on, not one it introduces.

I have appended an architecture proposal covering §17's missing Install step — see .ai/autoreview/proposals/2026-09.md.

Proposed changes

  1. Finding 1 first, and it is a revert: pip install -e at all five sites. Everything else here is secondary to the fact that the workflows are 22-jobs red and this is the whole reason.
  2. Finding 2 in the same push, because otherwise the next round of this has the same blind spot: make the validate step assert a non-empty platform list. Expect it to be red until step 1 lands — that is the correct sequence, test first.
  3. Finding 4 — two || floors and an exit 0.
  4. Findings 3 and 5 — text.
  5. Then re-run. Both workflows now execute on the PR, so for the first time the claim "this fixes EoSim CI" can be settled by the checks rather than by a local table.
  6. Open the EoSim issue named in finding 1. It is the one that actually matters: until platforms/ is packaged and located through importlib.resources, no wheel EoSim ever publishes will work, so the packaging debt the tracking job watches for is larger than "publish a wheel".

I opened no fix PR. Finding 1 is High and the fix is one word at five sites, but the sites are inside workflow files this PR rewrites — a branch cut from master would conflict with it, and the brief forbids touching a branch belonging to an open PR. Finding 2's fix has to land together with it, and I cannot run either through Actions from here.

Not checked

  • I did not install EoSim with pip in either mode. pip has no network in this sandbox. Finding 1 rests on (a) the 22 CI failures with the site-packages/platforms path in the traceback, which is direct evidence for the non-editable half, and (b) the path arithmetic of Path(__file__).parent.parent.parent measured against the two real directory layouts, which is deterministic — but I did not observe an editable install succeed at eosim run.
  • eosim doctor was not run in the empty-platforms layout. It is in an && chain after eosim list in a job that CI reports green, so it exits 0 there; I confirmed eosim list directly and inferred doctor from the job result.
  • Whether platforms/ under eosim/ is the right fix for EoSim is a recommendation, not a verified design. EoSim was not built or tested; I read pyproject.toml and eosim/cli/main.py at 7dec3460 only. The local EoSim checkout is dirty and was left untouched.
  • Finding 4 was reasoned, not reproduced. set -e terminating on a failed command substitution is standard bash behaviour and curl without -f exits 7 on a connection failure, but I did not force a network failure in Actions to watch the gate go red.
  • simulation-test.yml's Cross-Platform and Simulation Gate jobs are pre-existing and unmodified by this PR; the three Cross-Platform legs are green. I did not read their bodies.
  • The 11 vs 12 Simulate (…) legs: the bundle's checks.txt lists twelve and the check-runs API eleven distinct names for the completed run. I did not chase the discrepancy; every one of them fails identically, so it does not affect any finding.

Automated architecture review of 731331d4591e — 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.

@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 — eos#129 "ci: finish the EoSim fix — a tag that exists, and no wheel anywhere"

head: 71e038d author: Kartikey1306 ci: fail (2 of 40 — both cross-repo; all 17 EoSim jobs pass)

Verdict: The fix works and the process behind it was the right one — the author added a pull_request trigger so the workflows would actually execute, ran them four times, and found three blockers that were not visible by reading, including noticing that the -e flag they were asked to drop had been masking the platforms/ packaging bug. All 17 EoSim jobs pass on this head, for the first time in these workflows' history. Two things need attention: the new sanity-gate hand-rolls the same gate rule eos#121 extracts into a shared script specifically so it would not be duplicated, and the hand-rolled copy is weaker; and adding a pull_request trigger to two workflows breaks a test eos#121 introduces.

Findings

# Severity File:line Finding Recommended fix
1 Medium .github/workflows/eosim-sanity.yml:355-369 sanity-gate re-implements eos#121's gate rule inline, and the copy fails open on empty input. The jq expression is character-for-character #121's to_entries[] | select(.value.result != "success"), but the inline version omits both the set -euo pipefail and the empty/null guard that .github/scripts/ci-gate-check.sh has. Executed side-by-side comparison:
input          #129 inline    #121 script
""          rc=0 PASS   rc=1 refuse
null        rc=5 raw jq err rc=1 refuse
{}          rc=0 PASS      rc=0 PASS
[]          rc=0 PASS      rc=0 PASS
{"a":{"result":"skipped"}} rc=1         rc=1
So an empty RESULTS prints "All EoSim sanity jobs succeeded." and exits 0 here, where #121's script refuses. null produces jq: error (at <stdin>:0): null (null) has no keys rather than a diagnosis. (The {}/[] hole is shared and I have reported it separately on eos#121 — {} is what toJSON(needs) renders for a job with no needs:.) The comment on :348-354 is right that this form "cannot fall out of step with needs:", which was the real defect; the issue is that it is now the second implementation of the rule, and #121's test_every_gate_invokes_the_shared_script only covers the six workflows in its registry, so nothing holds this copy to the same behaviour.
Once #121 lands, replace the inline body with the shared script — it is a one-line run: plus a checkout step and a GATE_NAME, exactly as #121's three gates do:
- uses: actions/checkout@v4
- env: {RESULTS: '${{ toJSON(needs) }}', GATE_NAME: "EoSim Sanity Gate"}
run: printf '%s' "$RESULTS" | .github/scripts/ci-gate-check.sh
If #129 lands first, add set -euo pipefail and the empty/null guard to the inline body now, and open a follow-up to converge. Either way the two must not stay divergent.
2 Medium .github/workflows/eosim-sanity.yml:5-8, .github/workflows/simulation-test.yml:7-11 Merge interaction with eos#121 that neither PR mentions: test_every_pull_request_workflow_is_classified will fail once both land. #121's test globs .github/workflows/*.yml, keeps those with a pull_request trigger, and asserts every one appears in REQUIRED_CHECKS or NOT_REQUIRED. Its registry (verified by reading tests/unit/test_ci_gate.py at #121's head) covers ci.yml, build.yml, eos-simulation.yml, codeql.yml, python-tests.yml, third-party.yml, auto-assign.yml, claude-code-review.yml and book-build.yml — grep for eosim or simulation-test in that file returns nothing. This PR gives both eosim-sanity.yml and simulation-test.yml a pull_request trigger, so after both merge each is an unclassified pull-request workflow and that test fails. Add both to NOT_REQUIRED with a paths-filter reason, which is the same shape #121 already uses for book-build.yml ("its pull_request trigger is filtered to paths: …"). Because both new triggers do carry paths:, they also satisfy #121's test_workflows_recorded_as_not_requirable_really_are_not, so the fix is two dictionary entries and nothing else. Coordinate with #121 on which PR carries them.
3 Low .github/workflows/eosim-sanity.yml (5 sites), .github/workflows/simulation-test.yml:51-66, :93-108 The five-line install recipe is copy-pasted at seven sites, and has already needed three rounds of per-site fixes. The identical git clone --filter=blob:none / checkout --detach / pip install / derive SITE_PACKAGES / cp -r platforms block appears at every install point. The PR history shows the cost directly: -e had to be dropped "at all five sites, not two", ${{ runner.temp }} at all of them, and shell: bash at several — each a separate round because each site is a separate edit. The python -c "import importlib.metadata …" version assertion is likewise triplicated. Extract a composite action, .github/actions/install-eosim/action.yml, taking commit and expected-dist as inputs, and replace all seven sites with - uses: ./.github/actions/install-eosim. That also gives the platforms/ workaround and the version assertion one place to be deleted from when EoSim fixes its packaging.
4 Low .github/workflows/eosim-sanity.yml:73-99 (with :344) published-artifact-watch cannot fail, and it is in sanity-gate's needs. Both branches exit 0 — ::notice:: if an artifact appears, ::warning:: if not — so it contributes no signal to an all-must-succeed gate while occupying a slot in it. It also surfaces as a passing check literally named EoSim publishes no installable artifact (tracking) (confirmed in checks.txt: pass), i.e. a green tick whose name asserts a deficiency. I agree with the author's reasoning that eos must not gate its merges on another repository's release process, and the debt is real and worth tracking — this is about where it sits, not whether it should exist. Drop it from sanity-gate's needs — it is a notice, not a check — and rename it so the check name is not a claim, e.g. EoSim artifact publication (informational). Consider moving it to the scheduled trigger only, so it does not add a permanently-green status to every pull request that touches these files.
5 Low .github/workflows/eosim-sanity.yml (5 sites), simulation-test.yml:63, :105 SITE_PACKAGES is derived as os.path.dirname(os.path.dirname(eosim.__file__)), which depends on import resolution finding the installed package rather than a same-named directory on sys.path. eBoot's copy of this workflow — which the author cites as where this fix came from — uses python -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])', which needs no import and cannot be shadowed. Two repositories now solve the same problem two different ways. It works today because the clone goes to ${{ runner.temp }} and the step's cwd is the eos checkout, so nothing shadows it. Match eBoot: SITE_PACKAGES=$(python -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])'). Fold into finding 3's composite action so it is stated once.
6 Low .github/workflows/simulation-test.yml:20-24 The comment on EOSIM_COMMIT still argues the superseded rationale — "v1.5.0 is the release marked Latest, and is what eosim-sanity.yml already pins" — after the pin became a SHA. A reader now sees a SHA explained by an argument about which tag to choose. The # v1.5.0 as of 2026-09-03 trailing comment carries the useful part. Rewrite to state why a SHA rather than a tag: EoSim's v1.5.0 tag reports dist version 3.0.1 and its v3.0.1 tag reports __init__ 2.0.0, so neither tag name is a reliable identifier and the commit is pinned instead. That is the actual reason and it is more useful than the tag-selection history.
7 Low (CI) 2 of 40 checks fail, neither from this diff: Cross-compile ARM64 kernel fails building eBoot (eBoot/include/eos_image.h:135:23: error: 'eos_image_header_t' has no member named 'reserved'), and Full-stack integration summary as its dependent. Confirmed pre-existing — same failure on origin/master at feee2726 and on eos#121, #126 and #134. The body names eBoot#94 as the repair while a later comment on this PR names eBoot#97 as superseding that diagnosis; the two attributions disagree within the same PR. Nothing beyond reconciling the eBoot PR number. I did not look at eBoot.

Architecture conformance

Conforms. Master design §21 places CI templates under Infrastructure, and EoSim in Tier 1 — Foundation alongside eos, eBoot and ebuild. This diff touches only two workflow files plus the shared tests/CMakeLists.txt hunk; no runtime code, no import, no link line, no manifest entry, so §5.1's dependency direction is untouched and §21.1 is not in play.

It serves §17 directly, which is the section that matters here: "EoSim should be treated as essential to developer onboarding and CI, because a user must be able to experience EmbeddedOS before purchasing or configuring hardware", and "CI tests sharing the same application artifacts used on real hardware". The author's framing of the open debt is exactly right against that section — with no wheel and no PyPI presence, §17's Discover → Install → ebuild run --sim has no Install step for anyone outside the org, and every job in the org installs from a git clone. That gap is already recorded as a proposal ("§17 makes Install an adoption step and nothing requires a tool to be installable" in .ai/autoreview/proposals/2026-09.md), so I am not appending a duplicate.

Checks were strengthened, not weakened. sanity-gate moves from testing install-validate alone while printing "All EoSim sanity checks passed" to iterating every dependency — that was a genuine fail-open gate and the fix is correct in substance (finding 1 is about the implementation being duplicated, not about the direction). pip install -e becomes a plain install at every site, which is stricter and, as the author observed, is what exposed the platforms/ bug that the editable install had been accidentally papering over. EOSIM_EXPECTED_DIST adds an assertion where there was none.

The tests/CMakeLists.txt hunk is disclosed here, unlike on eos#126: the body opens with "Stacked on #127 so this branch is not red for the unrelated test_crypto_ed25519_loworder reason. Review the second commit." That is the right way to carry it. It is still the same block #118, #119, #121, #126 and #127 all add at the same anchor, so the merge-order note applies.

Two process points worth recording as correct, because they are the reason this PR found real problems: the author noticed that before the pull_request trigger existed their own earlier commits never ran the workflow they were editing, so the green checks on those commits were other workflows — "a check that does not run is not a check", one level up. And they identified that -e was masking the platforms/ dependency rather than treating its removal as unrelated churn. Both are the kind of thing that only surfaces by running the thing.

Proposed changes

In order:

  1. Finding 2 first — two entries in #121's NOT_REQUIRED, decided jointly with that PR. Cheapest and prevents a broken master.
  2. Finding 1 — converge on the shared script, or add the missing guards now if this lands first.
  3. Finding 3 + 5 together — one composite action, which is also where finding 5's sysconfig change belongs:
# .github/actions/install-eosim/action.yml
inputs:
  commit:        { required: true }
  expected-dist: { required: true }
runs:
  using: composite
  steps:
    - shell: bash
      run: |
        set -euo pipefail
        git clone --filter=blob:none https://github.com/embeddedos-org/EoSim.git "${{ runner.temp }}/EoSim"
        git -C "${{ runner.temp }}/EoSim" checkout --detach "${{ inputs.commit }}"
        pip install "${{ runner.temp }}/EoSim"
        # EoSim ships only eosim/platforms/__init__.py but resolves
        # PLATFORMS_DIR to <site-packages>/platforms. Delete when fixed upstream.
        SITE_PACKAGES=$(python -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])')
        cp -r "${{ runner.temp }}/EoSim/platforms" "$SITE_PACKAGES/"
        python - <<'PY'
        import importlib.metadata as m, os, sys
        got, want = m.version("eosim"), "${{ inputs.expected-dist }}"
        print(f"eosim dist version: {got}")
        sys.exit(0 if got == want else f"expected {want}, got {got}")
        PY
  1. Findings 4 and 6 — cosmetic but cheap.

On the three EoSim issues the author says they cannot file (publish a wheel/sdist, single-source __version__, reconcile or delete the v1.5.0 tag): all three are well-evidenced and worth filing. They are EoSim's to fix, and a maintainer with write access should open them; the diagnosis in this PR is enough to write them from.

Not checked

  • tests/unit/test_ci_gate.py — I could not execute it. It import yaml and pyyaml is not installed in my environment. Finding 2 is therefore Observed, not Verified by execution: I read #121's REQUIRED_CHECKS/NOT_REQUIRED literals and confirmed by grep that neither workflow appears in that file, and I read the new pull_request: triggers in this diff. I did not run the combined tree and watch the test fail. The reasoning depends only on the registry contents and the trigger presence, both of which are plain text, but I have not seen the red.
  • I did not run either workflow. Per the run's rules I pushed nothing. The four runs and the two green run URLs in the comments are the author's evidence, and checks.txt on this head independently corroborates the outcome: all 17 EoSim jobs pass — EoSim Sanity Gate, EoSim publishes no installable artifact (tracking), 3 × Guest OS Install, 6 × Nested Simulation, 3 × Cross-Platform, 3 × Simulate.
  • YAML validity I did not verify — no pyyaml, so the body's "both files still parse as YAML" is unconfirmed by me. That the jobs ran on CI is strong indirect evidence.
  • Every remote claim — no v0.1.0 tag, 13 releases with no wheel or sdist, pypi.org/pypi/eosim/json → 404, refs/tags/v1.5.0 → commit 7dec3460, and the version table (v1.5.0 → pyproject 3.0.1, v3.0.1 → __init__ 2.0.0) — I did not re-verify against the EoSim remote. I read the author's commands and they are the right commands, but the values are theirs, not mine. The SHA pin 7dec3460cba76083b6645eb4a867e39aa2af97df in particular I did not confirm corresponds to v1.5.0.
  • Windows and macOS behaviour. Findings about shell: bash and pwsh I take from the author's run logs; my host is Linux and I ran nothing on those platforms.
  • Whether eosim run produces correct output rather than merely exiting 0 — the author flags this explicitly under "Not run" and it remains open. Also their note that eosim list prints (0) while discover_platforms() returns 149 on the same directory, and exits 0: if accurate that means Validate platform / Validate all platforms are steps that cannot fail. I did not verify it, but it would make three of these jobs' validation steps vacuous and is worth checking before treating these greens as evidence about simulation correctness.
  • What I did run: the side-by-side probe in finding 1 — the inline sanity-gate body extracted verbatim into a script and invoked under bash -e against five inputs, compared against .github/scripts/ci-gate-check.sh from eos#121's head, with jq present. Nothing else in this PR is locally executable.

Automated architecture review of 71e038d8c7d0 — 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 added a commit to Kartikey1306/eos that referenced this pull request Sep 4, 2026
…atch that stops posing as a check

Answers the overnight review on embeddedos-org#129.

Finding 3 (Low, and the structural one) -- the five-line install recipe was
copy-pasted at seven sites across two workflows, and the PR's own history
shows the cost: -e dropped "at all five sites, not two", runner.temp at all
of them, shell: bash at several, each a separate round because each site was
a separate edit. Now .github/actions/install-eosim owns it -- clone at the
pinned commit, install, stage platforms/, assert the dist version -- and all
seven sites are a four-line `uses:`. The platforms/ workaround and the
version assertion get one place to be deleted from when EoSim fixes its
packaging. The triplicated inline importlib.metadata assert is gone with it.

Finding 5 (Low), folded into the composite -- SITE_PACKAGES comes from
sysconfig.get_paths()["purelib"], which needs no import and cannot be
shadowed, matching eBoot's copy of the workaround instead of solving the same
problem a second way.

Finding 1 (Medium) -- the inline gate accepted nothing as everything: an
empty RESULTS printed "All EoSim sanity jobs succeeded." and exited 0, and
null produced a raw jq error, where eos#121's extracted ci-gate-check.sh
refuses both. Both gates now refuse empty/null input with a diagnosis before
jq runs, under set -euo pipefail, and carry a note to become a call to embeddedos-org#121's
script once it is on master so the two cannot drift.

  Reproduced the review's side-by-side on the hardened body:
      ""      rc=1  gate received no results to check   (was rc=0 PASS)
      null    rc=1  gate received no results to check   (was raw jq error)
      {}      rc=0  PASS   -- shared with embeddedos-org#121's script; reported there, and
      []      rc=0  PASS      unreachable here: needs has five entries
      skipped rc=1  FAIL: a: skipped
      success rc=0  PASS

Also applied to simulation-test.yml's Simulation Gate, which still had the
original fail-open shape -- needs: [simulate, cross-platform], a test of
`simulate` alone, then "All simulation tests passed". Same toJSON(needs)
body, same guards.

Finding 4 (Low) -- published-artifact-watch could not fail and sat in
sanity-gate's needs under a name that made a green tick assert a deficiency.
Now "EoSim artifact publication (informational)", schedule/dispatch only, out
of the gate: pull requests no longer carry a permanently-green status about
another repository's release process, and the debt still gets said out loud
every night.

Finding 6 (Low) -- simulation-test's EOSIM_COMMIT comment argued tag
selection for what is now a SHA; it now states the actual reason (EoSim's tag
names do not identify their contents) and gains the EOSIM_EXPECTED_DIST the
composite asserts.

Finding 2 (Medium) is a two-line change in eos#121's registry, not here --
both workflows need NOT_REQUIRED entries with a paths-filter reason once both
PRs land, or embeddedos-org#121's classification test fails. Posted on both threads with
the exact entries; not folded in, because that registry lives on embeddedos-org#121's
branch and this PR должен not carry another PR's hunks.

Verified locally before push:
  all three YAML files parse
  composite referenced at 7 sites; zero inline clone/install/copy remnants
  eosim-sanity gate needs == every job except itself and the informational
    watch; sim gate iterates toJSON(needs), no single-dependency branch
  the five-input table above, executed
  the workflows themselves: this push's pull_request run is the test, and I
  will report what it shows rather than predict it.

Refs embeddedos-org#129
…atch that stops posing as a check

Answers the overnight review on embeddedos-org#129.

Finding 3 (Low, and the structural one) -- the five-line install recipe was
copy-pasted at seven sites across two workflows, and the PR's own history
shows the cost: -e dropped "at all five sites, not two", runner.temp at all
of them, shell: bash at several, each a separate round because each site was
a separate edit. Now .github/actions/install-eosim owns it -- clone at the
pinned commit, install, stage platforms/, assert the dist version -- and all
seven sites are a four-line `uses:`. The platforms/ workaround and the
version assertion get one place to be deleted from when EoSim fixes its
packaging. The triplicated inline importlib.metadata assert is gone with it.

Finding 5 (Low), folded into the composite -- SITE_PACKAGES comes from
sysconfig.get_paths()["purelib"], which needs no import and cannot be
shadowed, matching eBoot's copy of the workaround instead of solving the same
problem a second way.

Finding 1 (Medium) -- the inline gate accepted nothing as everything: an
empty RESULTS printed "All EoSim sanity jobs succeeded." and exited 0, and
null produced a raw jq error, where eos#121's extracted ci-gate-check.sh
refuses both. Both gates now refuse empty/null input with a diagnosis before
jq runs, under set -euo pipefail, and carry a note to become a call to embeddedos-org#121's
script once it is on master so the two cannot drift.

  Reproduced the review's side-by-side on the hardened body:
      ""      rc=1  gate received no results to check   (was rc=0 PASS)
      null    rc=1  gate received no results to check   (was raw jq error)
      {}      rc=0  PASS   -- shared with embeddedos-org#121's script; reported there, and
      []      rc=0  PASS      unreachable here: needs has five entries
      skipped rc=1  FAIL: a: skipped
      success rc=0  PASS

Also applied to simulation-test.yml's Simulation Gate, which still had the
original fail-open shape -- needs: [simulate, cross-platform], a test of
`simulate` alone, then "All simulation tests passed". Same toJSON(needs)
body, same guards.

Finding 4 (Low) -- published-artifact-watch could not fail and sat in
sanity-gate's needs under a name that made a green tick assert a deficiency.
Now "EoSim artifact publication (informational)", schedule/dispatch only, out
of the gate: pull requests no longer carry a permanently-green status about
another repository's release process, and the debt still gets said out loud
every night.

Finding 6 (Low) -- simulation-test's EOSIM_COMMIT comment argued tag
selection for what is now a SHA; it now states the actual reason (EoSim's tag
names do not identify their contents) and gains the EOSIM_EXPECTED_DIST the
composite asserts.

Finding 2 (Medium) is a two-line change in eos#121's registry, not here --
both workflows need NOT_REQUIRED entries with a paths-filter reason once both
PRs land, or embeddedos-org#121's classification test fails. Posted on both threads with
the exact entries; not folded in, because that registry lives on embeddedos-org#121's
branch and this PR must not carry another PR's hunks.

Verified locally before push:
  all three YAML files parse
  composite referenced at 7 sites; zero inline clone/install/copy remnants
  eosim-sanity gate needs == every job except itself and the informational
    watch; sim gate iterates toJSON(needs), no single-dependency branch
  the five-input table above, executed
  the workflows themselves: this push's pull_request run is the test, and I
  will report what it shows rather than predict it.

Refs embeddedos-org#129
@Kartikey1306
Kartikey1306 force-pushed the fix/eosim-remaining-wheel-and-version branch from 344cb54 to 54c9f05 Compare September 4, 2026 06:25
@Kartikey1306

Copy link
Copy Markdown
Contributor Author

All six findings addressed at the new head — composite install-eosim action replacing the seven copy-pasted recipes (with sysconfig.get_paths()["purelib"], matching eBoot), both gates refusing empty/null input with the side-by-side table reproduced in the commit, the watch job renamed EoSim artifact publication (informational), schedule-only, and out of the gate, and the EOSIM_COMMIT comment stating the real SHA rationale.

Finding 2 is deliberately not folded in, because the registry it changes lives on eos#121's branch and this PR should not carry another PR's hunks. The exact fix, for whichever of the two lands second, is two entries in NOT_REQUIRED:

"eosim-sanity.yml":
    "pull_request trigger is filtered to paths: [its own file and "
    "simulation-test.yml], so it reports only on changes to itself; "
    "requiring it would block every other PR on a status that never arrives",
"simulation-test.yml":
    "same paths-filtered self-test trigger as eosim-sanity.yml",

Both new triggers carry paths:, so they also satisfy test_workflows_recorded_as_not_requirable_really_are_not as-is. Cross-posted on #121.

Also fixed while in the file: simulation-test.yml's Simulation Gate still had the original fail-open shape — needs: [simulate, cross-platform], a branch on simulate alone, then "All simulation tests passed". Same toJSON(needs) body and empty-input guards as the sanity gate now.

Every open eos pull request is currently red on `EoS Full-Stack Simulation`,
and none of them caused it. The kernel job checks out embeddedos-org/eBoot at
`ref: master`, and eBoot master does not compile: include/eos_image.h:135 and
:142 static-assert offsetof(eos_image_header_t, reserved) for a member that
became tlv_len + tlv_hash, and core/ed25519_verify.c redefines
point_is_identity -- two pairs of PRs that each merged clean and broke the
build together. eBoot embeddedos-org#94 repairs it and waits on review; until it lands, no
change to any eos PR can make this job pass, and after it lands the next
broken eBoot master does the same thing again.

A floating `ref: master` makes every eos PR's CI depend on the moment-to-
moment state of another repository's default branch. Pinning the two
compiled-against checkouts makes the job a function of this repository plus
two recorded SHAs -- red means the PR broke something, green means it did not,
and a cross-repo bump is a reviewable one-line diff with CI on it.

  EBOOT_COMMIT  a172a6d6e1e6  the newest eBoot master ancestor that compiles;
                found by walking master back and building each candidate.
                Its child 8a015b2 already carries the ed25519 redefinition.
  EBUILD_COMMIT e5d8052f3e2c  ebuild's current master, frozen as-is. Both of
                its checkouts feed steps that are commented out (eFab does
                not exist), so this pin only removes the float.

The middleware matrix (10 repos) still floats; it runs those repos' own
tests rather than compiling eos against them, and 10 more pins deserve their
own decision. When eBoot embeddedos-org#94 merges, bump EBOOT_COMMIT to the merge SHA.

Verified before pushing, master vs pin under the job's own configuration
(-DEBLDR_BOARD=qemu_arm64 -DEBLDR_VERIFY_STAGE1=OFF -DCMAKE_BUILD_TYPE=Release,
cross-compile mode): eBoot@master fails at the eos_image.h asserts, the exact
error in the job log; eBoot@a172a6d builds every target, rc=0. Both pinned
SHAs verified reachable from their repos' master. Workflow parses; the three
`ref:` edits and the env block are the whole diff. This PR's own simulation
run is the live test: it uses this branch's workflow and should go green
while every master-based PR stays red.

Carried onto this branch from embeddedos-org#135 (001128d) so this PR's own simulation
job runs against a buildable eBoot: each pull request executes its own copy
of the workflow, so the fix greens a PR only once its branch contains it.
Byte-identical to embeddedos-org#135's commit -- git drops it as already-upstream the
moment embeddedos-org#135 merges. The pin itself is embeddedos-org#135's to review.

@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 — eos#129 "ci: finish the EoSim fix — a tag that exists, and no wheel anywhere"

head: d3b5852 author: Kartikey1306 ci: pass (64 check runs, 0 failures, 2 skipped by design)

Verdict: This is the right shape and the evidence behind it is real, not asserted. I pulled the authoritative check-run list for this head: 64 runs, 62 success, 2 skipped — all 11 Simulate (…) legs, all 23 EoSim sanity jobs, both gates, and all three Cross-Platform legs including windows-latest. EoSim artifact publication (informational) is skipped on pull_request, exactly as its if: intends. The composite action removes seven copies of a recipe that had drifted three times, and the two gate rewrites replace bodies that asserted more than they checked. Two things need work: the new empty-input guard misses the value GitHub actually produces, and the comments describing the extracted recipe were left behind at the sites it was extracted from.

Findings

# Severity File:line Finding Recommended fix
1 Medium .github/workflows/eosim-sanity.yml (sanity-gate), .github/workflows/simulation-test.yml (sanity-gate/"Simulation Gate") The guard does not cover the empty case that can actually occur. toJSON(needs) for a job with an empty or deleted needs: renders {} — not "" and not null — so [ -z "${RESULTS:-}" ] || [ "$RESULTS" = "null" ] passes it through, jq 'to_entries[]' over {} emits nothing, bad is empty, and the gate prints "All EoSim sanity jobs succeeded." and exits 0. Deleting one line of needs: restores the exact fail-open behaviour this rewrite replaced, and the comment above it claims the opposite ("Refuse to conclude anything from nothing"). Related: the gate now iterates whatever it is handed, so it cannot notice a job removed from needs: either — which is how the previous body came to test one dependency out of five. Guard on the object's size, not its string form: n=$(printf '%s' "$RESULTS" | jq 'length'); if [ "${n:-0}" -eq 0 ]; then echo "::error::gate received no results to check"; exit 1; fi. Then pin the expected count — [ "$n" -eq 5 ] for the sanity gate, -eq 2 for the simulation gate — so a shrinking needs: fails instead of passing quietly. Both gates, and the same two guards belong in #121's ci-gate-check.sh so the inline copies and the script still cannot disagree.
2 Low .github/workflows/eosim-sanity.yml (windows-sanity, macos-sanity run: bodies) The recipe moved into the composite action; its documentation did not. Both run: bodies still carry ten lines describing the wheel-404 install and the platforms/ copy — neither of which is in those bodies any more — followed by # dist-version assert lives in the install-eosim composite action above a bare eosim --version. The action exists to stop this recipe drifting across seven sites; leaving the recipe's comments at those sites re-creates the same drift in prose, and a reader now finds a platforms/ explanation attached to code that does not copy anything. windows-sanity's copied shell: bash comment also says "this job also runs on windows-latest", which is true of install-validate's three-OS matrix and not of a job whose runs-on: is only windows-latest. Delete the moved comments from both bodies, leaving one line pointing at ./.github/actions/install-eosim. Drop the duplicated shell: bash rationale from install-validate's two steps down to one, and reword the windows-sanity copy.
3 Low .github/actions/install-eosim/action.yml (clone step, dist-assert step) Both run: bodies interpolate ${{ inputs.* }} directly into the script text: git checkout --detach "${{ inputs.commit }}" and want = "${{ inputs.expected-dist }}" inside the <<'PYEOF' heredoc. Template substitution happens before the shell or Python sees the text, so the quoting around it is not protection — a value containing " breaks out of the shell word or the Python string literal. Not a live vulnerability: both call sites pass workflow-level env constants that no PR can influence. It becomes one the first time an input is wired to github.event.*, a fork-controlled matrix value, or anything from an issue body — and this file is deliberately the one place the recipe lives, so it will be called from more places than these seven. env: INPUT_COMMIT: ${{ inputs.commit }} on the step, then git checkout --detach "$INPUT_COMMIT"; and env: EXPECTED_DIST: ${{ inputs.expected-dist }} with want = os.environ["EXPECTED_DIST"]. Same cost, and it is GitHub's documented hardening rule for run: bodies.
4 Low .github/actions/install-eosim/action.yml ("Stage platform data") cp -r "${RUNNER_TEMP}/EoSim/platforms" "$SITE_PACKAGES/" is unguarded under set -euo pipefail, so the day EoSim fixes its packaging and stops shipping a top-level platforms/, every job in both workflows fails with a bare cp: cannot stat. Failing closed is right, but the action's own description calls itself "the one place to delete the platforms/ workaround from when EoSim fixes its packaging" and the failure will not say that. Guard on -d and emit ::notice::EoSim no longer ships a top-level platforms/; this step and the note in the env block can be deleted when it is absent, letting the following eosim list/eosim run be the real check. If you would rather keep it fatal, keep it fatal but name both possibilities in the message.

Architecture conformance

Conforms. §21: both workflows and the new composite action are Tier-1 eos infrastructure. §5.1 applied to CI dependencies as the recorded proposal reads it: eos consuming EoSim (Tier 1) is sibling-tier, so the direction is legal and only the ref was ever wrong. §17 is the section this PR serves — EoSim as an adoption primitive, "CI tests sharing the same application artifacts used on real hardware" — and the honest answer the PR gives is that the published-artifact half of that cannot be tested because no artifact exists; the informational job keeps that visible instead of letting a clone-based green stand in for it. That is the correct call under .ai/reviewer.md (a check that cannot fail is not a check) and it is why the job sits outside needs: and outside pull_request.

Two design gaps this PR sits on are already recorded, so nothing new is filed: the SHA-instead-of-released-ref pin, with the required record and the mandatory non-required drift job, in .ai/autoreview/proposals/2026-09.md (2026-09-04 addendum, triggered by eos#135 — the EOSIM_COMMIT block here is a good instance of the record that addendum asks for, and better than the eBoot one in #127 because it names what it evaluated and why it rejected it); and §17's missing Install step, i.e. that no released EoSim artifact is installable outside the org, in the 2026-09-03 entry "§17 makes Install an adoption step and nothing requires a tool to be installable". Your three EoSim-side items (publish a wheel/sdist, single-source __version__, reconcile or delete v1.5.0) are the concrete work behind that entry and are worth filing as EoSim issues regardless of write access — a maintainer can act on an issue, not on a PR comment in another repo.

Note on scope, not a finding against the diff

This head also carries d3b5852 "ci: pin the eBoot and ebuild checkouts instead of floating on master", which is the entire subject of eos#135 and is also on eos#127 — three open PRs with the same hunk — plus 2a26424, the test_crypto_ed25519_loworder restore that is additionally on #119, #122, #127 and #135. The body's "Stacked on #127 … Review the second commit" is stale: there are eight commits and the second is no longer the interesting one. The pin is correct and I verified it independently in the #127 review, so this is a merge-order problem, not a correctness one — but it does mean whichever of #127/#129/#135 lands second gets a conflict or an empty hunk, and it means a reviewer told to read "the second commit" reads none of the CI work.

Verified in this review

  • 64 check runs on this head: 62 success, 2 skipped, 0 failure. The skips are Create GitHub Release and EoSim artifact publication (informational); the latter is the if: schedule || workflow_dispatch behaving as designed. This is the first eos PR in this batch where the EoSim workflows report at all, which is the trigger change doing its job.
  • All 11 Simulate (<platform>) legs, Simulation Gate, all 23 sanity jobs, EoSim Sanity Gate, Windows Sanity, macOS Sanity and all three Cross-Platform legs are green — so the composite action, the sysconfig purelib copy and shell: bash work on ubuntu, macOS and Windows in practice, not just in argument.
  • Cross-compile ARM64 kernel is green here at 06:37:45Z while the same job failed on #119 at 06:35:46Z and on #122 — the difference being the eBoot pin this branch carries. Same-day, six minutes apart.
  • shell: bash in simulation-test.yml is on the Validate all platforms run: step, not on the adjacent uses: step — I checked, because shell alongside uses is a hard workflow-parse error. It is correct.

Not checked

  • Nothing was executed locally; no workflow was run from here. Everything above is either read from the files at d3b5852 or read from the GitHub check-run API for that SHA.
  • The bundle's checks.txt is incomplete for this PR — 40 rows against the API's 64 — so a reviewer working only from the bundle would not see the Simulate (…) matrix, Simulation Gate, Windows Sanity or the informational job's skip. Flagging because the same undercount would hide a failure on some other PR.
  • Green means the jobs completed. It does not mean the simulations are correct: eosim run --headless exiting 0 and eosim test <platform> exiting 0 are the assertions, and you already recorded that eosim list prints (0) while discover_platforms() finds 149 on the same directory — a CLI that miscounts and exits 0 is not evidence about the platform data. Not assessed here.
  • EOSIM_EXPECTED_DIST: "3.0.1" is asserted against importlib.metadata, which is the right source, but I did not confirm that 7dec3460's pyproject.toml declares 3.0.1 — the EoSim clone under the working root is dirty (179 files) so the sync step left it untouched and I did not read it.
  • The paths:-filtered pull_request trigger means these two workflows still do not run on an ordinary code change; the nightly cron covers regressions within 24 hours. So 64 green checks here should not be read as "simulation now gates eos". Your NOT_REQUIRED entries cross-posted to #121 are the right follow-through and I did not review #121.
  • Windows path handling in cp -r "$SITE_PACKAGES/" (a C:\… path under Git Bash) is load-bearing and is proven only by the green Windows Sanity and Install & Validate (windows-latest, …) runs on this head. It was not reasoned about, and it is the kind of thing that breaks on a runner-image change.

Automated architecture review of d3b5852e392d — 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.

@srpatcha
srpatcha merged commit 16cadfd into embeddedos-org:master Sep 8, 2026
66 checks passed
Kartikey1306 added a commit to Kartikey1306/eos that referenced this pull request Sep 14, 2026
Nine PRs were merged into master within minutes on 09-08, each on the base it
was written against. Master has not compiled since, and the Python guards
that would have named the rest never ran because the C build failed first.

Compile (every C job, CodeQL, and the ARM64 kernel in the simulation):
- services/linux/src/linux_security.c: embeddedos-org#119 and embeddedos-org#132 each added an #else to
  the same #ifndef _WIN32 in eos_busybox_install_to_rootfs(), so master has
  "#else after #else". The embeddedos-org#132 arm (`(void)bb;`) is the one removed -- the
  embeddedos-org#119 arm already uses bb and reports the unsupported platform.

Guards from embeddedos-org#121 / embeddedos-org#93 that later merges walked back:
- ci.yml: embeddedos-org#132 added windows-test after embeddedos-org#121's gate; the gate did not wait
  for it, so "CI Gate" could be green with the MSVC leg red.
- test_ci_gate.py: embeddedos-org#129 gave eosim-sanity.yml and simulation-test.yml a
  path-filtered pull_request trigger (they test their own edits); a
  path-filtered check cannot be required, so both are recorded in
  NOT_REQUIRED with the book-build.yml reason.
- tests/CMakeLists.txt: test_linux_security_paths (embeddedos-org#119) and test_pkg_fetch
  (embeddedos-org#115) had no add_executable(). embeddedos-org#115's replay replaced embeddedos-org#119's block with
  its own, and embeddedos-org#118's replay replaced that; two suites compiled against
  nothing. Both registered again. 41 -> 43 suites.
- tests/test_kernel.c: four tests from embeddedos-org#130 and embeddedos-org#131 were defined and never
  called -- their RUN() lines did not survive the replay of main().

And the one that was not bookkeeping:
- kernel/src/task.c: embeddedos-org#130 was merged after embeddedos-org#131 from a base that predates it,
  and its copy of task.c replaced embeddedos-org#131's. embeddedos-org#131 had also flattened 574 CRLF
  line endings, so its 1166-line diff hid a 39/21 change and the replay took
  embeddedos-org#130's side wholesale. Master kept embeddedos-org#131's tests and lost its kernel: the
  idle task could be deleted and suspended, a half-initialised TCB was
  published to the scheduler before its stack existed, and eos_schedule()
  pointed g_current_sp at the outgoing task. test_idle_task_is_permanent
  fails on master the moment it is called. embeddedos-org#131's task.c diff re-applied
  on top of embeddedos-org#130's; the result is embeddedos-org#131's file plus embeddedos-org#130's wake_armed hunk
  and nothing else (verified by diff against 3a00bd9).

Verified locally (macOS, clang): Release build clean, 43/43 ctest; the
README default configuration builds; 47/47 pytest.

Not in this PR: the nightly "Upstream drift" job builds eBoot at master and
eBoot master is broken separately (its own repair PR); bump EBOOT_COMMIT in
eos-simulation.yml once that lands.
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.

2 participants