jouleclaw: a routing plan carries the class of its energy figure #418

Merged
dcharlot merged 1 commit from fix/routing-plan-carries-its-class into main 2026-10-22 06:49:04 -04:00
Owner

#390 said the enforceable fix for router_joules was to give RoutingPlan a provenance, so a declared constant stops sharing a type with a measurement. This is that change.

RoutingPlan gains router_energy_class: Provenance. Every router in this workspace sets Estimator, because every one charges a constant or a sum of constants — nothing in routing is measured today, and the type now says so rather than leaving a reader to discover it.

It matters because the figure is debited: tier.rs does spent += plan.router_joules. A consumer that cannot tell a measurement from a declared constant cannot tell whether the budget it is enforcing means anything.

Alternatives rejected on the merits

  • JouleClass is a tier taxonomy (Cache/Lawful/Embed/Model/Wire) — not a grade.
  • Moving Provenance into jouleclaw-core is the tidier home, but it has 61 importers; churning them to serve two crates isn't proportionate.
  • A local grade enum in cascade would be a third spelling of a vocabulary the family already has.

So cascade and routing depend on jouleclaw-energy with default-features = false. Every hardware backend there is already opt-in, so this adds the type and no meter.

The magnitude is unchanged, deliberately

ROUTING_JOULES = 8e-9 J is 0.008 µJ:

  • below the integer-microjoule unit the protocol uses — EnergyReading is u64 µJ, and "floating-point is forbidden in the protocol for determinism" — so it rounds to zero there;
  • six orders of magnitude below the ~1 mJ floor jouleclaw-energy itself calls realistic for an Estimator source.

The significand is unjustified. Correcting it needs a measurement — substituting a different invented number would repeat the error this change exists to label. What the change does is make the class legible so no consumer reads 8 nJ as measured.

Falsification found two real gaps in my own tests

Mutating LearnedRouter's and PhasorRouter's own RoutingPlan literals changed nothing. The test exercised RoutingPlan::fallback for both routers, so their own constructions were never reached and could have claimed HwShunt freely. Fixed by driving each past cold start with record_outcome and asserting !plan.is_fallback() first, so the test cannot silently slide back onto the path that pins nothing.

Mutating PrivacyRouter's composition to take the inner plan's class was invisible. With every shipped router on Estimator, inner.router_energy_class and Provenance::Estimator read identically — the mutation was undetectable by construction. Separating them needed a stub inner router claiming HwShunt, which pins the actual rule: a sum containing an unmeasured constant is an estimate, however good the measured term was.

mutation result
fallback() claims HwShunt only a_fallback_plan_is_estimator_class FAILED
LearnedRouter's literal claims ModelBased only every_shipped_router_declares_an_estimator_class FAILED
PhasorRouter's literal claims HwShunt only every_shipped_router_declares_an_estimator_class FAILED
privacy composition claims the inner class only a_constant_added_to_a_measured_figure_degrades_the_class FAILED

Verification

  • cargo check --workspace --all-targets --locked (jouleclaw-rs, RUSTFLAGS=-C target-feature=+fp16) — 0 errors
  • cargo test --workspace --locked — 486 test binaries green, 0 failures
  • joule-code/examples/l3-jouleclaw check — 0 errors
  • check-lockfiles — 47 lockfiles current; both workspaces naming these crates were refreshed (jouleclaw-rs and l3-jouleclaw — found by grepping Cargo.lock, not Cargo.toml, since the second only appears in the lock)

The 10 clippy findings in these crates are pre-existing, unchanged in count, and all in lines this change did not author (coord_router_impl.rs:241 shifted to :242 behind an inserted line). Neither crate is in CI's clippy list.

🤖 Generated with Claude Code

