open-standards/scripts/check-orphan-sources.py
Transaction Science 130123f648
All checks were successful
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 59s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 33s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 3m15s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 10m2s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 3m49s
standards workspaces build + test / mesh-rs (mesh/mesh-rs, -p mesh-engine-gguf -p mesh-openai --features mesh-engine-gguf/gguf,mesh-openai/server, mesh-rs, linux-arm64) (pull_request) Successful in 3m3s
standards workspaces build + test / jouleclaw-rs (-nodebug, jouleclaw/jouleclaw-rs, -p jouleclaw-energy --features rapl,nvml, jouleclaw-rs, linux-arm64, -C target-feature=+fp16) (pull_request) Successful in 7m35s
jouleclaw-omni: declare 23 modules that were compiled by nothing
Twenty-five source files in this crate were named by no `mod` line, so they
were not in the build at all: ~19,000 lines that nothing type-checked, tested
or linted. `scripts/check-orphan-sources.py` pinned them as a baseline so the
count could only fall, and this is that fall: 25 -> 1.

Declaring them costs almost nothing, which is the surprise. Twenty-three
compile clean, and the two that do not are blocked by facts outside the code:

  video_decode.rs wants `ffmpeg_next`, which is not a dependency
  (`extern crate ffmpeg_next` -> E0463). That is a system library and a
  licensing choice, so it stays undeclared, and the baseline now holds it
  alone, with the reason written beside it.

  fusion.rs has every one of its `use` lines behind
  `#[cfg(feature = "metal")]` while the items that need those types do not, so
  a default build loses the imports and keeps the code: 31 unresolved types.
  It only ever compiled with that feature on. The module is now gated the same
  way, as `gpu_ops` and the sana_wm draft already are.

sana_wm_gpu_dispatchers_draft.rs is gated likewise: it imports
`crate::hal::metal`, which is `#[cfg(feature = "metal")]`.

Measured on the build host, with --keep-going so an early error cannot hide
what is behind it: `cargo check` 0 errors, `cargo clippy --all-targets` 0
errors, 44 tests pass, the whole jouleclaw workspace still checks, and the
orphan guard passes on the new baseline, its planted-orphan self-test included.

⚠️ Separately, and not from this change: `--features metal` does not compile on
main at all -- 3063 errors, concentrated in files that were already declared
(hunyuan3d.rs 300, audiogen.rs 269, trellis.rs 213). Measured on origin/main
before this change, so it is pre-existing. No CI job builds that feature.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-18 07:19:24 -04:00

155 lines
6.3 KiB
Python
Executable file

