jouleclaw-diagnose: a cross-model panel, so a verdict can rest on concurring models, or say they did not concur #277

Merged
dcharlot merged 1 commit from feat/diagnose-panel-entailer into main 2026-10-16 09:41:50 -04:00
Owner

What was missing

Backing::Concurring and Backing::Contested exist in the schema, and require_substantive_grounding already accepts them. But nothing produced either one: diagnose only ever declared one entailer's fixed backing. A verdict could never say "two independent models agreed", and could never record that they did not.

What this adds

  • PanelEntailer. A panel has at least two members, each a different model. Every consulted (claim, item) pair goes to every member, and the report carries each member's result under its own model id. That keeps require_substantive_grounding's check, that the declared backing matches the models in the evidence, working.
  • Backing read from the results, through the new Entailer::backing_of:
    • Concurring when every member gave the same label on every pair;
    • Contested when any two members differed on any pair.
  • A panel is only as substantive as its members. A fixture member makes the whole panel a fixture. An unstated member, including a nested panel, leaves it unstated. A stand-in's labels never become corroboration.
  • Grounding is unanimous per item. An item grounds a claim only when every result for that pair says "entails", so one model's "entails" can't outvote another's "neutral". If some model entailed the claim but no item had every model's agreement, the violation records models_disagree: true. If one member entails a pair and another contradicts it, that surfaces as the existing consistency conflict.

Single-model behaviour is unchanged. Each pair has one result, so "every result entails" means the same as "it entails". The new detail key appears only when a panel splits, so a single model's report keeps its bytes. The two new trait methods have default implementations, so existing entailers need no change.

Checked

On the build host, jouleclaw-diagnose and jouleclaw-edge-cli pass, including the 7 new tests:

  • the panel needs two different models;
  • the panel's floor comes from its members;
  • a panel that agrees grounds the claim as Concurring;
  • a panel that disagrees is Contested and does not ground the claim;
  • a panel split between "entails" and "contradicts" surfaces a conflict;
  • a single model's grounding violation is unchanged;
  • a fixture on the panel is not corroboration.

Clippy reports nothing new.

Each of these mutations fails at least one test:

  • grounding by any one model;
  • a panel that is never contested;
  • members' floor ignored;
  • the same model allowed twice.

🤖 Generated with Claude Code

## What was missing `Backing::Concurring` and `Backing::Contested` exist in the schema, and `require_substantive_grounding` already accepts them. But nothing produced either one: diagnose only ever declared one entailer's fixed backing. A verdict could never say "two independent models agreed", and could never record that they did not. ## What this adds - **`PanelEntailer`.** A panel has at least two members, each a different model. Every consulted (claim, item) pair goes to every member, and the report carries each member's result under its own model id. That keeps `require_substantive_grounding`'s check, that the declared backing matches the models in the evidence, working. - **Backing read from the results**, through the new `Entailer::backing_of`: - `Concurring` when every member gave the same label on every pair; - `Contested` when any two members differed on any pair. - **A panel is only as substantive as its members.** A fixture member makes the whole panel a fixture. An unstated member, including a nested panel, leaves it unstated. A stand-in's labels never become corroboration. - **Grounding is unanimous per item.** An item grounds a claim only when every result for that pair says "entails", so one model's "entails" can't outvote another's "neutral". If some model entailed the claim but no item had every model's agreement, the violation records `models_disagree: true`. If one member entails a pair and another contradicts it, that surfaces as the existing consistency conflict. **Single-model behaviour is unchanged.** Each pair has one result, so "every result entails" means the same as "it entails". The new detail key appears only when a panel splits, so a single model's report keeps its bytes. The two new trait methods have default implementations, so existing entailers need no change. ## Checked On the build host, `jouleclaw-diagnose` and `jouleclaw-edge-cli` pass, including the 7 new tests: - the panel needs two different models; - the panel's floor comes from its members; - a panel that agrees grounds the claim as `Concurring`; - a panel that disagrees is `Contested` and does not ground the claim; - a panel split between "entails" and "contradicts" surfaces a conflict; - a single model's grounding violation is unchanged; - a fixture on the panel is not corroboration. Clippy reports nothing new. Each of these mutations fails at least one test: - grounding by any one model; - a panel that is never contested; - members' floor ignored; - the same model allowed twice. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jouleclaw-diagnose: a cross-model panel, so a verdict can rest on concurring models, or say they did not concur
All checks were successful
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 59s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 34s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 5s
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 1m7s
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 3m9s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 5m11s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 54s
6b782b5ef6
`Backing::Concurring` and `Backing::Contested` were in the schema, and
`require_substantive_grounding` already accepted them. But nothing produced
either: diagnose only ever declared one entailer's fixed backing. A verdict
could never say "two independent models agreed", nor record that they did
not.

- `PanelEntailer`: at least two members, each a different model. Each
  consulted (claim, item) pair is put to every member, and the report
  carries every member's result under its own model id, so
  `require_substantive_grounding`'s check that the claim matches the
  evidence holds.
- Its backing is read from the results (`Entailer::backing_of`):
  `Concurring` when every member gave the same label on every pair, and
  `Contested` when any two differed. A panel is only as substantive as its
  members. A fixture member makes the whole panel a fixture, and an
  unstated member leaves it unstated, so a stand-in's labels never become
  corroboration.
- Grounding is unanimous per item: an item grounds a claim only when every
  result for that pair entails it. One model's "entails" no longer outvotes
  another's "neutral", and a claim some model entailed, without every
  model's agreement on an item, says `models_disagree: true`. A pair one
  member entails and another contradicts is the existing consistency
  conflict.
- Single-model behaviour is unchanged. Each pair has one result, so
  "every result entails" is "it entails". The new detail key appears only
  where a panel split, so a single model's report keeps its bytes. The
  trait's two new methods are provided, so existing entailers are
  untouched.

Co-Authored-By: Claude Opus 5.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!277
No description provided.