Skip to content

CI: trim per-PR simulator scene coverage - #1823

Merged
ChaoWao merged 1 commit into
hw-native-sys:mainfrom
doraemonmj:ci/downselect-sim-scenes
Aug 18, 2026
Merged

ChaoWao merged 1 commit into
hw-native-sys:mainfrom
doraemonmj:ci/downselect-sim-scenes

Conversation

@doraemonmj

@doraemonmj doraemonmj commented Aug 13, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Reduce the Per-PR simulator scene set by moving simulator-only lifecycle, error-matrix, stress, scale, and redundant-path coverage behind the existing manual selection.
  • Keep representative correctness paths in Per-PR CI and keep the complete Sim-eligible corpus in Daily CI through manual_mode: include.
  • Remove DFX cases from the main pytest scene step, while retaining them in the dedicated dep-gen, chip-swimlane, PMU, and args-dump smoke steps. The dep-gen smoke targets now cover the complete directories, including the chain cases.
  • Make dedicated DFX post-validation reuse the same platform, --case, and --manual selection as scene execution.
  • Keep the complete host-build-graph invalid-input matrix in Per-PR CI and validate that retained fatal-code case names exist.

No kernels, test parameters, runtime configuration, golden checks, or timeout thresholds are changed.

What moves to Daily

Area Moved out of the Per-PR main Sim set Representative Per-PR coverage retained
Worker lifecycle and failures Dynamic-registration boundary/error cases; most runtime fatal-code variants Registration-and-run success; one orchestration fatal and one scheduler fatal path
SPMD and dispatch stress Sync-start stress, pure-AIV duplicates, starvation, wide HBG dispatch Basic, mixed AIC+AIV, spill, edge, and early-dispatch paths
Multi-device coverage Redundant P2 collectives, P3 rank/reservation examples, simple multi-chip dispatch One-phase P2 allreduce and expert-dispatch combine paths
Dependency and graph expansion Large dependency chains, dense dummy graph, duplicate HBG execution/prepared-callable paths Boundary dependency case, ordinary/mixed HBG replay, the full invalid-input matrix, and the full TMR prepared-callable suite
Paged attention and benchmarks Scope/unroll/multi-round expansions, one HBG batch variant, HBG 500-task BGEMM Basic TMR, batch/HBG representative paths, and architecture-specific TMR BGEMM
Equivalent runtime paths A2/A3 TMR predicated dispatch, A5 TMR alternating matmul-add, A2/A3 L2 per-task runtime-env HBG predicate/alternating equivalents and the L3 runtime-env example
DFX duplication DFX cases are excluded from the main pytest scene step The same cases still run in dedicated Per-PR DFX smoke steps; Daily also includes them

Selection after this PR

Collection was run from final commit 1b2ef52c against the 275 discovered examples/tests/st items:

Platform Per-PR (--manual exclude) Daily/manual subset (--manual only)
A2/A3 Sim 66 93
A5 Sim 50 74

Shared cases keep Onboard coverage when they declare the corresponding Onboard platform. A small set of cases declares A5 Sim but not A5 Onboard (runtime-fatal variants and selected collective/group-reservation cases); those cases become A5 Daily-only and remain covered on A2/A3 Onboard where declared. The marker and testing documentation now call out this platform-fallback behavior explicitly.

Timing

Final-head run 32119518132 passed all four Sim lanes. The comparison is against pre-change run 31687370652 and separates the main scene step from the dedicated DFX tail so that the total comparison is apples-to-apples.

Aggregate across four Sim lanes Pre-change Final Change
Main Run pytest scene tests steps 22m09s 14m01s -8m08s (-37%)
Dedicated DFX pytest steps 2m12s 5m08s +2m56s
Total pytest work 24m21s 19m09s -5m12s (-21%)
Complete Sim jobs 37m08s 28m41s -8m27s (-23%)

The final main pytest lanes took 3m25s (A2/A3 Ubuntu), 4m12s (A2/A3 macOS), 3m03s (A5 Ubuntu), and 3m21s (A5 macOS), all below the 5-minute target. Complete jobs still take 6m24s–8m41s because setup and the serial dedicated DFX tail remain; further scene downselection alone is insufficient to make every whole job sub-five-minute.

Validation

  • Related scene-test and manual-selection unit tests: 85 passed.
  • Final collection: A2/A3 Sim 66 Per-PR / 93 manual; A5 Sim 50 Per-PR / 74 manual.
  • Full host-build-graph invalid-input matrix: 4 cases passed on each simulator platform.
  • Complete TMR dep-gen directories: 2 cases passed on each simulator platform with --manual include; A2/A3 exclude and only selection were also verified.
  • Local DFX validation passed for chip-swimlane, PMU, args-dump, and scope-stats on both simulator platforms; the first three also passed in the dedicated final-head CI smoke steps.
  • Pre-commit checks across all 67 changed files passed, including YAML, Ruff, Pyright, platform-literal, and whitespace checks.
  • git diff --check upstream/main...HEAD: passed.

Final-head GitHub Actions CI passed, including pre-commit, packaging, profiling flags, unit tests, all Onboard lanes, and all four Sim lanes.

@coderabbitai

coderabbitai Bot commented Aug 13, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d27801b-2ae8-48b5-b515-6faa6be92035

📥 Commits

Reviewing files that changed from the base of the PR and between 300fb6d and 0967e54.

