Skip to content

feat: Circle experimental capsules — decimals & stale_quote (2 of 2)#4

Merged
adrianhihi merged 6 commits into
mainfrom
feat/circle-experimental-capsules
May 26, 2026
Merged

feat: Circle experimental capsules — decimals & stale_quote (2 of 2)#4
adrianhihi merged 6 commits into
mainfrom
feat/circle-experimental-capsules

Conversation

@adrianhihi

Copy link
Copy Markdown
Collaborator

Circle Experimental Capsules — PR 2 of 2

Follow-up to #3. Adds 2 experimentally-validated capsules from Helix's April 2026 Arc Testnet research, with end-to-end demo reproduction.


Why this PR exists

PR #1 (Circle Foundation) added 5 Circle capsules with seed q-values. Three of them — wallets-api-rate-limit, circle-param-invalid, circle-insufficient-funds — were validated against live Circle Sandbox.

This PR adds 2 more capsules, both with q-values derived from a previously-conducted controlled experiment series on Arc Testnet (April 2026):

Capsule Strategy q Source
decimals-metadata-mismatch override_api_decimals 0.95 Exp A — 1 real Arc tx
stale_quote observe (advisory) 0.96 Exp D — 932 real Arc tx, 96% E2E vs 0% bare

Both capsules are now exercised end-to-end in examples/circle-e2e.ts (Scenarios 4 and 5).


What it ships

Type system (types.ts)

  • ErrorCode += decimals-metadata-mismatch, stale_quote
  • FailureCategory += infrastructure (token metadata bugs, native-vs-ERC-20 confusion)
  • FailureClassification.chain optional field (e.g. 'arc-testnet', 'base-sepolia')

Strategy implementation (provider.ts)