#!/usr/bin/env python3
"""No library source file is unreachable from its crate root.
An orphan `.rs` file — one no `mod` declaration, `#[path]` attribute or
`include!` ever names — is not merely untested. It is **never compiled**, so it
is invisible to every check in this repository at once: not `cargo check`, not
`cargo test`, not clippy, not the conformance suites. It cannot fail, because
nothing ever asks it anything.
That makes it the strongest member of a family this repo keeps finding: a
feature-gated test run without `--features`, a platform-gated meter on a
single-platform runner, a conformance suite living in `main()` that
`cargo test` compiles and never runs. In each the code looks present and
reports nothing. An orphan file does not even type-check.
The hazard is not the dead code itself, it is the next reader. A file that
documents itself as doing something real, sitting in the tree beside files that
do, will eventually be wired in by someone who trusts its header — and it has
never been compiled, let alone verified.
What is NOT an orphan, and why the exclusions matter:
src/bin/*.rs cargo auto-discovers these as binaries
examples/, tests/, benches/ likewise auto-discovered
lib.rs, main.rs, mod.rs, build.rs entry points
foo.rs beside a foo/ directory a directory module of the same name
A first pass at this check counted 77 orphans by missing the `src/bin`
exclusion. The real figure is a quarter of that and sits in one crate. A
detector that over-reports is as useless as one that under-reports, so the
exclusions are part of the check, not a convenience.
Usage:
scripts/check-orphan-sources.py # fail on anything not in BASELINE
scripts/check-orphan-sources.py --list # print every orphan found
The baseline pins what exists today so CI does not go red on a pre-existing
condition, and so the number can only go **down**. Removing a file from the
baseline is the point; adding one is a regression and should be argued for in a
commit message, not slipped in.
"""
from __future__ import annotations
import os
import re
import sys
# Pre-existing orphans, pinned 2026-10-02. All 25 are in jouleclaw-omni, which
# also holds `runtime/energy.rs` — a file documenting itself as measuring
# "actual GPU, CPU, ANE and DRAM energy consumption using Apple's IOReport
# framework" while in fact multiplying `getrusage` CPU seconds by a fixed 15 W
# and apportioning the result 60/20/20 across subsystems. It has never been
# compiled. That is precisely the trap this check exists to stop growing:
# a real meter with a per-rail liveness gate lives in `jouleclaw-energy`, and a
# reader who wires this one in instead gets a fabricated figure.
BASELINE = {
# Wants an `ffmpeg_next` dependency it does not have
# (`extern crate ffmpeg_next` -> E0463): a system library and a licensing
# choice, so it stays undeclared until that is decided. Every other file
# that was here on 2026-10-17 is now declared and type-checked.
"jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/video_decode.rs",
}
ENTRY = {"lib", "main", "mod", "build"}
DECL = re.compile(r"(?m)^\s*(?:pub(?:\([^)]*\))?\s+)?mod\s+([A-Za-z_]\w*)\s*;")
PATH_ATTR = re.compile(r'#\[path\s*=\s*"([^"]+)"\]')
INCLUDE = re.compile(r'include!\s*\(\s*"([^"]+)"')
def declared_names(src_root: str) -> set[str]:
"""Every module name the crate's own sources name, by any mechanism."""
names: set[str] = set()
for dirpath, dirs, files in os.walk(src_root):
dirs[:] = [d for d in dirs if d != "target"]
for f in files:
if not f.endswith(".rs"):
continue
try:
text = open(os.path.join(dirpath, f), encoding="utf-8", errors="ignore").read()
except OSError:
continue
names.update(DECL.findall(text))
for pat in (PATH_ATTR, INCLUDE):
for hit in pat.findall(text):
names.add(os.path.basename(hit).removesuffix(".rs"))
return names
def find_orphans(repo: str) -> list[str]:
orphans: list[str] = []
seen_roots: dict[str, set[str]] = {}
for dirpath, dirs, files in os.walk(repo):
dirs[:] = [d for d in dirs if d not in ("target", ".git", "node_modules")]
rel = os.path.relpath(dirpath, repo)
if "/src" not in "/" + rel + "/":
continue
# cargo auto-discovers these; they are reachable without a `mod`.
if "/src/bin" in "/" + rel or rel.endswith("/src/bin"):
continue
rs = [f for f in files if f.endswith(".rs")]
if not rs:
continue
src_root = os.path.join(repo, rel.split("/src")[0], "src")
if src_root not in seen_roots:
seen_roots[src_root] = declared_names(src_root)
declared = seen_roots[src_root]
for f in rs:
stem = f[:-3]
if stem in ENTRY:
continue
if stem in declared:
continue
if os.path.isdir(os.path.join(dirpath, stem)):
continue # a directory module of the same name
orphans.append(os.path.normpath(os.path.join(rel, f)))
return sorted(orphans)
def main() -> int:
repo = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
orphans = find_orphans(repo)
if "--list" in sys.argv:
for o in orphans:
mark = " (baseline)" if o in BASELINE else " NEW"
print(f"{o}{mark}")
print(f"\n{len(orphans)} orphan(s); {len(BASELINE)} pinned in the baseline")
return 0
new = [o for o in orphans if o not in BASELINE]
gone = sorted(BASELINE - set(orphans))
if gone:
print("These baseline orphans are reachable again, or were removed — good.")
print("Drop them from BASELINE in this script so the floor ratchets down:")
for g in gone:
print(f" {g}")
print()
if new:
print("New orphan source file(s): never compiled, so invisible to every")
print("check in this repo — cargo check, cargo test, clippy, conformance.")
print("Declare it with `mod`, move it under src/bin/, or delete it.\n")
for n in new:
print(f" {n}")
return 1
print(f"No new orphan sources ({len(orphans)} pinned, {len(BASELINE)} expected).")
return 1 if gone else 0
if __name__ == "__main__":
sys.exit(main())