📒 Files selected for processing (22)
  • examples/workers/l3/allreduce/test_allreduce.py
  • examples/workers/l3/domain_rank_map/test_domain_rank_map.py
  • tests/st/a2a3/host_build_graph/available_aicore_counts/test_available_aicore_counts.py
  • tests/st/a2a3/host_build_graph/graph_execution/test_graph_execution_aic_aiv.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/dep_gen/test_dep_gen_chain.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dummy_task/test_dummy_task.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dynamic_register/test_dynamic_register.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_sync_start_stress/test_spmd_sync_start_stress.py
  • tests/st/a5/host_build_graph/graph_execution/test_graph_execution.py
  • tests/st/a5/host_build_graph/graph_execution/test_graph_execution_aic_aiv.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/dep_gen/test_dep_gen_chain.py
  • tests/st/a5/tensormap_and_ringbuffer/dummy_task/test_dummy_task.py
  • tests/st/a5/tensormap_and_ringbuffer/dynamic_register/test_dynamic_register.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_sync_start_stress/test_spmd_sync_start_stress.py
  • tests/st/host_build_graph_wide_dispatch/test_host_build_graph_wide_dispatch.py
  • tests/st/runtime_fatal_codes/test_runtime_fatal_codes.py
  • tests/st/worker/collectives/all_to_all/test_all_to_all.py
  • tests/st/worker/collectives/allgather/test_allgather.py
  • tests/st/worker/collectives/allreduce/test_allreduce.py
  • tests/st/worker/collectives/broadcast/test_broadcast.py
  • tests/st/worker/collectives/group_reservation/test_group_reservation.py
  • tests/st/worker/collectives/reduce_scatter/test_reduce_scatter.py

📝 Walkthrough

Walkthrough

Selected simulator tests now use manual-execution markers for a2a3sim and a5sim. Runtime-fatal tests retain only specified per-PR simulator cases for automatic execution.

Changes

Simulator execution policy

