# Tier 1: the CPU battery.  Runs on any machine with Python and the declared
# dependencies; this is what a GitHub-hosted runner executes on every push and
# pull request.
#
# Selector: -m "not gpu and not bigcard and not assets"
#
# The list is files, not a bare "tests/", so that adding a test file is a
# deliberate act of deciding which tier it belongs to.  A new file that nobody
# added here is not silently absorbed into the tier that runs everywhere.
#
# Every file below also carries members of other tiers; the marker selector is
# what separates them, and tests/conftest.py applies the gpu and assets markers
# by AST so an unmarked test cannot leak into this tier by omission.

# what the distribution declares, against what the package actually is
tests/test_packaging_declaration.py

# the engine range and the two surfaces that must name it: the derived
# dependency specifier, the installed-engine drift check `doctor` makes at
# install time, and the door's refusal.  Real files and real SHA-256, no
# card, no network -- and it belongs in the tier that runs on every push
# because the defect it answers (pip resolving an engine the seam pin
# refuses) is a defect of the DECLARATION, which is what a push changes
tests/test_engine_pin.py

# the checkout produces one artefact rather than one per builder: line endings
# are pinned, so the LICENSE and NOTICE bytes inside dist-info/licenses/ do not
# depend on the cloner's core.autocrlf
tests/test_checkout_reproducibility.py

# the three front doors: argument surfaces, executable resolution ladders,
# product coverage, and every named refusal
tests/test_init_door.py
tests/test_render_door.py

# the forecast door: argument grammar, the refusal inventory, and the device
# admission decision.  The decision is exercised at free-memory values no
# card here has, which is the only way to test the refusal that fires when a
# card is too small; the door's one point of device contact is substituted
tests/test_forecast_door.py

# the proof guards: pin structure, authority pin shapes, and the ordering law
# that the source pins are verified before the checkout guard reads the
# manifest module's constants
tests/test_proof_guard_pins.py
tests/test_proof_guard_ordering.py

# the multi-GPU partition executor's pure logic (the transport and halo
# reasoning that does not need a device to be wrong)
tests/test_partition_executor_v841.py

# the source manifests that name this tree's own files: every declared row is
# a file that is here, and the recorded manifest refuses rather than hashing a
# hole
tests/test_source_manifests.py

# mesh validation against a synthetic defect-free variable-resolution sphere:
# the arc-length tolerance has to admit binary32 storage noise at fine spacing
# and still refuse metre-scale corruption at coarse spacing.  Builds its own
# mesh, so it belongs in the tier that needs no assets
tests/test_mesh_validation.py

# the sizing gates: a resolution spec the BUILD refuses has to be refused by
# SIZING first.  Its arithmetic members run anywhere; the members that drive
# rw_mpas_mesh skip by name when no generator is staged, which is the state a
# hosted runner is in
tests/test_mesh_spec_gates.py

# the full-physics harness's non-device surface: constructor audits, contract
# pins, surface classification.  Its four asset-touching members are marked
# and land in tier 2.
tests/test_cuda_v841_full_physics_x4.py

# the big-card preflight itself, which in this tier only proves that it skips
# with a number rather than passing vacuously
tests/test_device_capacity.py

# the observational referee: manifest strictness, the metric arithmetic against
# hand-computed values, case-block bootstrap reproducibility, canonical-bundle
# byte determinism, the fail-closed treatment receipt, and the synthetic
# end-to-end suite run twice for identical digests.  It needs numpy and nothing
# else -- no card, no assets, no network -- and it was in no tier list at all
# until the referee's first real run, which meant the machinery that decides
# whether the physics is right was not gated on any push.
tests/test_obs_referee.py
# the history stream's refl10cm/q2 publication: the writer surface (dims,
# units, bitwise q2, the q2_products_allowed flip), the diagflag pass-through
# by signature, and the model bundle's composite-reflectivity and dewpoint
# derivations against the engine's own formula.  Dropping either field from
# the default stream makes divergence 3's declared referee unrunnable, which
# is exactly what the first real run reported.
tests/test_history_refl_q2.py

# ---------------------------------------------------------------------------
# THE 2026-08-29 TIER CENSUS.  Everything below this line was on NO tier list.
#
# Measured in this tree at dd6183d, with GPUWM_HEX_NO_LOCAL_GPU=1 and the
# tier-1 selector -m "not gpu and not bigcard and not assets":
#
#     56 test files on disk, 16 named by a tier list, 40 named by none
#     867 tests collect under the tier-1 selector
#       238 of them are in this list
#       629 of them (73%) were in no tier and ran in NO CI at all
#     the 40 unlisted files, run together: 618 passed, 11 skipped,
#     5 deselected, in 73.91 s
#
# Every one of the forty collects and passes on a machine with no card, no
# assets and no network -- so none of them was device-only, none of them was
# deliberately deferred, and none of them was hard to run.  They were simply
# never added, one file at a time, and the file that says so already exists
# in this list: tests/test_obs_referee.py carries the note "it was in no tier
# list at all until the referee's first real run, which meant the machinery
# that decides whether the physics is right was not gated on any push."  That
# happened at least forty more times.
#
# The header of this file states the intent -- "a new file that nobody added
# here is not silently absorbed" -- and nothing enforced it.
# tests/test_tier_membership.py now does: every tests/test_*.py on disk must
# be named by exactly one tier list, so the forty-first cannot arrive quietly.
#
# Grouped by subsystem rather than one comment per file, because the argument
# for the coverage is the same within each group and forty separate one-line
# reasons would say less than these seven.
# ---------------------------------------------------------------------------