#390 said the enforceable fix for `router_joules` was to give `RoutingPlan` a provenance, so a declared constant stops sharing a type with a measurement. This is that change. `RoutingPlan` gains `router_energy_class: Provenance`. Every router in this workspace sets `Estimator`, because every one charges a constant or a sum of constants — **nothing in routing is measured today**, and the type now says so rather than leaving a reader to discover it. It matters because the figure is **debited**: `tier.rs` does `spent += plan.router_joules`. A consumer that cannot tell a measurement from a declared constant cannot tell whether the budget it is enforcing means anything. ## Alternatives rejected on the merits - **`JouleClass`** is a tier taxonomy (Cache/Lawful/Embed/Model/Wire) — not a grade. - **Moving `Provenance` into `jouleclaw-core`** is the tidier home, but it has **61 importers**; churning them to serve two crates isn't proportionate. - **A local grade enum in cascade** would be a third spelling of a vocabulary the family already has. So cascade and routing depend on `jouleclaw-energy` with `default-features = false`. Every hardware backend there is already opt-in, so this adds the type and no meter. ## The magnitude is unchanged, deliberately `ROUTING_JOULES = 8e-9` J is **0.008 µJ**: - below the integer-microjoule unit the protocol uses — `EnergyReading` is `u64` µJ, and *"floating-point is forbidden in the protocol for determinism"* — so it rounds to **zero** there; - **six orders of magnitude** below the ~1 mJ floor `jouleclaw-energy` itself calls realistic for an `Estimator` source. The significand is unjustified. Correcting it needs a measurement — substituting a *different* invented number would repeat the error this change exists to label. What the change does is make the class legible so no consumer reads 8 nJ as measured. ## Falsification found two real gaps in my own tests **Mutating `LearnedRouter`'s and `PhasorRouter`'s own `RoutingPlan` literals changed nothing.** The test exercised `RoutingPlan::fallback` for both routers, so their own constructions were never reached and could have claimed `HwShunt` freely. Fixed by driving each past cold start with `record_outcome` and asserting `!plan.is_fallback()` **first**, so the test cannot silently slide back onto the path that pins nothing. **Mutating `PrivacyRouter`'s composition to take the inner plan's class was invisible.** With every shipped router on `Estimator`, `inner.router_energy_class` and `Provenance::Estimator` read identically — the mutation was undetectable by construction. Separating them needed a stub inner router claiming `HwShunt`, which pins the actual rule: **a sum containing an unmeasured constant is an estimate, however good the measured term was.** | mutation | result | |---|---| | `fallback()` claims `HwShunt` | **only** `a_fallback_plan_is_estimator_class` FAILED | | `LearnedRouter`'s literal claims `ModelBased` | **only** `every_shipped_router_declares_an_estimator_class` FAILED | | `PhasorRouter`'s literal claims `HwShunt` | **only** `every_shipped_router_declares_an_estimator_class` FAILED | | privacy composition claims the inner class | **only** `a_constant_added_to_a_measured_figure_degrades_the_class` FAILED | ## Verification - `cargo check --workspace --all-targets --locked` (`jouleclaw-rs`, `RUSTFLAGS=-C target-feature=+fp16`) — **0** errors - `cargo test --workspace --locked` — **486** test binaries green, **0** failures - `joule-code/examples/l3-jouleclaw` check — **0** errors - `check-lockfiles` — **47** lockfiles current; both workspaces naming these crates were refreshed (`jouleclaw-rs` and `l3-jouleclaw` — found by grepping `Cargo.lock`, not `Cargo.toml`, since the second only appears in the lock) The 10 clippy findings in these crates are **pre-existing**, unchanged in count, and all in lines this change did not author (`coord_router_impl.rs:241` shifted to `:242` behind an inserted line). Neither crate is in CI's clippy list. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jouleclaw: a routing plan carries the class of its energy figure
All checks were successful
jouleclaw fabrics / cuda (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 20s
jouleclaw fabrics / vulkan (linux, RTX 4050 + Vulkan loader) (pull_request) Successful in 20s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 1m7s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 2m40s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m39s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 7s
joule-code conformance gate / joule-moq-ingest, every target (pull_request) Successful in 2m12s
joule-code conformance gate / joule-moq-relay, every target (pull_request) Successful in 2m32s
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 3m27s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 4m9s
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 1m4s
jouleclaw fabrics / metal (macOS, Apple GPU) (pull_request) Successful in 58s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 10m50s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 3m12s
b6ad1b0763
#390 said the enforceable fix for `router_joules` was to give `RoutingPlan` a
provenance, so a declared constant stops sharing a type with a measurement.
This is that change.

`RoutingPlan` gains `router_energy_class: Provenance`. Every router in this
workspace sets `Estimator`, because every one of them charges a constant or a
sum of constants — **nothing in routing is measured today**, and the type now
says so rather than leaving a reader to find out. It matters because the figure
is debited: `tier.rs` does `spent += plan.router_joules`, and a consumer that
cannot tell a measurement from a constant cannot tell whether the budget it is
enforcing means anything.

Three alternatives were rejected on the merits, not on taste:

- `JouleClass` is a tier taxonomy (Cache/Lawful/Embed/Model/Wire), not a grade.
- Moving `Provenance` into `jouleclaw-core` would be the tidier home, but it has
  **61 importers**; churning them to serve two crates is not proportionate.
- A local grade enum in cascade would make a third spelling of a vocabulary the
  family already has.

So cascade and routing depend on `jouleclaw-energy` with
`default-features = false`. Every hardware backend there is already opt-in, so
this adds no meter to the cascade's dependency graph — just the type.

**The magnitude is unchanged, deliberately.** `ROUTING_JOULES = 8e-9` J is
0.008 µJ: below the integer-microjoule unit the protocol uses (`EnergyReading`
is `u64` µJ, and "floating-point is forbidden in the protocol for
determinism"), so it rounds to zero there, and six orders of magnitude below
the ~1 mJ floor `jouleclaw-energy` itself calls realistic for an `Estimator`
source. The significand is unjustified. Correcting it needs a measurement;
substituting a different invented number would repeat the error this change
exists to label.

Falsification found two real gaps in my own tests before this was right:

- Mutating `LearnedRouter`'s and `PhasorRouter`'s own `RoutingPlan` literals
  changed **nothing**, because the test exercised `RoutingPlan::fallback` for
  both — their constructions were never reached. Fixed by driving each past
  cold start with `record_outcome` and asserting `!plan.is_fallback()` *first*,
  so the test cannot silently slide back onto the path that pins nothing.
- Mutating `PrivacyRouter`'s composition to take the inner plan's class was
  **invisible**, because with every shipped router on `Estimator` the two
  expressions agree. Separating them needed a stub inner router claiming
  `HwShunt`, which pins the actual rule: a sum containing an unmeasured
  constant is an estimate, however good the measured term was.

All four mutations now fail exactly one named test each.

Lockfiles: both workspaces that name these crates are refreshed
(`jouleclaw/jouleclaw-rs`, `joule-code/examples/l3-jouleclaw`); 47 lockfiles
current.

Verified: workspace check 0 errors, 486 test binaries green, 0 failures;
`l3-jouleclaw` check 0 errors. The 10 clippy findings in these crates are
pre-existing, unchanged in count, and all in lines this change did not author
(`coord_router_impl.rs:241` shifted to `:242` behind an inserted line); neither
crate is in CI's clippy list.

Co-Authored-By: Claude Opus 5 <[email protected]>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!418
No description provided.