Layer / File(s) Summary
Runtime simulator case selection
tests/st/runtime_fatal_codes/test_runtime_fatal_codes.py
The simulator test now parameterizes automatic execution over selected per-PR cases. Other cases remain available for manual simulator runs.
A2A3 and A5 specialized test markers
tests/st/a2a3/..., tests/st/a5/..., tests/st/host_build_graph_wide_dispatch/test_host_build_graph_wide_dispatch.py
Selected host-build-graph, tensor-map, ring-buffer, dynamic-register, stress, dummy-task, and wide-dispatch cases now include manual execution markers.
Collective and example test markers
tests/st/worker/collectives/*, examples/workers/l3/*
Selected collective and worker example tests now mark a2a3sim and/or a5sim for manual execution.

Estimated code review effort: 2 (Simple) | ~10 minutes

Mergeability Score: ⚪ Minimal · up to 0967e

This change only adjusts simulator test selection while retaining representative Per-PR coverage and daily execution for migrated cases; no actionable merge-blocking risk remains after normal checks and review.

Possibly related issues

Possibly related PRs

Poem

A rabbit marks the tests with care,
“Simulators wait for manual air.”
Per-PR cases run in line,
The rest await a daily sign.
Hop, hop—cleaner queues now shine!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed The description identifies PR #1823 and provides relevant CI run references for the stated simulator coverage changes.
Out of Scope Changes check ✅ Passed The file changes match the stated objective and only adjust manual execution selection for simulator tests.
Title check ✅ Passed The title clearly describes the main change: reducing per-PR simulator scene coverage.
Description check ✅ Passed The description directly explains the simulator scene downselection, retained coverage, workflow changes, and validation results.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@doraemonmj
doraemonmj force-pushed the ci/downselect-sim-scenes branch from 0cf9476 to b329975 Compare August 17, 2026 04:05
@doraemonmj doraemonmj changed the title CI: move additional simulator scenes to daily sweep CI: trim per-PR simulator scene coverage Aug 17, 2026
@ChaoWao

ChaoWao commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Review — CI: trim per-PR simulator scene coverage

Reviewed git diff 288e1803...b3299755 (merge-base to head).

Real goal vs stated goal

They match. This is pure test-selection metadata: 59 test files gain a "manual": [<sim platforms>] case key or a @pytest.mark.manual([...]) marker, and the dedicated DFX smoke steps in _st-sim-a2a3.yml / _st-sim-a5.yml gain --manual include so those files still collect. No selection mechanism changes — is_manual_for_platform and the platform-list form already exist on main (simpler_setup/scene_test.py:827), and docs/ci.md:118 already documents them. Two files needed structural edits because they parametrize from a dict rather than CASES: runtime_fatal_codes (derived list) and host_build_graph_validation (hardcoded list).

Churn: 61 files, +124/−13 = 137 lines. 59 of them are a one-line annotation; the other two are the Sim workflows. No src/, python/, or simpler_setup/ changes.

Representative-coverage claims: spot-checked, they hold

  • a2a3 HBG predicated_dispatch — both cases stay non-manual, so the TMR move keeps an equivalent.
  • a5 HBG alternating_matmul_add/default — stays non-manual (its Case1/Case2 were already manual: True, but those are platforms: ["a5"], so the a5sim equivalent survives).
  • spmd_sync_start, spmd_sync_start_edge, spmd_sync_start_mix_spill, spmd_sync_start_early_dispatch — untouched.
  • TestAllreduceOnephaseP2, examples/workers/l3/per_task_runtime_env, examples/workers/l3/ep_dispatch_combine — untouched.
  • runtime_fatal_codes keeps exactly one orchestrator path (orch_error_code=9) and one scheduler path (sched_error_code=101), and its onboard test keeps list(CASES).

Every added marker lists only *sim platforms, so the Onboard guardrail claim is accurate (one wording caveat below).


Must fix

1. test_dep_gen_chain.py: three cases leave per-PR Sim entirely — the dedicated dep_gen step targets a file, not the directory

The step is pytest .../dfx/dep_gen/test_dep_gen.py (_st-sim-a2a3.yml:114, _st-sim-a5.yml:114), so it never collects test_dep_gen_chain.py. That file's n_64_no_chain, n_200_single_overflow and n_391_two_overflow are now manual on a2a3sim/a5sim and are picked up by nothing in the Sim lanes — including n_391_two_overflow, the two-overflow dep-chain reconciliation case the file exists to guard. Only n_65_single_overflow survives, and it runs in the main step without --enable-dep-gen, so it validates nothing about deps.json.

So "continue running them in the dedicated dep-gen … smoke steps" is not true for this file.

Cheapest fix: point both dep_gen steps at the directory (.../dfx/dep_gen/) instead of the file. With --manual include that also keeps the chain file's _post_validate loop self-consistent (see #10), and it is nearly free now that the kernel-compile cost already lands in that step (see #4). Alternatively drop the chain markers, or correct the claim.

2. host_build_graph_validation: list(CASES) replaced by a hardcoded parametrize list

tests/st/host_build_graph_validation/test_host_build_graph_validation.py:80-92 now enumerates the four case names literally. A fifth entry added to CASES (line 36) would be silently untested — in per-PR and Daily. The same PR solves the same problem correctly one file over, in tests/st/runtime_fatal_codes/test_runtime_fatal_codes.py:221-227, by deriving the params from CASES. Please use that shape here.


Should fix

3. host_build_graph_validation: the loss is total, and the saving is small

That test declares platforms=["a2a3sim", "a5sim"] — there is no onboard variant — so mixed_subtask_overflow, unbound_owner_read and unbound_owner_write now have zero per-PR coverage anywhere. _build_callable is @functools.cached per platform (line 43), so keeping zero_block_num pays the whole kernel-compile cost regardless; the three moved cases only save a worker spin-up plus a no-op run each. Either state the measured per-case saving that justifies it, or keep the matrix intact.

4. The timing claim overstates the gain — the table excludes the steps that absorbed the work

Per-step durations from the two runs the description cites (gh api repos/hw-native-sys/simpler/actions/runs/<id>/jobs):

pre 31687370652 final 31993266388
Run pytest scene tests, 4 lanes 1329 s (22m09s) 744 s (12m24s)
dedicated DFX steps, 4 lanes 132 s 284 s
pytest work, total 1461 s 1028 s
whole Sim jobs, 4 lanes 2228 s (37m08s) 1614 s (26m54s)

Net pytest-work reduction is 433 s (7m13s, ~30 %), not 9m45s / 44 %. The DFX steps grew 2–5× per lane (a2a3 dep_gen 4 s→10 s, a2a3 HBG dep_gen 3 s→17 s, a5 PMU 2 s→9 s) — consistent with kernel compilation for those cases migrating out of the xdist-parallel main step into the serial -p no:xdist tail. The table does disclose the exclusion, but the headline number is computed as if the excluded steps had not grown.

The whole-job aggregate still shows a real win (−10m14s), so the conclusion survives — only the framing needs correcting. Worth noting the pre-change a2a3-ubuntu job (698 s) is an outlier: ~220 s more non-pytest time than its macOS sibling, so single-run deltas are noisy.

5. docs/ci.md:110-111 is now inaccurate

It states: "Per-PR scene-test jobs keep the default --manual exclude, so moving a case to Daily does not require a second workflow exclusion list." After this PR the per-PR DFX steps pin --manual include, so marking a case that lives under a DFX-smoke path manual does not move it to Daily — it keeps running in per-PR. That is exactly the invariant the next contributor will rely on. Please update the paragraph in this commit (per .claude/rules/doc-consistency.md §1, §4).


Consider

6. manual: True instead of a platform list

tests/st/host_build_graph_wide_dispatch/test_host_build_graph_wide_dispatch.py:85. Equivalent today (the case is sim-only), but it is the one marker the "all newly added shared-case markers are platform-scoped" guardrail does not literally cover, and it would silently exclude onboard if a2a3/a5 were ever added to platforms. ["a2a3sim", "a5sim"] costs nothing.

7. _PER_PR_SIM_CASES is unvalidated

tests/st/runtime_fatal_codes/test_runtime_fatal_codes.py:221. A typo in either name silently marks all 11 cases manual and zeroes per-PR Sim fatal-code coverage — a green-CI failure shape (cf. .claude/rules/ci-change-detection.md §7). One assert _PER_PR_SIM_CASES <= CASES.keys() closes it.

8. The residual risk is asymmetric between arches, and the guardrail table hides it

For the shared cases that declare a5sim but no a5 — runtime_fatal_codes (9 of 11), host_build_graph_validation (3 of 4), collectives all_to_all / allgather / broadcast / reduce_scatter / group_reservation — there is no onboard-a5 fallback, so on a5 they become Daily-only. On a2a3 the per-PR onboard lane still covers them. The "Onboard Per-PR" column is unchanged precisely because those cases were never in a5 onboard, so it reads as a clean bill of health when it isn't. One sentence in the description would fix that. (TestConsecutiveGroupReservation is the only class in its file, so group reservation drops to a2a3-onboard-only in per-PR.)

9. The DFX steps hardcode --manual include while their siblings honor $MANUAL_MODE

Every other pytest invocation in these reusable workflows uses --manual "$MANUAL_MODE". A caller passing the valid input manual_mode: only now gets the main step running only manual cases while the DFX steps run everything. Either derive the value or add a comment on why these are pinned.

10. Latent local footgun (pre-existing pattern, newly reachable)

The DFX test_run overrides post-validate every platform-matching case — for case in self.CASES: if st_platform in case["platforms"]: self._post_validate(...) (test_dep_gen_chain.py:142-144, test_chip_swimlane.py:109, test_pmu.py:95, and the sibling files) — replicating the platform filter but not --case or --manual. With three of four chain cases now manual, pytest .../dfx/dep_gen/ --platform a2a3sim --enable-dep-gen (default --manual exclude) asserts on output dirs for cases that never ran and fails with a misleading no output dir for case 'n_64_no_chain' created this run.

No CI lane trips it: the DFX steps pass --manual include, and no workflow passes --case (grep over .github/). Fixing #1 removes the reachable path; the --case half is pre-existing and out of scope here.


Verdict

Request changes, for #1 (three dep-chain cases silently leave per-PR Sim, contradicting the stated design) and #2 (hardcoded parametrize list can silently drop future cases). Both are small edits. Everything else is description accuracy (#4, #5, #8) or hardening.

The approach itself is sound: it reuses an existing, documented mechanism rather than inventing a second exclusion list, keeps the full corpus in Daily, correctly scopes every marker to simulator platforms, and the wall-clock win is real even after correcting the arithmetic.

Move simulator-only lifecycle, error, stress, scale, and redundant coverage
to the manual set retained by daily CI. Keep representative paths and
dedicated DFX smoke validation in per-PR CI while leaving onboard selection
unchanged.

Run dep-gen smoke targets over their complete directories and make DFX
post-validation reuse the same platform, case, and manual filters as scene
execution. Preserve the full HBG invalid-input matrix, validate retained
fatal-code case names, and document the dedicated-DFX and platform-fallback
semantics.
@doraemonmj
doraemonmj force-pushed the ci/downselect-sim-scenes branch from b329975 to 1b2ef52 Compare August 18, 2026 09:02
@doraemonmj

Copy link
Copy Markdown
Contributor Author

@ChaoWao Addressed all ten points from the review:

  1. Both TMR dep-gen smoke steps now target the complete dfx/dep_gen/ directory, so test_dep_gen_chain.py is included.
  2. Restored host-build-graph validation parametrization to derive from list(CASES).
  3. Kept the complete four-case host-build-graph invalid-input matrix in Per-PR Sim.
  4. Reworked the timing section into an apples-to-apples comparison using final-head run 32119518132: main scene steps are down 8m08s (37%), total pytest work is down 5m12s (21%), and complete Sim jobs are down 8m27s (23%).
  5. Updated the CI/testing documentation to distinguish the main Per-PR selection from dedicated DFX smoke behavior.
  6. Changed wide-dispatch from manual: True to the explicit a2a3sim/a5sim platform list.
  7. Added a subset assertion validating _PER_PR_SIM_CASES against CASES.
  8. Documented the asymmetric A5 fallback risk for cases that declare a5sim but not A5 Onboard.
  9. Dedicated DFX steps now preserve only when requested and otherwise use include, instead of unconditionally pinning include.
  10. Added a shared _matching_cases() helper and switched DFX post-validation hooks to reuse the platform, --case, and --manual filters used by scene execution; added unit coverage for all manual modes and selectors.

The final-head GitHub Actions run is green, including all four Sim lanes and all Onboard lanes. The PR description has also been updated with the final selection counts, corrected timing, and validation results.

@ChaoWao
ChaoWao merged commit 5bcceb0 into hw-native-sys:main Aug 18, 2026
19 checks passed
@ChaoWao

ChaoWao commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Re-review — force-push b3299755 → 1b2ef52c

Rebased onto a newer main (merge-base be25a3b6) and revised in response to the previous pass. Now 67 files, +240/−112 = 352 lines, of which one is a mechanism change (simpler_setup/scene_test.py, 47 lines) that was not in the previous head. All 19 checks pass.

  Core             1 files  +   26  -   21  =47    simpler_setup/scene_test.py
  Test/Ex         61 files  +  178  -   69  =247
  Docs             3 files  +   23  -   11  =34    docs/ci.md, docs/testing.md, .claude/skills/testing/SKILL.md
  Uncategorized    2 files  +   13  -   11  =24    the two _st-sim-*.yml workflows
  TOTAL           67 files  +  240  -  112  =352

Every previous finding: resolved

Previous finding Resolution — verified
Must #1 — three dep-chain cases left per-PR Sim entirely because the step targeted a file Both TMR dep_gen steps now target .../dfx/dep_gen/, so test_dep_gen_chain.py is collected and its three overflow cases are back in per-PR Sim.
Must #2 — host_build_graph_validation hardcoded parametrize list Reverted entirely; the file is no longer in the diff, so the full four-case invalid-input matrix stays in per-PR on both simulator platforms.
Should #3 — total loss of three validation cases with no onboard fallback Moot, same revert.
Should #4 — timing table excluded the steps that absorbed the work Table now separates main / DFX / total / whole-job. I recomputed all eight cells from the Actions API and every one matches exactly: main 1329 s→841 s (22m09s→14m01s), DFX 132 s→308 s (2m12s→5m08s), pytest work 1461 s→1149 s (24m21s→19m09s, −21 %), whole jobs 2228 s→1721 s (37m08s→28m41s, −23 %). The per-lane main steps (205/252/183/201 s) also match the quoted 3m25s / 4m12s / 3m03s / 3m21s.
Should #5 — docs/ci.md:110-111 became inaccurate Rewritten, and it now states the exact rule the code implements including the only passthrough. docs/testing.md and the testing-skill table updated to match.
Consider #6 — manual: True instead of a platform list Now ["a2a3sim", "a5sim"] in host_build_graph_wide_dispatch. Across the whole diff all 74 added markers are sim-scoped; no bare True remains.
Consider #7 — _PER_PR_SIM_CASES unvalidated assert _PER_PR_SIM_CASES <= CASES.keys() at module scope, with the offending names in the message.
Consider #8 — asymmetric A5 residual risk hidden by the guardrail table Called out in the body and, better, encoded in both docs: onboard coverage survives only when the case declares that onboard platform.
Consider #9 — DFX steps pinned --manual include while their siblings honour $MANUAL_MODE Now `--manual "${{ inputs.manual_mode == 'only' && 'only'
Consider #10 — post-validate loop ignored --case / --manual Fixed properly, and generalised past this PR's own scope: the filter is extracted as SceneTestCase._matching_cases() and all ten validators route through it, including test_scope_stats.py, which this PR does not otherwise touch. Grepping the tree, the only remaining for case in ...CASES loops are the two authoritative ones inside scene_test.py.

Verified independently as well: the manual-selection unit tests pass locally (32 passed), and all four chip_swimlane/*.py files sit inside the directory the dedicated step targets on both architectures — so test_sync_start_drain_phases and test_sync_start_early_local_owner keep full per-PR coverage and merely moved out of the parallel sweep. That retires the early-dispatch concern from the first pass entirely.

The net saving fell from the ~7m13s the previous head would have delivered to 5m12s, because coverage was restored in three places. That is the right direction for the trade.

On the refactor

test_run now computes matched first and skips before build_callable, then hands the same list to run_class_cases. Behaviour-preserving for the selection itself, with two side effects that are both improvements: a class filtered out by --case no longer pays a kernel compile, and because pytest.skip() raises, a subclass validator placed after super().test_run(...) can no longer run against a class that never executed. _matching_cases also tightened case.get("platforms", []) to case["platforms"], matching what test_run always did.


Remaining — all Consider, nothing blocking

  1. The A2/A3 host_build_graph dep_gen step still names test_dep_gen.py rather than its directory. No gap today (that directory holds exactly one file), but a filename target silently missing siblings is the precise defect this revision fixed for TMR, and the summary says the dep-gen targets "now cover the complete directories" while one still does not. One-word change.

  2. test_dep_gen_chain.py is now the only half-marked file. n_65_single_overflow stays non-manual, so it runs twice per PR: plain in the main sweep, and again with --enable-dep-gen in the DFX step. If the dep-gen-off run is the point — a different orchestration build, and the golden still checks the barrier — a comment saying so would settle it; otherwise mark it and make the file uniform.

  3. TestChipSwimlaneMixed._validate_dump_func_ids still hardcodes TestChipSwimlaneMixed_default. It is the one validator in these files that does not derive its label from _matching_cases. Safe today (single-case class, and the class only runs when that case matched), but a second case would make it silently validate the wrong output directory.

  4. The skip-before-build_callable ordering is load-bearing and unrecorded. One present-tense line at the skip — no case has executed yet, so a subclass validator after super().test_run() cannot see cases that did not run — would stop a future edit from quietly moving it back down.

ℹ️ pto-isa pin: pinned to f51c92f610827daad0ddfb383072e03d514b4ae9 (moved with the rebase). No pto-isa header references changed — advisory only.

Verdict

Approve. Both must-fixes and all three should-fixes from the previous pass are resolved, the fix for the post-validate mismatch went further than asked and removed the pattern repo-wide, the timing numbers are now exactly reproducible from the Actions API, and the docs state the real rule rather than the old one. The four remaining items are cosmetic or future-proofing.

ChaoWao added a commit to ChaoWao/simpler-fork that referenced this pull request Aug 18, 2026
…view

`network1` / `network2` / `network3`, but only the span vocabulary moved. The
rest of the tree still called L4 a pod, so one level had two names. This
converts the remainder and fixes the three findings from hw-native-sys#1877's review.

`pod` meant three different things, so each occurrence was judged rather than
swept:

  * `POD` — Plain Old Data, the C++ term codestyle.md rule 8 is built on.
    114 occurrences, untouched.
  * `SceneTestLevel.POD = 4` — the L4 scene level, now `NETWORK1`, together with
    its `@scene_level()` call sites.
  * lowercase `pod` — the level word, in identifiers, paths, CI job names and
    prose. Converted.

Renamed with history: the three `.github/actions/pod-*` composite actions,
`_st-pod.yml`, and `tests/st/.../l4_pod/` with its test file. Job names follow
(`st-pod-onboard-a2a3` -> `st-network1-onboard-a2a3`), which is safe because the
active ruleset enforces deletion, non-fast-forward, pull_request and linear
history and carries no required status checks — so no PR waits on a check that
stops reporting.

Fixture names move together with every signature that requests them
(`st_pod_peer` -> `st_network1_peer` and siblings); a missed one is a
fixture-not-found at collection, so all five L4 tests were collected to check.

`POD_*` are 28 variables read from a `.env` on each runner machine, and
`_st-network1.yml` accepts only keys matching a prefix. Renaming repo-side while
those files still say `POD_` would make the filter drop every key — silently,
because it `continue`s. Those files are not in this repository.

So the reader now accepts both spellings and exports every key as `NETWORK1_*`.
The rest of the job and the tests see exactly one name, and a machine can be
converted whenever, in either order. `POD_ENV_FILE` still works for the same
reason. Drop the `POD_` branch once no `.env` uses it.

**`set_level_prefix` could dangle a live name pointer.** `SpanScope` keeps the
`const char *` it was handed and dereferences it in its destructor, and rebinding
reassigned the strings it points into. A process constructing Workers at two
levels also relabelled the first Worker's spans mid-run. The first non-empty word
now wins and later ones are refused; `level_prefix()` reports what is actually
bound, and Python compares the two and warns, because one process has one
vocabulary and that is worth saying rather than leaving in a trace.

**docs/dfx/host-trace.md documented only `host.*`** and still claimed names do
not encode the emitting level — pointing at hw-native-sys#1793 for the fix that hw-native-sys#1877 was.
The table now uses `<level>.` and names the four possible words.

**test_strace_timing.py lost its retired-name coverage.** The fixture was called
`old` because it stood for an older log; hw-native-sys#1877's rename converted its contents to
the current names, leaving `_RETIRED_WORDS` — added by that same PR to read
archived logs — with no test at all. Restored as its own case, plus one covering
`span_family` across every level word, `ext.`, and an unknown leader.

- `pytest tests/ut/py -m "not requires_hardware"` — 1520 passed, 0 failed.
- `ctest -LE requires_hardware --timeout 300` — 101/101.
- All 51 local `uses:` references in `.github/` resolve, checked against the
  working tree; a stale one is this change's only way to redden CI.
- All five L4 tests collect, which is what proves the fixture renames.
- End to end on a2a3sim: a real trace still splits into 13 chip and 9 host spans.
- `pre-commit` clean except clang-tidy, whose hook venv cannot import simpler and
  fails identically on untouched files. The longer variable names pushed one
  `pytest.fail` message in conftest.py past the 120-column limit; the message is
  now built from a local rather than nested inside the f-string.

`docs/hierarchical-level-runtime.md` is the one place that maps a level word onto
a physical entity, so it is where `network1` is explained as the layer commonly
deployed as a pod. Nothing else in the tree repeats the mapping.

Rebasing onto hw-native-sys#1823 conflicted in three docs: it rewrote the `manual` marker
rows that this change had only reworded, in `.claude/skills/testing/SKILL.md`,
`docs/testing.md` and `docs/ci.md`. Both sides are kept — the expanded DFX-step
wording with the level word applied. That PR also added prose calling the level
POD, which this converts too.
ChaoWao added a commit to ChaoWao/simpler-fork that referenced this pull request Aug 18, 2026
…view

`network1` / `network2` / `network3`, but only the span vocabulary moved. The
rest of the tree still called L4 a pod, so one level had two names. This
converts the remainder and fixes the three findings from hw-native-sys#1877's review.

`pod` meant three different things, so each occurrence was judged rather than
swept:

  * `POD` — Plain Old Data, the C++ term codestyle.md rule 8 is built on.
    114 occurrences, untouched.
  * `SceneTestLevel.POD = 4` — the L4 scene level, now `NETWORK1`, together with
    its `@scene_level()` call sites.
  * lowercase `pod` — the level word, in identifiers, paths, CI job names and
    prose. Converted.

Renamed with history: the three `.github/actions/pod-*` composite actions,
`_st-pod.yml`, and `tests/st/.../l4_pod/` with its test file. Job names follow
(`st-pod-onboard-a2a3` -> `st-network1-onboard-a2a3`), which is safe because the
active ruleset enforces deletion, non-fast-forward, pull_request and linear
history and carries no required status checks — so no PR waits on a check that
stops reporting.

Fixture names move together with every signature that requests them
(`st_pod_peer` -> `st_network1_peer` and siblings); a missed one is a
fixture-not-found at collection, so all five L4 tests were collected to check.

`POD_*` are 28 variables read from a `.env` on each runner machine, and
`_st-network1.yml` accepts only keys matching a prefix. Renaming repo-side while
those files still say `POD_` would make the filter drop every key — silently,
because it `continue`s. Those files are not in this repository.

So the reader now accepts both spellings and exports every key as `NETWORK1_*`.
The rest of the job and the tests see exactly one name, and a machine can be
converted whenever, in either order. `POD_ENV_FILE` still works for the same
reason. Drop the `POD_` branch once no `.env` uses it.

**`set_level_prefix` could dangle a live name pointer.** `SpanScope` keeps the
`const char *` it was handed and dereferences it in its destructor, and rebinding
reassigned the strings it points into. A process constructing Workers at two
levels also relabelled the first Worker's spans mid-run. The first non-empty word
now wins and later ones are refused; `level_prefix()` reports what is actually
bound, and Python compares the two and warns, because one process has one
vocabulary and that is worth saying rather than leaving in a trace.

**docs/dfx/host-trace.md documented only `host.*`** and still claimed names do
not encode the emitting level — pointing at hw-native-sys#1793 for the fix that hw-native-sys#1877 was.
The table now uses `<level>.` and names the four possible words.

**test_strace_timing.py lost its retired-name coverage.** The fixture was called
`old` because it stood for an older log; hw-native-sys#1877's rename converted its contents to
the current names, leaving `_RETIRED_WORDS` — added by that same PR to read
archived logs — with no test at all. Restored as its own case, plus one covering
`span_family` across every level word, `ext.`, and an unknown leader.

- `pytest tests/ut/py -m "not requires_hardware"` — 1520 passed, 0 failed.
- `ctest -LE requires_hardware --timeout 300` — 101/101.
- All 51 local `uses:` references in `.github/` resolve, checked against the
  working tree; a stale one is this change's only way to redden CI.
- All five L4 tests collect, which is what proves the fixture renames.
- End to end on a2a3sim: a real trace still splits into 13 chip and 9 host spans.
- `pre-commit` clean except clang-tidy, whose hook venv cannot import simpler and
  fails identically on untouched files. The longer variable names pushed one
  `pytest.fail` message in conftest.py past the 120-column limit; the message is
  now built from a local rather than nested inside the f-string.

`docs/hierarchical-level-runtime.md` is the one place that maps a level word onto
a physical entity, so it is where `network1` is explained as the layer commonly
deployed as a pod. Nothing else in the tree repeats the mapping.

Three findings from the hw-native-sys#1880 review are folded in. A proxy URL may carry
`user:password@`, and both the local reachability check and the peer-side one in
network1-stage wrote the whole value to the job log; the parse that already
stripped the credential is now a `proxy_hostport` helper the error message shares,
so a failure still names the address without the secret. The a2a3 reproduction
commands in three skills carried `-m "not sdma"` but not `--exclude-level 4`,
which CI pairs it with, so a single-machine reproduction would collect the
level-4 tests that need the two-machine job. One `POD` survived in an
_st-network1.yml comment describing that job's test result.

Rebasing onto hw-native-sys#1823 conflicted in three docs: it rewrote the `manual` marker
rows that this change had only reworded, in `.claude/skills/testing/SKILL.md`,
`docs/testing.md` and `docs/ci.md`. Both sides are kept — the expanded DFX-step
wording with the level word applied. That PR also added prose calling the level
POD, which this converts too.
ChaoWao added a commit to ChaoWao/simpler-fork that referenced this pull request Aug 18, 2026
…view

`network1` / `network2` / `network3`, but only the span vocabulary moved. The
rest of the tree still called L4 a pod, so one level had two names. This
converts the remainder and fixes the three findings from hw-native-sys#1877's review.

`pod` meant three different things, so each occurrence was judged rather than
swept:

  * `POD` — Plain Old Data, the C++ term codestyle.md rule 8 is built on.
    114 occurrences, untouched.
  * `SceneTestLevel.POD = 4` — the L4 scene level, now `NETWORK1`, together with
    its `@scene_level()` call sites.
  * lowercase `pod` — the level word, in identifiers, paths, CI job names and
    prose. Converted.

Renamed with history: the three `.github/actions/pod-*` composite actions,
`_st-pod.yml`, and `tests/st/.../l4_pod/` with its test file. Job names follow
(`st-pod-onboard-a2a3` -> `st-network1-onboard-a2a3`), which is safe because the
active ruleset enforces deletion, non-fast-forward, pull_request and linear
history and carries no required status checks — so no PR waits on a check that
stops reporting.

Fixture names move together with every signature that requests them
(`st_pod_peer` -> `st_network1_peer` and siblings), as does the type one of them
returns (`PodPeer` -> `Network1Peer`); a missed fixture is a fixture-not-found at
collection, so all five L4 tests were collected to check.

`POD_*` are 28 variables read from a `.env` on each runner machine, and
`_st-network1.yml` accepts only keys matching a prefix. Renaming repo-side while
those files still say `POD_` would make the filter drop every key — silently,
because it `continue`s. Those files are not in this repository.

So the reader now accepts both spellings and exports every key as `NETWORK1_*`.
The rest of the job and the tests see exactly one name, and a machine can be
converted whenever, in either order. `POD_ENV_FILE` still works for the same
reason. Drop the `POD_` branch once no `.env` uses it.

The `a2a3pod` runner label is machine-side for the same reason and gets no such
escape: a job matches every label in its list, so it cannot accept either
spelling. It stays until those machines are relabelled, and the workflows and
docs/ci.md say why it reads differently from everything around it.

**`set_level_prefix` could dangle a live name pointer.** `SpanScope` keeps the
`const char *` it was handed and dereferences it in its destructor, and rebinding
reassigned the strings it points into. A process constructing Workers at two
levels also relabelled the first Worker's spans mid-run. The first non-empty word
now wins and later ones are refused; `level_prefix()` reports what is actually
bound, and Python compares the two and warns, because one process has one
vocabulary and that is worth saying rather than leaving in a trace.

**docs/dfx/host-trace.md documented only `host.*`** and still claimed names do
not encode the emitting level — pointing at hw-native-sys#1793 for the fix that hw-native-sys#1877 was.
The table now uses `<level>.` and names the four possible words.

**test_strace_timing.py lost its retired-name coverage.** The fixture was called
`old` because it stood for an older log; hw-native-sys#1877's rename converted its contents to
the current names, leaving `_RETIRED_WORDS` — added by that same PR to read
archived logs — with no test at all. Restored as its own case, plus one covering
`span_family` across every level word, `ext.`, and an unknown leader.

- `pytest tests/ut/py -m "not requires_hardware"` — 1581 passed, 0 failed.
- `ctest -LE requires_hardware --timeout 300` — 101/101.
- All 55 local `uses:` references in `.github/` resolve, checked against the
  working tree; a stale one is this change's only way to redden CI.
- All five L4 tests collect, which is what proves the fixture renames.
- End to end on a2a3sim: a real trace still splits into 13 chip and 9 host spans.
- `pre-commit` clean except clang-tidy, whose hook venv cannot import simpler and
  fails identically on untouched files. The longer variable names pushed one
  `pytest.fail` message in conftest.py past the 120-column limit; the message is
  now built from a local rather than nested inside the f-string.

`docs/hierarchical-level-runtime.md` is the one place that maps a level word onto
a physical entity, so it is where `network1` is explained as the layer commonly
deployed as a pod. Nothing else in the tree repeats the mapping.

Three findings from the hw-native-sys#1880 review are folded in. A proxy URL may carry
`user:password@`, and both the local reachability check and the peer-side one in
network1-stage wrote the whole value to the job log; the parse that already
stripped the credential is now a `proxy_hostport` helper the error message shares,
so a failure still names the address without the secret. The a2a3 reproduction
commands in three skills carried `-m "not sdma"` but not `--exclude-level 4`,
which CI pairs it with, so a single-machine reproduction would collect the
level-4 tests that need the two-machine job. One `POD` survived in an
_st-network1.yml comment describing that job's test result.

`.claude/skills/testing/SKILL.md`, `docs/testing.md` and `docs/ci.md` carry both
hw-native-sys#1823's expanded `manual`-marker and pre-commit-build wording and the level word,
which this change also applies to the prose that PR added calling the level POD.
ChaoWao added a commit that referenced this pull request Aug 18, 2026
`network1` / `network2` / `network3`, but only the span vocabulary moved. The
rest of the tree still called L4 a pod, so one level had two names. This
converts the remainder and fixes the three findings from #1877's review.

`pod` meant three different things, so each occurrence was judged rather than
swept:

  * `POD` — Plain Old Data, the C++ term codestyle.md rule 8 is built on.
    114 occurrences, untouched.
  * `SceneTestLevel.POD = 4` — the L4 scene level, now `NETWORK1`, together with
    its `@scene_level()` call sites.
  * lowercase `pod` — the level word, in identifiers, paths, CI job names and
    prose. Converted.

Renamed with history: the three `.github/actions/pod-*` composite actions,
`_st-pod.yml`, and `tests/st/.../l4_pod/` with its test file. Job names follow
(`st-pod-onboard-a2a3` -> `st-network1-onboard-a2a3`), which is safe because the
active ruleset enforces deletion, non-fast-forward, pull_request and linear
history and carries no required status checks — so no PR waits on a check that
stops reporting.

Fixture names move together with every signature that requests them
(`st_pod_peer` -> `st_network1_peer` and siblings), as does the type one of them
returns (`PodPeer` -> `Network1Peer`); a missed fixture is a fixture-not-found at
collection, so all five L4 tests were collected to check.

`POD_*` are 28 variables read from a `.env` on each runner machine, and
`_st-network1.yml` accepts only keys matching a prefix. Renaming repo-side while
those files still say `POD_` would make the filter drop every key — silently,
because it `continue`s. Those files are not in this repository.

So the reader now accepts both spellings and exports every key as `NETWORK1_*`.
The rest of the job and the tests see exactly one name, and a machine can be
converted whenever, in either order. `POD_ENV_FILE` still works for the same
reason. Drop the `POD_` branch once no `.env` uses it.

The `a2a3pod` runner label is machine-side for the same reason and gets no such
escape: a job matches every label in its list, so it cannot accept either
spelling. It stays until those machines are relabelled, and the workflows and
docs/ci.md say why it reads differently from everything around it.

**`set_level_prefix` could dangle a live name pointer.** `SpanScope` keeps the
`const char *` it was handed and dereferences it in its destructor, and rebinding
reassigned the strings it points into. A process constructing Workers at two
levels also relabelled the first Worker's spans mid-run. The first non-empty word
now wins and later ones are refused; `level_prefix()` reports what is actually
bound, and Python compares the two and warns, because one process has one
vocabulary and that is worth saying rather than leaving in a trace.

**docs/dfx/host-trace.md documented only `host.*`** and still claimed names do
not encode the emitting level — pointing at #1793 for the fix that #1877 was.
The table now uses `<level>.` and names the four possible words.

**test_strace_timing.py lost its retired-name coverage.** The fixture was called
`old` because it stood for an older log; #1877's rename converted its contents to
the current names, leaving `_RETIRED_WORDS` — added by that same PR to read
archived logs — with no test at all. Restored as its own case, plus one covering
`span_family` across every level word, `ext.`, and an unknown leader.

- `pytest tests/ut/py -m "not requires_hardware"` — 1581 passed, 0 failed.
- `ctest -LE requires_hardware --timeout 300` — 101/101.
- All 55 local `uses:` references in `.github/` resolve, checked against the
  working tree; a stale one is this change's only way to redden CI.
- All five L4 tests collect, which is what proves the fixture renames.
- End to end on a2a3sim: a real trace still splits into 13 chip and 9 host spans.
- `pre-commit` clean except clang-tidy, whose hook venv cannot import simpler and
  fails identically on untouched files. The longer variable names pushed one
  `pytest.fail` message in conftest.py past the 120-column limit; the message is
  now built from a local rather than nested inside the f-string.

`docs/hierarchical-level-runtime.md` is the one place that maps a level word onto
a physical entity, so it is where `network1` is explained as the layer commonly
deployed as a pod. Nothing else in the tree repeats the mapping.

Three findings from the #1880 review are folded in. A proxy URL may carry
`user:password@`, and both the local reachability check and the peer-side one in
network1-stage wrote the whole value to the job log; the parse that already
stripped the credential is now a `proxy_hostport` helper the error message shares,
so a failure still names the address without the secret. The a2a3 reproduction
commands in three skills carried `-m "not sdma"` but not `--exclude-level 4`,
which CI pairs it with, so a single-machine reproduction would collect the
level-4 tests that need the two-machine job. One `POD` survived in an
_st-network1.yml comment describing that job's test result.

`.claude/skills/testing/SKILL.md`, `docs/testing.md` and `docs/ci.md` carry both
#1823's expanded `manual`-marker and pre-commit-build wording and the level word,
which this change also applies to the prose that PR added calling the level POD.
@doraemonmj
doraemonmj deleted the ci/downselect-sim-scenes branch August 19, 2026 02:05
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