@JimmyShi22 v0.2 is the right structure. Two-layer separation in Composability means an implementer can plug into just the inner layer without taking the full stack, that’s the join point this section needed.
@babyblueviper1 PR looks solid. The three recordPointer invariants and the WYRIWE L4 execution binding are exactly the pieces missing from the Judgment Validator section. Shipped same day as promised.
Here’s the WYRIWE subsection , drop it in wherever the Judgment Validator lands, no PR needed from my side:
WYRIWE — Input Provenance (WYRIWE / ethereum/ERCs#1810)
WYRIWE makes IProofVerifier’s inputHash auditable. The base interface commits to a value — WYRIWE commits to how that value was derived, binding the signed inference receipt to the provenance chain that produced its input.
WYRIWE is a separate standard; ERC-8274 composes with it optionally — the dependency arrow points from 8274 to WYRIWE, not the reverse. The forum thread uses the working number 8299 pending editor assignment.
Inner Layer: IProofVerifier
function proofSystem() external pure returns (string memory); // "wyriwe/v1"
function verify(
bytes32 inputHash,
bytes32 outputHash,
bytes calldata agentData, // abi.encode(agentId, registryAddress)
bytes calldata proofData // abi.encode(modelHash, rawInputHash,
// sanitizationPipelineHash, commitmentHash, timestamp, sig)
) external view returns (bool);
verify recomputes commitmentHash = keccak256(abi.encode(agentId, modelHash, inputHash, outputHash, timestamp)), recovers the signer from the EIP-712 WyriweAttestation signature, and confirms the recovered signer matches the agentId declared in agentData. No external calls — pure recomputation and signature recovery. The registryAddress in agentData is passed through for the outer layer’s on-chain authorization check; the inner layer does not call it.
Provenance paths
inputHash is derived from raw calldata using one of two paths:
| Path |
Condition |
inputHash |
| Sentinel |
No transformation applied |
rawInputHash (= keccak256(rawCalldata)) |
| Non-sentinel |
A transformation step was applied (sanitization, judgment) |
keccak256(abi.encode(rawInputHash, sanitizationPipelineHash)) |
In the non-sentinel path, sanitizationPipelineHash = keccak256(cid_bytes) where cid_bytes is the UTF-8 encoding of the full CID string including the ipfs:// scheme prefix — byte-exact, no trimming. This pins the exact version of the transformation to the commitment. Any verifier can recompute inputHash from the raw calldata and the published CID without trusting the prover.
Judgment as a non-sentinel transformation
The non-sentinel path is the natural integration point with the Judgment Validator subsection above. When execution is gated on a signed verdict:
-
rawInputHash = keccak256 of the raw proposal (pre-judgment)
-
sanitizationPipelineHash = hash of the verdict data or policy CID that authorized execution
-
inputHash = keccak256(abi.encode(rawInputHash, sanitizationPipelineHash)) — the proposal bound to its verdict
This is the triple-hash chain: rawProposalHash → verdictHash (bound in inputHash) → executedActionHash (= outputHash). A verifier receiving (inputHash, outputHash, proofData) can confirm that execution was authorized by the specific verdict that produced that inputHash — without replaying the judgment. The commitmentHash closes the envelope: agent identity, model version, provenance-committed input, output, and timestamp all in one EIP-712-signed receipt.
Confidence and aggregation
WYRIWE attestations do not carry a verdict score, they carry a tamper-evident receipt of what ran. Confidence derivation follows the same Type A model established above: a pure function of settled commit-reveal records, no trusted updater, no mutable score stored on-chain. The receipt proves what the model saw and returned; aggregation and weighting live in IAgentVerifier, above the inner layer.
Type B weight (usage-based) carries the same self-dealing risk noted above. WYRIWE attestations count as valid Type A evidence only when backed by a commit-reveal settlement — a bare signed receipt without a settled outcome does not satisfy the Type A invariant.
Outer Layer: IAgentVerifier
IAgentVerifier wraps WyriweProofVerifier and adds:
-
Registration check against the ERC-8004 identity registry
-
VerificationCompleted event emission for on-chain consumers
-
Type A confidence aggregation over settled WYRIWE attestations
The inner layer (pure recomputation) and outer layer (stateful registry check + aggregation) remain separable, an operator running only the inner layer gets receipt verification; adding the outer layer gets identity-bound accountability.
Live proof
Ledger entry 23, api.babyblueviper.com/ledger/23 — is the first production instance of this composition:
| Step |
Detail |
| Identity |
PGA #14, tokenId 14 in ERC-8004 dynamic registry — mainnet ownerOf checkable |
| Provenance |
Non-sentinel: rawProposalHash → verdictHash → executedActionHash |
| Verdict |
approve_with_concerns, confidence 0.85 — concerns: identity-binding, impersonation |
| Timing |
Verdict timestamp strictly before execution timestamp — ordering invariant independently verifiable |
| Anchor |
Entry 23 verdict event id → TruthAnchorV1 (ERC-8263) — anchor leg pending |
Three of the four layers are independently verifiable now: identity (on-chain), verdict (pre-action), execution (post-verdict). The anchor leg in TruthAnchorV1 closes the fourth layer once posted, at that point all four layers (ERC-8004, WYRIWE, ERC-8274, ERC-8263) are satisfied by a single production entry.