override_api_decimals uses 3-priority resolution:

  1. On-chain — read ERC-20 decimals() if context.publicClient + tokenAddress provided
  2. Ground-truth table — for native USDC where no contract exists (Arc Testnet's case)
  3. Caller-supplied — fallback to context.expected_decimals

This handles Exp A's actual failure mode: Arc Testnet USDC is a native asset with no ERC-20 contract to query. Circle's API claims decimals=18; the real atomic resolution is 6. The repair must use ground-truth knowledge, not on-chain reads.

Two-tier perceive detection (circle/perceive.ts)

Tier 1 — Caller-emit (explicit context):

  • decimals-metadata-mismatch: when caller provides both expected_decimals and api_reported_decimals
  • stale_quote: when context.stale_quote=true OR response.data.code === 'STALE_QUOTE' OR message match

Tier 2 — Heuristic:

  • If requested_amount / available_balance > 10^9, suspect a decimals bug rather than insufficient funds (18-vs-6 ratio is 10^12, so 10^9 catches it comfortably)

Seed capsules (seed-genes.ts)

2 new entries with q-values from telemetry, not guesses.

Demo expansion (examples/circle-e2e.ts)

Scenarios 4 and 5 reproduce Exp A and Exp D respectively:

  • Scenario 4 — naive agent uses API's wrong decimals=18, sends 0.001 × 10^12 raw amount, Circle returns insufficient funds. Perceive heuristic catches the suspicious ratio, ground-truth table provides correct decimals=6, parameterModifier scales the amount, retry succeeds on real Arc Testnet.

  • Scenario 5 — synthetic STALE_QUOTE error matching x402 facilitator response shape. Perceive routes to stale_quote capsule. observe strategy records the failure for caller's preflight; does not auto-fix. Console surfaces reorder recommendation backed by Exp D's 932-tx data.


Validation

Two full demo runs (LEARN then IMMUNE rerun), all 5 scenarios pass cleanly:

Capsule deltas across two demo runs

Capsule RUN 0 (seed) RUN 1 RUN 2 Δ Final q
decimals-metadata-mismatch 1 3 5 +4 0.964
stale_quote 48 52 56 +8 0.976
wallets-api-rate-limit 9 21 31 +22 0.982
circle-param-invalid 3 7 11 +8 0.909
circle-insufficient-funds (new) 4 10 +6 0.758
gateway-rate-limit 7 7 7 0 0.700
gateway-nonce-used 8 8 8 0 0.920
cctp-attestation-pending 6 6 6 0 0.980

All exercised capsules show q-value rising. Untouched capsules (gateway, cctp) unchanged — Gene Map is self-consistent.

  • tsc --noEmit clean
  • ✅ 570/570 existing tests pass
  • ✅ Real Arc Testnet transactions submitted in Scenario 4 (verifiable on testnet.arcscan.app)
  • ✅ Demo Run 2 (IMMUNE) maintains correct classification; q-values continue rising

Notable findings during development

  1. Arc Testnet USDC is a native asset, not ERC-20. Circle's SDK returns { isNative: true, decimals: 18 } with no tokenAddress. Original Exp A repair worked by using ground-truth knowledge, not on-chain reads. Strategy now reflects this.

  2. stale_quote is an advisory capsule. The actual workflow reorder (think → discover → estimate → pay → verify) is the agent's responsibility, not the engine's. Helix records the failure pattern via observe strategy; agents preflight Gene Map audit logs to decide on reordering. Auto-reorder is a future PR.

  3. stale_quote preserves underscore casing. Inconsistent with other ErrorCodes' hyphen convention, but matches the string already stored in bench audit logs and Cloudflare registry. Changing to hyphens would silently break cross-agent inheritance.


Roadmap

This PR completes the "experimentally-validated capsule" milestone. Future work (out of scope here):

  • Real e2e demos for CCTP V2 and Circle Gateway — capsules are seeded in PR Welcome to helix Discussions! #1, strategies implemented, but no live integration testing yet. Both Circle products support Sandbox.

  • Automatic workflow reorder for stale_quote — implement as a wrap-layer feature alongside observe capsule. Currently advisory only.

  • Mainnet adapter and production tier configuration — pending Circle KYC approval and production API access.


Verification by reviewers

  • All Arc Testnet transactions verifiable on testnet.arcscan.app
  • Cloudflare telemetry registry: https://helix-telemetry.haimobai-adrian.workers.dev/v1/stats
  • Bench scripts: scripts/circle-bench/ (Exp A through Exp D)
  • To reproduce demo locally:
  git checkout feat/circle-experimental-capsules
  npm install && npm run build -w packages/core
  set -a; source scripts/circle-bench/.env; set +a
  rm -f circle-demo-genes.db
  npx tsx examples/circle-e2e.ts

ErrorCode union:
  decimals-metadata-mismatch  (Exp A April 2026, Arc Testnet)
  stale_quote                  (Exp D April 2026, x402 facilitator)

FailureCategory union:
  infrastructure  (token metadata bugs, native vs ERC-20 confusion)

FailureClassification.chain (optional string):
  identifies the blockchain context for chain-specific bugs
  e.g. 'arc-testnet', 'base-sepolia', 'avalanche-fuji'
stale_quote uses 'observe' (existing pass-through strategy, no whitelist
needed — advisory pattern records the failure for caller's preflight).
Three priorities for resolving correct decimals:
  1. on-chain ERC-20.decimals() if context.publicClient + tokenAddress
  2. ground-truth table for native USDC (arc-testnet, base-sepolia, etc.)
  3. caller-supplied via context.expected_decimals

Strategy returns _helix_actual_decimals + _helix_repair_source so
parameterModifier knows how to apply the correction.
decimals-metadata-mismatch + override_api_decimals:
  q=0.95 from Exp A on Arc Testnet
  Real tx: 0x113addf13baa75d60cd402360d2ecb67512c31b4214750f56ace81c749781d07

stale_quote + observe:
  q=0.96 from Exp D on Arc Testnet
  48/50 success across 932 confirmed transfers (96% E2E vs 0% bare)
  Advisory pattern — Helix records, caller preflights with reorder
Tier 1 (caller-emit, explicit context):
  decimals-metadata-mismatch: when context provides expected_decimals
    and api_reported_decimals
  stale_quote: when context.stale_quote=true OR response.data.code='STALE_QUOTE'
    OR /stale.*quote|quote.*expired/i message match

Tier 2 (heuristic for decimals):
  If requested_amount / available_balance > 10^9, suspect a decimals
  bug rather than a true insufficient funds error.
  (10^12 ratio is the 18-vs-6 case; 10^9 catches it comfortably)
Scenario 4 — Decimals override (Exp A reproduction):
  Naive agent uses API's wrong decimals=18 for Arc USDC (real value 6)
  Sends inflated amount → insufficient funds
  Helix perceive heuristic catches the amount/balance > 10^9 ratio
  Override strategy uses ground-truth table for native asset
  Real Arc Testnet tx submitted after correction

Scenario 5 — Stale quote advisory (Exp D reproduction):
  Synthetic STALE_QUOTE response matching x402 facilitator shape
  Helix perceive Tier 1 catches it
  observe strategy records the failure but does NOT auto-fix
  Console surfaces reorder recommendation backed by 932-tx bench data
  Agent's preflight is responsible for applying the workflow reorder
@adrianhihi adrianhihi merged commit 982c88c into main May 26, 2026
4 checks passed
adrianhihi added a commit that referenced this pull request May 26, 2026
…ity analysis

20 real Arc Testnet tx in Group A (idempotencyKey strip).
20 correct holds in Group C (UUID format violation).
Group B revealed refresh_metadata action is design-intent only —
Circle's actual tokenId error shapes route to hold_and_notify
via uuid_format (Rule 2) or catch-all (no errors[] array).
Documented for PR #4 numeric-code routing.
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