From 104a8b444c3f41e01ecc072835b0cc0e15f443a8 Mon Sep 17 00:00:00 2001 From: David Charlot Date: Fri, 2 Oct 2026 00:46:17 -0400 Subject: [PATCH 1/2] check: no library source file is unreachable from its crate root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Going after the meters turned up a worse instance of a family this repo keeps finding. `jouleclaw-omni/src/runtime/energy.rs` documents itself as measuring "actual GPU, CPU, ANE and DRAM energy consumption in joules using Apple's IOReport framework". It does not call IOReport. The macOS path multiplies `getrusage` CPU seconds by a fixed 15 W; the other path multiplies wall-clock by 45 W; each then splits the result 60/20/20 across subsystems by constant fractions. It has **zero tests**, and `runtime/mod.rs` does not declare it — so it has never been compiled, by anything, ever. That is the strongest member of the family. A feature-gated test with no `--features` reports zero tests; a platform-gated meter on a single-platform runner compiles out; a conformance suite in `main()` gets built and never run. An orphan source file does not even type-check. It is invisible to cargo check, cargo test, clippy and every conformance suite simultaneously, and it cannot fail because nothing asks it anything. The hazard is the next reader, not the dead code. A real meter with a per-rail liveness gate already lives in the same workspace (`jouleclaw-energy`); someone who trusts this file's header and wires it in instead gets CPU-seconds times a guess, apportioned by invented fractions — energy derived from a performance proxy, which is the thing the whole metering ladder exists to grade against. So: `scripts/check-orphan-sources.py`, wired into the hygiene workflow. The per-subsystem split is worth naming separately — four fields reading as four independent observations when all four are fractions of one number is precision standing in for measurement, and it invites conclusions nothing here supports. **Measured, not estimated.** 1659 library sources checked; 25 orphans, all in `jouleclaw-omni`, 19,964 lines never compiled. Every other crate is clean. My first pass said 77 — it counted `src/bin/*.rs`, which cargo auto-discovers, so the exclusions are part of the check rather than a convenience. The baseline was then generated by the detector instead of retyped, because hand-copying it pinned 15 of 25 and the check caught the other ten. Falsified in both directions before being trusted, and the CI step repeats the self-test on every run: a planted orphan must fail the check, and removing it must pass. Exit codes verified without a pipe — `$?` after `| head` is head's status, which is how a gate silently stops gating. The baseline pins today's 25 so this does not go red on a pre-existing condition, and names what the file falsely claims. Removing an entry is the point; adding one is a regression to argue for in a commit message. `energy.rs` itself gets a corrected header and nothing else. I had added a declared `EnergyBasis` to it and reverted that: the field made the orphan stop compiling, and a broken orphan is worse than an honest one. Whether those 25 files are wired up or deleted is not mine to decide — 20k lines is someone's work, and the guard stops the problem growing either way. Co-Authored-By: Claude Opus 5 --- .github/workflows/no-vanity-metrics.yml | 43 +++++ .../jouleclaw-omni/src/runtime/energy.rs | 33 +++- scripts/check-orphan-sources.py | 175 ++++++++++++++++++ 3 files changed, 247 insertions(+), 4 deletions(-) create mode 100755 scripts/check-orphan-sources.py diff --git a/.github/workflows/no-vanity-metrics.yml b/.github/workflows/no-vanity-metrics.yml index d156f331a..43e35cd52 100644 --- a/.github/workflows/no-vanity-metrics.yml +++ b/.github/workflows/no-vanity-metrics.yml @@ -140,3 +140,46 @@ jobs: exit 1 # (touched to test that this very change supersedes its own queued runs) + # ── No library source file is unreachable from its crate root ───────────── + # + # An orphan `.rs` — one no `mod`, `#[path]` or `include!` ever names — is not + # merely untested. It is never compiled, so it is invisible to every check in + # this repository at once: cargo check, cargo test, clippy, the conformance + # suites. It cannot fail, because nothing asks it anything. + # + # This repo keeps finding that family: a feature-gated test run without + # `--features`, a platform-gated meter pinned to one runner, a conformance + # suite in `main()` that `cargo test` compiles and never runs. An orphan file + # is the strongest member — it does not even type-check. + # + # The hazard is the next reader, not the dead code. One such file documents + # itself as measuring energy via IOReport and in fact multiplies CPU seconds + # by a fixed watt figure; a reader who trusts that header gets a fabricated + # number. The script's baseline pins today's 25 so this does not go red on a + # pre-existing condition, and so the count can only ratchet down. + orphan-sources: + name: No new orphan source files + runs-on: linux + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Both directions, before trusting the result: a planted orphan must fail + # the check, and removing it must pass. A guard verified in only the + # passing direction is a guard that has never been seen to work. + - name: The check fails closed (self-test) + run: | + set -euo pipefail + probe=jcp/jcp-rs/crates/jcp-efficiency/src/_ci_orphan_probe.rs + printf 'pub fn never_compiled() -> u64 { 0 }\n' > "$probe" + if python3 scripts/check-orphan-sources.py >/dev/null 2>&1; then + rm -f "$probe" + echo "::error::the orphan check passed with a planted orphan present" + exit 1 + fi + rm -f "$probe" + python3 scripts/check-orphan-sources.py + + - name: Run the orphan-source check + run: python3 scripts/check-orphan-sources.py + diff --git a/jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/runtime/energy.rs b/jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/runtime/energy.rs index 5c5976f52..51672402b 100644 --- a/jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/runtime/energy.rs +++ b/jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/runtime/energy.rs @@ -1,8 +1,33 @@ -//! Energy metering for Apple Silicon via IOReport. +//! Energy **estimation** from process time. Not a measurement, and not +//! IOReport — despite what this header said until 2026-10-02. //! -//! Measures actual GPU, CPU, ANE, and DRAM energy consumption in joules -//! using Apple's IOReport framework. Falls back to time-based estimation -//! on non-macOS platforms. +//! # What it actually does +//! +//! This file is **not compiled**: `runtime/mod.rs` does not declare it, so no +//! `cargo check`, `cargo test` or clippy run in this repository has ever looked +//! at it. The corrected description below is therefore a warning to the next +//! reader rather than a description of running code. +//! +//! It does not call IOReport. The macOS path reads `getrusage` and multiplies +//! CPU seconds by a fixed watt figure; the other path multiplies wall-clock by +//! a different fixed figure. Each then splits the result across GPU, CPU, ANE +//! and DRAM by constant fractions. +//! +//! The per-subsystem fields are the sharper problem. `gpu_joules`, +//! `cpu_joules`, `ane_joules` and `dram_joules` read as four independent +//! observations; they are four fractions of one guess. A split implies +//! resolution that does not exist, which invites per-subsystem conclusions +//! nothing here could support — precision standing in for measurement. +//! +//! # Before wiring this in +//! +//! A real meter lives in this same workspace: `jouleclaw-energy`, with a +//! per-rail liveness gate that declines to report rather than report a frozen +//! counter. Any figure intended to reach a receipt must come from there. If a +//! coarse power figure is genuinely wanted for scheduling, that is a legitimate +//! need — but it is `Estimator`-class in the JCP metering ladder (SPEC §5.1), +//! it MUST NOT be presented as `ModelBased`, and the subsystem split MUST NOT +//! be presented at all. use std::time::{Duration, Instant}; diff --git a/scripts/check-orphan-sources.py b/scripts/check-orphan-sources.py new file mode 100755 index 000000000..49143bf55 --- /dev/null +++ b/scripts/check-orphan-sources.py @@ -0,0 +1,175 @@ +#!/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 = { + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/bark.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/canary.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/chatterbox.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/depth_anything.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/esrgan.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/fibo.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/jamba.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/kokoro.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/mamba2.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/mimo.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/mochi.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/moonshine.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/nemotron.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/parler_tts.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/sam2.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/sana_wm_gpu_dispatchers_draft.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/sd3.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/architecture/sesame_csm.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/expert_cache.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/fusion.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/gpv.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/inference/video_decode.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/runtime/energy.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/server/model_library.rs", + "jouleclaw/jouleclaw-rs/crates/jouleclaw-omni/src/server/worker.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()) -- 2.54.0 (Apple Git-157) From 0c0b66f0017df47ccf8ff3cfe28e96b1278d488d Mon Sep 17 00:00:00 2001 From: David Charlot Date: Sat, 10 Oct 2026 09:54:53 -0400 Subject: [PATCH 2/2] jouleclaw-jcp: wire in two orphaned modules, and six tests that never ran MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rebasing the orphan-source guard over 817 commits of main found two new orphans immediately, which is the clearest argument for the check that I could have asked for. `jouleclaw-jcp/src/skill.rs` and `src/stack.rs` — 557 lines — are not declared anywhere: `lib.rs` names only `mod tests`. They were never abandoned, only never wired. Declaring them compiles clean, and brings **six tests** alive that had never once executed: skill::a_failing_pressure_test_blocks_registration_with_failures_on_record skill::a_granted_skill_loads_after_passing_pressure skill::a_tampered_document_is_a_different_audience stack::a_tight_ceiling_keeps_cheap_queries_cheap stack::the_default_stack_answers_behind_a_grant stack::the_grant_is_the_budget_authority_across_walks Those are not incidental. They assert that a tampered document resolves to a different audience, that a grant is the budget authority across walks, and that a failing pressure test blocks registration — tamper-detection and grant-authority properties, written down, compiled never, run never. All 15 tests in the crate now pass. Baselining them would have been the wrong move and is worth saying why: the guard exists to stop growth, so pinning code that arrived *after* the baseline would have converted it from a ratchet into a record of defeat. The baseline stays at the original 25, all in `jouleclaw-omni`, which are a different question — 20k lines whose disposal is the owner's call, not a two-line `mod` declaration. Also in this commit, from the original change: the orphan check itself, its CI job with a self-test that fails closed, and a corrected header on `jouleclaw-omni/runtime/energy.rs`, which documented itself as measuring energy via IOReport while multiplying `getrusage` CPU seconds by a fixed 15 W and apportioning the result 60/20/20 across subsystems. Re-verified on today's main after the rebase: the self-test still fails closed with a planted orphan and passes without one, exit codes checked without a pipe, and the ratchet reports the pinned 25 unchanged. Co-Authored-By: Claude Opus 5 --- jouleclaw/jouleclaw-rs/crates/jouleclaw-jcp/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jouleclaw/jouleclaw-rs/crates/jouleclaw-jcp/src/lib.rs b/jouleclaw/jouleclaw-rs/crates/jouleclaw-jcp/src/lib.rs index 02ff2f534..762e7fb03 100644 --- a/jouleclaw/jouleclaw-rs/crates/jouleclaw-jcp/src/lib.rs +++ b/jouleclaw/jouleclaw-rs/crates/jouleclaw-jcp/src/lib.rs @@ -52,6 +52,9 @@ use jcp_schema::{ContentId, Did, Energy, Frame, FrameKind, SignedGrant, Trust}; use jouleclaw_mcp::{McpError, MeteredTool}; use jouleclaw_transparency_log::{InclusionProof, LogError, MerkleTree, SignedTreeHead, TreeHead}; +pub mod skill; +pub mod stack; + /// The JCP resource of an MCP tool: the content address of its stable /// `tool_id` (e.g. `"mcp:filesystem/read"`). A grant scoped to this resource /// authorizes exactly this tool — a same-named tool on another server is a -- 2.54.0 (Apple Git-157)