jcp-efficiency: an undefined ratio is not zero #291
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/jcp-efficiency-undefined-ratio-is-not-zero"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The defect
uj_per_accepted_token()is the crate's headline figure, and it read:For a cost-per-result metric,
0is the optimum. So "the denominator was zero" (uncomputable) was reported as "this cost nothing per token" — perfect, and better than any successful run.It is not a convenience accessor.
wire()seals it into the signed core, andverify()reads it straight back out rather than recomputing it, so the conflation was sealed and consumed as the headline figure.The triggering case is the crate's own documented one:
completed: falseis documented as meaning "the tokens/joules below bought nothing" — exactly whentokens_outis 0 and the sealed figure became 0. A unit that burned 10 J and accepted nothing sealed, signed:Indistinguishable to a dashboard or an auditor from a run that used no energy at all.
The family already specifies the right shape
The doc comment claimed to match it — "matching the family's
uj_per_accepted_tokenconvention" — while doing the opposite:mesh/SPEC.md§6: the figure is "omitted when no tokens were accepted".mesh/SPEC.md§8: it "is undefined when no tokens were accepted".MeshReceipt::uj_per_accepted_tokenreturnsOption<u64>, omits the key from its sealed wire, and has tests pinning both branches.So this is a consistency fix onto a published family convention, not a new design. The
eval/1twin of it landed as #292.What changed, and the criterion
Changed — because the zero they returned is each figure's optimum:
Efficiency::uj_per_accepted_token0Option<u64>, omitted from the sealed core when undefinedEfficiencyReceipt::uj_per_accepted_tokenu64Option<u64>;verify()reads it as optional, so an older receipt carrying the figure still round-tripsuusd_per_accepted_tokenOption, butwire()sealed.unwrap_or(0)— inventing the value figure its own doc says is "never invented"and_then; key omitted.value_uusdis an input and still sealsTotals::tokens_per_completed_unit0Option<u64>Totals::uj_per_completed_unit0Option<u64>Totals::waste_fraction0.0Option<f64>tokens_per_completed_unitclaims to "charge every attempt against the results actually delivered", which it stops doing precisely when nothing was delivered: 50 units and 500 J of spend reported 0 cost per completed unit.waste_fraction's0.0is a perfect zero-waste record, which is what an empty ledger reported.Deliberately unchanged:
value_per_jouleandtokens_per_seckeep their0.0. Higher is better for both, so the fallback is their worst value, not their optimum — a zero that understates is not this defect.a_fallback_toward_the_worst_value_is_left_alonepins that choice so it reads as a decision rather than an omission.Tests
spend_that_bought_nothing_seals_no_headline_figure— 10 J, nothing accepted: the figure isNone, the key is absent from the signed core, the envelope still verifies, and the 10 J is still on it.a_value_figure_is_not_invented_without_accepted_tokens—value_uusdseals; the ratio derived from it does not.a_ledger_with_nothing_completed_reports_no_cost_per_unit— through the real seal → verify →aggregatepath; 30 J of spend, no cost-per-unit figure, andTotals::default().waste_fraction()isNone.a_fallback_toward_the_worst_value_is_left_alone— the kept zeros.Falsification
Some(0)on the headline figure0on the aggregate cost-per-unit ratioIn all three,
the_four_metrics_compute_from_the_inputsandseal_verify_round_trips_and_tamper_failskept passing — the tests are specific to the undefined case.Second commit: the cross-workspace consumers (CI caught this)
The first commit verified only
jcp/jcp-rs.jcp-efficiencyis a path dependency of three other workspaces, andcargo test --workspaceinsidejcp/jcp-rsnever compiles them — so thejouledesk-rs,sandbox-rsandjoulehook-rslegs all failed to build. Consumers:Five call sites read a figure that is now an
Option:jouledesk/src/lib.rs— the assertion that waste inflates joules-per-completed-unit. Two units completed there, so the ratio is defined;.expectrecords that rather than hiding it.jouledesk/examples/channel.rs,examples/room.rs,sandbox-tee/examples/attested_efficiency.rs— each prints—when undefined, for the same reasonsession.rsdoes.joulehook-meter—assert_eq!on a receipt field; 900 tokens were accepted, so the figure is present and the assertion takesSome.Efficiency's own fields did not change, so theEfficiency { .. }literals in all four consumers are untouched; only reads ofEfficiencyReceipt::uj_per_accepted_tokenandTotals::uj_per_completed_unitneeded work.Verification
Each of the four workspaces that compile this crate, not just the one holding the edit:
cargo check --workspace --all-targetscargo test --workspacejcp/jcp-rsjouledesk/jouledesk-rssandbox/sandbox-rsjoulehook/joulehook-rsScope
No conformance vector pins an
efficiency/1receipt (jcp/conformance/v1/has none; theuj_per_accepted_tokeninmesh/conformance/belongs tomesh-receipt, a different crate, which already omits it correctly). There is no jcp-side SPEC section listingefficiency/1fields.🤖 Generated with Claude Code
`uj_per_accepted_token()` is the crate's headline figure, and it read self.energy.uj().checked_div(self.tokens_out).unwrap_or(0) For a cost-per-result metric 0 is the *optimum*, so "the denominator was zero" (uncomputable) was reported as "this cost nothing per token" (perfect, and better than any successful run). It is not a convenience accessor: `wire()` seals it into the signed core, and `verify()` reads it straight back out rather than recomputing it, so the conflation was sealed and consumed as the headline. The case is the crate's own documented one. `completed: false` is documented as meaning "the tokens/joules below bought nothing" — exactly when `tokens_out` is 0 and the sealed figure became 0. A unit that burned 10 J and accepted nothing sealed `{"completed":0,"tokens_out":0,"energy_uj":10000000, "uj_per_accepted_token":0}`, signed: indistinguishable to a dashboard or an auditor from a run that used no energy. The family already specifies the right shape, and this crate's doc comment claimed to match it ("matching the family's `uj_per_accepted_token` convention") while doing the opposite. `mesh/SPEC.md` §6 says the figure is "omitted when no tokens were accepted", `mesh/SPEC.md` §8 says it "is undefined when no tokens were accepted", and `MeshReceipt::uj_per_accepted_token` returns `Option<u64>` and omits the key from its sealed wire, with tests pinning both branches. The fix brings jcp-efficiency onto that shape. Changed, because the zero they returned is each figure's *optimum*: - `Efficiency::uj_per_accepted_token` -> `Option<u64>`; omitted from the sealed core when undefined. `EfficiencyReceipt`'s field becomes `Option<u64>` and `verify()` reads it as optional, so an older receipt that carries the figure still round-trips. - `uusd_per_accepted_token` already returned `Option` because "a value figure is never invented" — but `wire()` sealed `.unwrap_or(0)`, inventing one. It now flattens with `and_then` and the key is omitted. `value_uusd` is an input and still seals. - `Totals::tokens_per_completed_unit` and `uj_per_completed_unit` -> `Option<u64>`. The first claims to "charge every attempt against the results actually delivered", which it stops doing precisely when nothing was delivered: 50 units and 500 J of spend reported 0 cost per completed unit. - `Totals::waste_fraction` -> `Option<f64>`: 0.0 is a perfect zero-waste record, which is what an empty ledger used to report. Deliberately unchanged: `value_per_joule` and `tokens_per_sec` keep their `0.0`. Higher is better for both, so the fallback is their worst value, not their optimum — a zero that understates is not this defect. `a_fallback_toward_the_worst_value_is_left_alone` pins that choice. `examples/session.rs` renders an undefined figure as "—" rather than a number, which also makes the distinction visible in the demo it prints. Co-Authored-By: Claude Opus 5 <[email protected]>CI caught what the previous commit's verification could not: `jcp-efficiency` is a **path dependency of three other workspaces**, and `cargo test --workspace` inside `jcp/jcp-rs` never compiles them. The jouledesk-rs, sandbox-rs and joulehook-rs legs all failed to build. The consumers are: jouledesk/.../jouledesk/Cargo.toml jouledesk/.../jouledesk-livekit/Cargo.toml jouledesk/.../jouledesk-github/Cargo.toml sandbox/.../sandbox-tee/Cargo.toml joulehook/.../joulehook-meter/Cargo.toml Five call sites read a figure that is now an `Option`: - `jouledesk/src/lib.rs` — the assertion that waste inflates joules-per-completed-unit. Two units completed there, so the ratio is defined; `.expect` now records that rather than hiding it. - `jouledesk/examples/channel.rs`, `examples/room.rs` and `sandbox-tee/examples/attested_efficiency.rs` — `println!` of the figure. Each prints "—" when undefined, for the same reason `session.rs` does: 0 is the optimum of a cost-per-result figure, so printing it would name the cheapest possible cost for work that delivered none. - `joulehook-meter` — `assert_eq!` on a receipt field; 900 tokens were accepted, so the figure is present and the assertion takes `Some`. `Efficiency`'s own fields did not change, so the `Efficiency { .. }` literals in all four consumers are untouched; only reads of `EfficiencyReceipt::uj_per_accepted_token` and `Totals::uj_per_completed_unit` needed work. Verified by building and testing **each** of the four workspaces that compile this crate — jcp-rs, jouledesk-rs, sandbox-rs, joulehook-rs — rather than only the one holding the edit: `cargo check --workspace --all-targets` and `cargo test --workspace` exit 0 in all four, with 0 failed suites. Co-Authored-By: Claude Opus 5 <[email protected]>