# The admission decisions: what the port REFUSES and why.  Every one of these
# is a refusal that has to name its breakage (the project's refusal law), and
# a refusal that stops firing is invisible from the outside -- the run simply
# proceeds and produces a number.  Pure argument checking, no device.
tests/test_admission_strings.py
tests/test_arch_admission.py
tests/test_cell_coordination_admission.py
tests/test_convection_admission.py
tests/test_device_admission.py
tests/test_domain_size_agreement.py
tests/test_dt_admission.py
tests/test_dual_edge_admission.py
tests/test_native_free_init_admission_305.py
tests/test_partition_device_admission.py
tests/test_regional_mesh_admission.py

# The device-memory ledger and the tools that read it.  The capacity numbers
# decide whether a mesh is admitted to a card at all; the ledger has already
# been superseded twice, and an arithmetic change here silently moves the size
# of the largest forecast this port will accept.  The arithmetic runs on CPU.
tests/test_capacity_copy_elisions.py
tests/test_device_memory_capacity_tools.py
tests/test_device_memory_ledger_probes.py

# The CUDA surfaces that are decidable without a CUDA device: kernel source
# structure, the NVRTC reciprocal rewrite, the libm identity, the vectorised
# vertical arithmetic against its scalar sibling, and the projection probe.
# These are the parts of the device path a hosted runner CAN check, and not
# checking them meant no push examined the kernel sources at all.
tests/test_cuda_physics_tier_park_v841.py
tests/test_cuda_regional_kernels.py
tests/test_element_parallel_kernels.py
tests/test_kernel_element_ab.py
tests/test_fullstep_projection_probe.py
# The step's host path: the admission memo, the untimed recovery launch, the
# solve-region check unit and the three call sites that read once.  The
# device halves import cupy inside the test and are marked gpu by conftest.
tests/test_solve_region_checks.py
tests/test_libm_identity.py
tests/test_nvrtc_reciprocal_rewrite.py
tests/test_vertical_artifact_met_state.py
tests/test_vertical_vectorized_equivalence.py

# The regional/nesting seam: anchoring, mesh binding, the physics seam, the
# lateral boundary reader, the refined-region field and the ring/shell ratio.
# This is the newest subsystem in the port and the one under most edit, which
# is precisely the wrong thing to leave off every push.  The members that need
# the native-culled reference set skip by name (measured: 11 skips across the
# whole forty, each printing its own reason under -rs).
tests/test_lbc.py
tests/test_nest_ratio_ring_shell.py
tests/test_refined_region_field.py
tests/test_regional_forecast_anchor.py
tests/test_regional_mesh_binding.py
tests/test_regional_physics_seam.py
tests/test_regional_runtime.py
# The point-mesh door (0.3.0): the HRRR intermediate writer, the point plan
# and its cull, the runtime mesh-row file and the finest-edge class band.
# They arrived with the door and were named by no tier list, which is the
# forty-first file tests/test_tier_membership.py exists to catch.
tests/test_hrrr_intermediate.py
tests/test_mesh_point.py
tests/test_mesh_rows.py
tests/test_regional_class_band.py

# Time stepping and physics cadence: the local timestep and the PBL call
# interval.  A cadence that drifts changes every forecast this port produces
# and changes no interface, so nothing but a test can see it.
tests/test_local_timestep.py
tests/test_pbl_cadence.py

# The cycling cascade: the loop that carries one forecast into the next.
tests/test_cycle_cascade.py

# The swath subsystem end to end -- registry, plan, geometry, detection,
# composite spec, the door and the real-forecast surface.  Seven files and
# 139 tests for the product's newest user-facing feature, none of which any
# push ran.
tests/test_swath_composite_spec.py
tests/test_swath_detect.py
tests/test_swath_door.py
tests/test_swath_geometry.py
tests/test_swath_plan.py
tests/test_swath_real_forecast.py
tests/test_swath_registry.py

# Distribution and tree hygiene: the wheel a user actually reaches, and the
# conflict-marker scan.  Both are about what leaves this machine, which makes
# a push exactly the event they should run on.
tests/test_no_conflict_markers.py
tests/test_wheel_reach.py

# The tier census itself: every test file on disk is named by exactly one tier
# list.  It is what stops this block having to be written again.
tests/test_tier_membership.py

# The four writers that land on a tracked file. No card, no assets, no
# network: it reads three modules with ast and round-trips three JSON
# files through tmp_path. `* text=auto eol=lf` normalizes the blob, so a
# CRLF worktree is invisible to every blob-reading check and only a
# leg that RUNS this can see it.
tests/test_tracked_file_writers_keep_lf.py

# The mp=28 seeded-pair door and its scalar rows, added when the hex-mod lane
# folded into the integration tip these files rode in on. No card, no assets,
# no network: the pair door's argument surface and refusals, the gallery
# caption logic, the backend row builder, and the species-row extras hook.
tests/test_pair_door.py
tests/test_plot_pair_gallery.py
# The point-source placement instrument: the table arithmetic pinned to the
# proven 3.75 km table's own epoch, and the census and upwind placement run
# over a synthetic leg with one supercooled strip. No card, no assets.
tests/test_point_source_placement.py
tests/test_backend_row_builder.py
tests/test_species_row_extended.py
