Skip to content

feat: local HAL provider + zero-config viem ERC-8004 client (C→A milestone)#7

Open
DealAppSeo wants to merge 1 commit into
mainfrom
feat/cc1-2026-05-28-local-hal-and-erc8004
Open

feat: local HAL provider + zero-config viem ERC-8004 client (C→A milestone)#7
DealAppSeo wants to merge 1 commit into
mainfrom
feat/cc1-2026-05-28-local-hal-and-erc8004

Conversation

@DealAppSeo
Copy link
Copy Markdown
Owner

What

Two new packages + Plonky3-overclaim cleanup on the README. The packages fill the hallucination and identity slots of createHDP() with local-primary implementations so trinity-internal consumers can reach C of the C→A milestone (D-017). Hosted repid-engine stays as the swappable fallback behind the same interface.

Sprint contract

Phase Status Output
0 — Verify HAL + createHDP + ERC-8004 locations repid-engine/src/hal/lib/{extract,score,constants,types}.ts deterministic + dependency-free; createHDP() slots are injection points; canonical addresses confirmed
A — Local HAL extractor (primary) New packages/defaults/hallucination-hal-local/ (private:true); 4/4 byte-equivalent vs production
B — Zero-config ERC-8004 viem client New packages/defaults/identity-erc8004-viem/; 4/4 live reads pass; 6/6 write-gates fire; zero broadcasts
C — DECISION_LOG seed + Plonky3 overclaim cleanup E:\dev\living-docs\DECISION_LOG.md seeded as stub (Sean's canonical D-017–D-029 NOT in tree; CC1 did not invent); 6 README edits replace Plonky3-as-reputation-proof framing per D-019

Package 1 — @hyperdag/hallucination-hal-local (private: true)

Why private: true. The HAL formula weights, the Pythagorean Comma constant (531441/524288), and the canonical signal field names are patent-load-bearing per CLAUDE.md hard-stop and the existing @hyperdag/hallucination-hal dist comment ("part of HDP's patent portfolio (P-003) and are NOT redistributed"). This package ships as source for trinity-internal createHDP({}) consumers but the private: true flag prevents accidental npm publish. Sean owns the publish gate.

Three classes:

  • LocalHALProvider — primary. No network calls. 4 deterministic signals (harm / epistemic / evidence / scope) computed from the output; 5th (agreement_score) is caller-supplied. Implements IHallucination structurally; populates the canonical 6-DOF block via best-effort projection of the native 5-signal block.
  • RemoteHALProvider — re-export of @hyperdag/hallucination-hal for API symmetry.
  • HALRouter — single IHallucination that flips between local/remote based on HDP_MODE env (local | remote | hybrid). Hybrid runs local first; if score lands in borderline [0.20, 0.30] AND a remote URL is configured, runs remote for a second opinion. Remote unreachable in hybrid → returns local with borderline_fallback: true.

A/B proof — 4/4 byte-equivalent to production HAL:

Case Claim local score local vetoed matches prod?
A — overconfident CRE "LA industrial cap rates definitely compressed 4.8%..." 0.6528 true
B — hedged CRE "Based on CBRE data, ... approximately 0.5–1.2%..." 0.1703 false
C — false technical "Plonky3 definitely uses BN254 with Groth16..." 0.4724 true
D — math truth "The Pythagorean Comma ratio is exactly 531441/524288..." 0.2573 true

(Case D vetoed=true at the 0.25 threshold is a known characteristic of the deterministic-only extractor on short factually-correct claims with very high certainty; matches production. The remote provider can override via cross-LLM agreement when needed — exactly the hybrid mode case.)

Honest divergence (vs remote with cross-LLM):

  • No providers → agreement_score=null, 4-signal combiner runs (different than remote-with-providers result for factual / time-sensitive prompts).
  • BYOK providers → caller passes LLM provider configs. NO local LLM bundled — that would be a 1–4 GB tarball. Out of scope tonight; honest fallback to BYOK or remote.
  • This divergence is documented in packages/defaults/hallucination-hal-local/README.md.

Package 2 — @hyperdag/identity-erc8004-viem

Zero-config viem-backed IIdentity. Default Base Sepolia RPC + canonical addresses. Read works zero-config; signed writes require explicit signer; mainnet writes additionally require allowMainnet: true.

Defaults:

  • RPC URL https://sepolia.base.org
  • IdentityRegistry 0x8004A818BFB912233c491871b3d84c89A494BD9e (canonical, per CLAUDE.md / XC audit)
  • Chain ID 84532

Safety layers (all default-ON):

Layer Triggers Error class
Read-only mode Write attempted without privateKey or walletClient MissingSignerError (carries one-line example in the message)
dryRun (default true) Any write attempted with a signer but dryRun !== false DryRunBlocked (carries intended functionName + args so tests can inspect what would have happened)
Mainnet guard Write attempted with chainId=8453 without allowMainnet: true MainnetGuardError

Live proof (4/4 reads from canonical IdentityRegistry, no signer):

agentId=3747  owner=0xdf6b8215...  uri=data:application/json;base64,...
              decoded name=SOPHIA, description="Constitutional trading
              agent. Pythagorean Comma veto. 0% drawdown."
              (matches the canonical trinity-sophia token from CC1 memory)
agentId=1     owner=0x21fdEd74...  decoded name="Test Agent 004 (Image Test)"
agentId=2     owner=0x08684d22...  uri=ipfs://bafkreiffkwgvqplnbg6...
agentId=100   owner=0xec94934E...  decoded name="AlphaSentinel AI"
              x402Support=true

Write-gating proof (6/6 gates fire; zero broadcasts):

✓ register without signer -> MissingSignerError (mentions privateKey)
✓ register signer + dryRun -> DryRunBlocked (captures register/ipfs://test123)
✓ mainnet write without allowMainnet -> MainnetGuardError

The dryRun=false (broadcast) path was deliberately NOT exercised tonight — requires Sean's explicit approval per sprint rules.

README — Plonky3 cleanup (per D-019)

Six edits replacing overclaims with honest framing:

Before After
"Optional ZKP RepID circuit (Plonky3) for privacy-preserving score proofs." "Selective-disclosure / private-ownership proofs via a Plonky3 STARK range-check today; the roadmap-V2 circuit that binds the proof to the actual RepID-derivation transcript is in active development."
"The ZKP RepID circuit provides a verifiable-attestation flavor today" "First-class TEE-backed ValidationRegistry support is roadmap (see V2 below). The Plonky3 STARK in @hyperdag/reputation-zkp today proves a narrow range claim (repid > threshold); binding the proof to the agent decision + HAL signals is also V2."
| IReputation | @hyperdag/reputation-zkp | ZKP RepID | | IReputation | @hyperdag/reputation-zkp | On-chain RepID via ERC-8004 ReputationRegistry; ZKP for private-ownership / range proofs (Plonky3, V1 today — full V2 binds to RepID transcript) |
Mermaid subgraph "Privacy Layer" / "ZKP RepID Circuit" / "Sovereign Credentials" "Privacy Layer (V1: range-check today; V2: bound to RepID transcript)" / "Plonky3 STARK Circuit" / "Selective-disclosure proofs"
"ZKP RepID — privacy-preserving reputation proofs (Plonky3, BabyBear field, Poseidon2)." "ZKP for private ownership — Plonky3 STARK (BabyBear field, Keccak FRI) range-check today; roadmap-V2 circuit binds the proof to the agent decision + HAL signals + RepID-delta derivation."
V2 roadmap row Adds explicit "ZKP RepID circuit bound to agent decision + HAL signals + RepID-delta transcript (extension of today's Plonky3 range-check)"

Per XC's 2026-05-28 functional audit: today's zkp-postcard binary proves only that some scalar (repid - threshold - 1) fits in u32 — the scalar is fetched from a trusted database, not derived in ZK from any agent execution. The edits make that explicit instead of letting the README imply otherwise.

DECISION_LOG seed (Phase C1)

E:\dev\living-docs\DECISION_LOG.md was created as a structured stub because Sean's canonical D-017–D-029 content was not in the tree at sprint time. Per the sprint constraint ("DO NOT invent DECISION_LOG entries — use Sean's canonical content or ask"), CC1 did not fabricate entries. The stub establishes the file at the canonical path and lays out the expected schema so Sean can paste real text in one editing pass.

What this PR deliberately does NOT do

  • ❌ Touch the validation harness (GA's lane) or the scoring model
  • ❌ Compile and publish @hyperdag/hallucination-hal-local to npm (private: true; Sean's gate)
  • ❌ Execute any on-chain writes (sprint rule + safety layers)
  • ❌ Self-merge — copy edits + new package surface are Sean's review
  • ❌ Touch packages/contracts/ERC8004SPEC.md or any Marco De Rossi file (CLAUDE.md hard-stop)
  • ❌ Invent DECISION_LOG entries
  • ❌ Touch repid-engine

Files changed

~ README.md                                                       (6 edits)
+ packages/defaults/hallucination-hal-local/                      (12 files)
+ packages/defaults/identity-erc8004-viem/                        (12 files)

(The 2 packages have a total of ~24 source + test + readme files; no dist/ checked in.)

After merge

  1. Sean reviews the README cleanup against XC_TRUSTSHELL_FUNCTIONAL_AUDIT.md framing.
  2. Decision on whether to track packages/defaults/hallucination-hal-local permanently or split it to a separate private monorepo.
  3. Sean paste-fills E:\dev\living-docs\DECISION_LOG.md with the canonical D-017–D-029 content.

Report: E:\dev\reports\2026-05-28\CC_LOCAL_HAL_AND_ERC8004.md (next).

…estone)

Two new packages filling the hallucination + identity slots of createHDP()
with local-primary implementations, plus an honest Plonky3 framing pass on
the public README (per D-019).

## packages/defaults/hallucination-hal-local/  (private: true)

Local-primary IHallucination implementation. Ports the deterministic
5-signal extractor + canonical combiner from
repid-engine/src/hal/lib/{extract,score,constants,types}.ts.

Three classes:
  - LocalHALProvider — primary; no network calls; 4 deterministic signals
    from the output, optional caller-supplied agreement_score for the
    5th. Implements IHallucination structurally; populates the canonical
    6-DOF block via best-effort projection of the native 5-signal block.
  - RemoteHALProvider — re-export of @hyperdag/hallucination-hal for
    API symmetry.
  - HALRouter — single IHallucination that flips between local/remote
    based on HDP_MODE env var (local | remote | hybrid). Hybrid runs
    local first; if score lands in borderline [0.20, 0.30] AND a remote
    URL is configured, runs remote for a second opinion.

WHY private: true: the HAL formula weights, the Pythagorean Comma
constant (531441/524288), and the signal field names are
patent-load-bearing per CLAUDE.md hard-stop + the existing
@hyperdag/hallucination-hal dist comment (P-003 portfolio). The package
ships as source for trinity-internal createHDP({}) consumers but the
package.json `private` flag prevents accidental `npm publish`. Sean
owns the publish decision.

A/B PROOF (4/4 byte-equivalent vs production HAL):
  - Case A (overconfident CRE)        local=0.6528 vetoed=true  prod=match
  - Case B (hedged CRE)               local=0.1703 vetoed=false prod=match
  - Case C (false technical claim)    local=0.4724 vetoed=true  prod=match
  - Case D (mathematical truth)       local=0.2573 vetoed=true  prod=match

The 5th signal (cross-LLM agreement) is honestly fallback-able:
  - No providers          -> agreement_score=null, 4-signal combiner
  - BYOK providers        -> caller passes provider configs (no LLM keys
                             bundled; that would be a 1-4 GB tarball)
  - Remote fallback       -> HALRouter routes borderline to repid-engine

## packages/defaults/identity-erc8004-viem/  (Apache 2.0)

Zero-config viem-backed IIdentity. Default Base Sepolia RPC + canonical
addresses. Read mode works with no signer; signed writes require
explicit `privateKey` or `walletClient`.

Defaults:
  RPC URL            https://sepolia.base.org
  IdentityRegistry   0x8004A818BFB912233c491871b3d84c89A494BD9e
  ReputationRegistry 0x8004B663056A597Dffe9eCcC1965A193B7388713 (read-only)
  Chain ID           84532

Safety layers (all default-ON):
  - read-only mode             -> writes throw MissingSignerError with
                                  one-line example in the message
  - dryRun=true (default)      -> writes throw DryRunBlocked carrying
                                  the intended functionName + args; no
                                  broadcast. Explicit dryRun:false to fire
  - allowMainnet=false (default) -> mainnet writes throw MainnetGuardError;
                                  read-only mainnet probes still work

LIVE PROOF (4/4 reads from canonical IdentityRegistry on Base Sepolia,
chainId 84532, RPC sepolia.base.org, no signer):
  agentId=3747 owner=0xdf6b8215... uri=data:application/json;base64,...
    decoded name=SOPHIA, description="Constitutional trading agent.
    Pythagorean Comma veto. 0% drawdown." -- matches the canonical
    trinity-sophia token ID in CC1 memory.
  agentId=1   owner=0x21fdEd74... uri=data:application/json;base64,...
    decoded name="Test Agent 004 (Image Test)"
  agentId=2   owner=0x08684d22... uri=ipfs://bafkreiffkwgvqplnbg6...
  agentId=100 owner=0xec94934E... uri=data:application/json;base64,...
    decoded name="AlphaSentinel AI" with x402Support=true

WRITE-GATING PROOF (6/6 gates fire; zero broadcasts):
  ✓ register without signer -> MissingSignerError (mentions privateKey)
  ✓ register signer + dryRun -> DryRunBlocked (captures register/ipfs://test123)
  ✓ mainnet write without allowMainnet -> MainnetGuardError

## README.md  (Plonky3-as-reputation-proof cleanup per D-019)

Six edits replacing overclaims with honest framing:
  - "Optional ZKP RepID circuit (Plonky3) for privacy-preserving score
    proofs" -> explicit V1=range-check / V2=bound-to-transcript split
  - "ZKP RepID circuit provides a verifiable-attestation flavor today"
    -> "today the Plonky3 STARK proves a narrow range claim
    (repid > threshold); binding the proof to the agent decision +
    HAL signals is also V2"
  - Six-default table "ZKP RepID" cell -> "On-chain RepID via ERC-8004
    ReputationRegistry; ZKP for private-ownership / range proofs
    (Plonky3, V1 today -- full V2 binds to RepID transcript)"
  - Mermaid Privacy Layer subgraph label -> "(V1: range-check today;
    V2: bound to RepID transcript)"
  - Core building blocks "ZKP RepID" -> "ZKP for private ownership --
    Plonky3 STARK (BabyBear field, Keccak FRI) range-check today;
    roadmap-V2 circuit binds the proof to the agent decision + HAL
    signals + RepID-delta derivation"
  - V2 roadmap line gains "ZKP RepID circuit bound to agent decision +
    HAL signals + RepID-delta transcript (extension of today's Plonky3
    range-check)"

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant