fix: ci: point Validate Platforms at the directory the descriptors are actually in - #27
Conversation
…e actually in Opened by the scheduled autoreview pipeline after review of open PRs. Reviewed against the EmbeddedOS Master Design v2.0. Files: .github/workflows/ci.yml
srpatcha
left a comment
There was a problem hiding this comment.
Review — EoSim#27 "fix: ci: point Validate Platforms at the directory the descriptors are actually in"
head: ce75c9c author: srpatcha ci: fail (pre-existing on master; see below)
Verdict: The core fix is correct and I reproduced it independently — platforms/ does not exist on origin/master, eosim/platforms/ holds 149 platform.yml, and all 149 validate clean against eosim.core.schema.validate_platform. Four things stand between this and being finished: the job still cannot run in CI, the PR body misstates what the new guard protects against, the docs that encode the same wrong path are untouched, and the logic duplicates an existing pytest.
Note on role: this PR was opened by this same autoreview pipeline (autofix/validate-platforms-path). Per .ai/reviewer.md §"Cannot review own work" this is an observation comment only — it carries no approval and no merge verdict, and a human must make that call.
What I verified myself (not taken from the PR body)
Extracted origin/master with git archive into a temp dir (the local EoSim checkout has 179 dirty files and was not touched) and ran the step body verbatim for both paths:
'platforms': FileNotFoundError: [Errno 2] No such file or directory: 'platforms'
'eosim/platforms': Validated 149 platforms, 0 with errors
git ls-tree -r origin/master | grep -c '^eosim/platforms/[^/]*/platform\.yml$' → 149; no path under platforms/ exists at the root. The bug and the fix are both real.
Findings
| # | Severity | File:line | Finding | Recommended fix |
|---|---|---|---|---|
| 1 | Medium (P2) | .github/workflows/ci.yml:101 |
The fix cannot be exercised by CI, here or after merge. validate-platforms declares needs: lint, and Lint & Format has failed on every ci.yml run on master back to at least 2026-05-20 — I confirmed Validate Platforms = skipped in runs 33500937190 (2026-09-01) and 26149181083 (2026-05-20), and ruff check eosim/ on origin/master reports 357 errors. In this PR's own checks.txt the job is skipping again. So the only evidence for this change is two throwaway scripts under /tmp that no reviewer can inspect or re-run. |
Drop needs: lint from validate-platforms in this PR. The job needs pip install -e ".[dev]", not a style lane; it has no build-order reason to sit behind lint. That single deletion converts this PR from unverifiable to self-proving, and is the smallest change that gets the 149 descriptors under a gate that actually executes. |
| 2 | Medium (P2) | .github/workflows/ci.yml:131-133 (PR body, §Fix) |
The stated rationale for the zero-guard is wrong about the failure mode it covers. The body says a later move of eosim/platforms/ "makes os.listdir return an empty list, the step prints Validated 0 platforms and All platforms valid!, and exits 0". It does not: I ran the patched body against a missing directory and got FileNotFoundError — a traceback and a non-zero exit, with the new ERROR: line never printed. The guard's real coverage is directory exists but contains no platform.yml, which is a narrower case than the one the body argues from. |
Either correct the body, or better, make the guard cover the case it claims. Insert before the loop: if not os.path.isdir(platforms_dir): print(f'ERROR: {platforms_dir!r} does not exist'); sys.exit(1). Then relocation gives the same one-line diagnostic as depopulation instead of a stack trace, and the body's argument becomes true as written. |
| 3 | Medium (P2) | CONTRIBUTING.md:77-79,100; README.md:158-159; docs/platform-authoring.md:7,10,138,144; docs/api-reference.md:14,69,84,132,183 |
The same wrong path is written into every document a contributor reads, and this PR fixes only the CI copy. CONTRIBUTING.md:77 still instructs "Create platforms/<name>/platform.yml" — a contributor who follows it puts a descriptor where nothing reads it, and the newly-fixed gate will not see it. README.md:159 also claims "52+ platform definitions" against a verified 149. |
Fold the doc corrections into this PR — platforms/ → eosim/platforms/ at those lines, and 52+ → 149. It is the same one-line defect in the same change, and per the org rule a change that leaves existing documentation wrong is not finished. |
| 4 | Low (P3) | .github/workflows/ci.yml:110-137 vs tests/integration/test_platform_pipeline.py:88-107 |
Duplication, and it is the direct cause of this bug. TestPlatformValidation::test_validate_all_real_platforms already walks every descriptor and asserts errors == {}, using the correct eosim/platforms path. The CI job re-implements that same logic as a python -c heredoc inside YAML, where no linter, type checker or test can reach it — which is exactly why one copy drifted to a dead path and the other did not. Note also that tests/integration/ is run by nothing in CI: grep -rn "tests/integration" .github/workflows/ is empty, the only caller is Makefile:61. |
Replace the heredoc step with python -m pytest tests/integration/test_platform_pipeline.py::TestPlatformValidation -q. One call site, covered by the test suite, and it drags the integration directory into CI where it belongs. |
| 5 | Low (P3) | tests/integration/test_platform_pipeline.py:93-94,111-112 |
The pytest that this job duplicates carries the same silent-pass shape the PR body objects to: if not platforms_dir.exists(): pytest.skip("platforms/ directory not found"). It is harmless today because the path is right, but the day the directory moves, the test goes green by skipping while the CI job goes red — the two disagree in the one scenario the guard exists for. The skip message also still says platforms/. |
Turn both skips into pytest.fail(f"{platforms_dir} not found"), and fix the stale message. A fixture directory that ships in the repo is not an optional dependency. |
| 6 | Low (P3) | .github/workflows/ci.yml:139-147 |
Pre-existing, in the job this PR edits: Platform count check cannot fail. count < 100 emits ::warning:: only, and ls ... 2>/dev/null swallows the error. With the new hard guard at zero, the range 1-99 is now covered by a warning nobody reads — 148 descriptors could disappear with the job still green. |
exit 1 instead of ::warning::, or delete the step as redundant now that the validation step counts and fails. |
CI state
| Check | Result | Attribution |
|---|---|---|
| Lint & Format | fail | Pre-existing on master. 357 ruff errors in eosim/ on origin/master, verified locally. This PR touches only .github/workflows/ci.yml and cannot have caused it. |
| Quick Checks | fail | Same cause — pr-check.yml:30 runs ruff check eosim/. |
| Validate Platforms | skipping | Finding 1. The job this PR exists to fix did not run on this PR. |
| Test / Coverage / Docs / Build / Simulator Smoke Test (ci.yml) | skipping | All needs: lint. |
| CI Summary | pass | Green with six of its eight dependencies skipped or failed. Already the subject of PR #26; not re-raised here. |
| Security Scan, CodeQL (js-ts, python), Coverage Gate, Simulator Smoke, assign | pass | — |
Merge-conflict check
The body claims no overlap with #26. Verified, and extended: four open PRs touch ci.yml. Hunk ranges are #27 (this PR) 112-118 and 128-133; #26 280+; #22 22,44,65,100,151,196,216,237 (its 100 hunk is in the same job but stops at line 106); #16 137. No two ranges intersect, and GitHub reports this PR MERGEABLE.
Architecture conformance
Conforms. Master design §21 places EoSim in Tier 1 — Foundation (eos, eBoot, ebuild, EoSim), and §17 makes EoSim's CI contract part of the adoption path — "CI tests sharing the same application artifacts used on real hardware", with 149 platform descriptors as the shared artifact. This change is confined to .github/workflows/ci.yml, adds no import, link line or manifest entry, and creates no dependency in either direction, so §5.1 dependency law is not engaged. Restoring a Tier-1 validation gate to a working state is squarely what §17 asks for.
Proposed changes
Smallest sequence that leaves the tree working at every step:
- Keep the two lines already in the diff — they are correct.
- Remove
needs: lintfromvalidate-platforms(finding 1). This is the one change that makes the rest provable, and it is a single deleted line. - Add the
isdirpre-check (finding 2), or correct the PR body. Prefer the code. - Correct the five documentation sites and the
52+count (finding 3). - Leave findings 4-6 for a follow-up PR — they are a step rewrite and a test change, and folding them in here would mix a one-line CI path fix with a restructuring, which
.ai/architect.mdexplicitly warns against.
Not checked
- I did not run the workflow. No GitHub Actions run of
validate-platformsexists for this head, and I did not trigger one. My verification ran the step's Python body against an extracted copy oforigin/masterunder the host's Python 3.13, not the job'subuntu-latest/ Python 3.12 withpip install -e ".[dev]". Behaviour ofyaml.safe_loadandvalidate_platformshould not differ, but that is inference, not a CI pass. - I did not verify the PR body's
/tmp/eosim_run_validate_step.pyand/tmp/eosim_zero_guard.py. They are outside the repo and I did not read them. My 149-clean result is independent of them, not a confirmation of them. - I did not run the repo's test suite.
pytest,ruff format --check, and the integration suite were not executed; onlyruff check eosim/ --statisticswas, onorigin/master, to attribute the lint failure. - The
EoSimworking tree is dirty (179 files) and was left untouched, per the rules of engagement. Everything above was read fromorigin/masteror from agit archiveextract, so none of it reflects uncommitted local work. - Findings 3-6 describe code outside this diff. They are adjacent defects of the same root cause, not regressions this PR introduces.
Automated architecture review of ce75c9c34910 — 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.
Problem
The
Validate Platformsjob in.github/workflows/ci.ymlcannot pass. ItsValidate all platform YAML filesstep opens a directory that does not existin this repository:
.github/workflows/ci.yml:115. There is noplatforms/at the repositoryroot — the platform descriptors live in
eosim/platforms/, which is where thevery next step in the same job already looks:
.github/workflows/ci.yml:140. So the two steps of one job disagree aboutwhere the data is, and the one that actually validates is the one pointing at
nothing. Running that step verbatim against
origin/mastergives:Why nobody has hit it
validate-platformsdeclaresneeds: lint, andLint & Formathas failed onevery run of this workflow on
master(runs33500937190,
32813379622,
31154407920).
Validate Platformsis reportedskippedin all of them, so it has neverexecuted. The moment the lint lane goes green this becomes a hard failure —
this fix is a prerequisite for that work, not a competitor to it.
Fix
Two lines in
.github/workflows/ci.yml:platforms_dir = 'eosim/platforms'— point the validation at thedirectory that holds the descriptors, matching the count-check step.
The second one matters because of how this bug would come back. With the path
corrected but no guard, a later move of
eosim/platforms/makesos.listdirreturn an empty list, the step printsValidated 0 platformsandAll platforms valid!, and exits0. A validation gate that passes because itfound nothing to validate is worse than one that crashes: 149 platform
descriptors would silently stop being checked with the job still green.
Files changed
.github/workflows/ci.yml—validate-platformsjob only.Expected impact
Validate Platformsvalidates the 149eosim/platforms/*/platform.ymldescriptors against
eosim.core.schema.validate_platforminstead of abortingon a missing directory. All 149 pass today, so this does not introduce a new
red lane; it converts a job that could only ever fail into one that does its
job.
Risks and compatibility
Lint & Formatstill fails onmasterfor unrelated reasons (a large ruffbacklog across
eosim/), so this change on its own does not make CIgreen. It removes one of the blockers behind it.
ci-summaryjob, line 280+). This change is confined to the
validate-platformsjob atlines 109-137, so the two do not overlap textually and are independent
fixes to different jobs.
eosim/platforms/is ever relocated, the new guard turns the silentno-op into a visible failure. That is the intent.
Surfaced by the maintenance sweep scan
state/maint/20260906T013056/EoSim.md, §"CI — latest run on master".Verification
Executed in an isolated worktree branched from
origin/master:validate-platformspython3 /tmp/eosim_run_validate_step.pyzero-guardpython3 /tmp/eosim_zero_guard.pyOpened by the scheduled autoreview pipeline (model
claude-opus-5), branched fromorigin/master. No human has reviewed this yet. Close it freely if the fix is wrong - a bad automated PR is a bug worth reporting.Fixes #31