docs(uniswap): R19 Task B — Universal Router upstream PR opened (Uniswap/universal-router#477) - #448
Conversation
…dence Upstream PR opened at Uniswap/universal-router#477 ("examples: policy-guarded swap pattern for autonomous agents (SBO3L reference)"). What the upstream PR contributes: - examples/policy-guarded-swap/README.md — pattern explanation, executor_evidence JSON shape, counterfactual analysis - examples/policy-guarded-swap/PolicyGuardedRouter.sol — illustrative on-chain wrapper (~200 LOC) showing how a policy-engine signed receipt gates a forwarded UR.execute call What this PR adds in the SBO3L repo: - docs/proof/uniswap-universal-router-pr.md — judge evidence pointing at upstream PR #477. Captures the reference impl pointer, ENSIP-26 composition, and discussion-thread note. Per-command policy gating prevents the canonical "swap-only gate misses appended SWEEP" attack on autonomous agent multicalls. SBO3L's full Rust impl at crates/sbo3l-execution/src/uniswap_router.rs is the working reference. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1de062fd24
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| trait (shared with `UniswapExecutor` for single-leg swaps). | ||
| - Evidence emitted as canonical JSON, signed Ed25519, anchored to | ||
| the agent's audit chain (commitment in the ENS `audit_root` | ||
| text record per [ENSIP-26](ensip-upstream-pr.md)). |
There was a problem hiding this comment.
Replace dead ENSIP link target
The markdown link points to ensip-upstream-pr.md, but that file does not exist in this repo (the ENSIP upstream document currently lives at docs/submission/ensip-upstream-submission.md), so readers following this evidence chain hit a dead link instead of the referenced proof. Because this file is explicitly for judge-verifiable evidence, the broken pointer undermines the verification flow and should be updated to an existing path or URL.
Useful? React with 👍 / 👎.
) * fix(docs): apps/docs build complete + Vercel deploy + Cmd+K target Closes loop on PR #437. Two remaining build errors fixed; live deploy shipped to https://sbo3l-docs.vercel.app/. ### 1. "Cannot read properties of undefined (reading 'map')" Root cause: `VersionSelectorWrapper.astro` (the Starlight `Sidebar` component override) wrapped the default sidebar without forwarding `Astro.props`. Default sidebar's `Astro.props.sidebar` was undefined, so `SidebarSublist`'s `sublist.map(...)` crashed every rendered docs page during static generation. Fix: spread props explicitly: `<Default {...Astro.props}><slot /></Default>`. ### 2. "/api conflicts with /[...slug]" Root cause: Starlight content-collection stub at `src/content/docs/api/index.mdx` resolved to `/api`, colliding with the standalone Redoc page at `src/pages/api.astro`. The .astro page won (correctly), but Astro emitted a build warning every run. Fix: delete the stub; the Redoc page is the actual API surface. Sidebar entry `{ label: "API reference", link: "/api" }` still routes correctly because Astro resolves it to the .astro page. ### 3. Vercel-friendly prebuild script `scripts/copy-openapi.sh` used `git rev-parse --show-toplevel` to find `crates/sbo3l-server/openapi.yaml`. On Vercel's build container there is no `.git` directory, so the script exited 128 and bricked the deploy. Added a graceful fallback: try `git rev-parse` first; on failure walk up from the script's own dir; if neither path locates the upstream spec but `public/openapi.yaml` already exists (e.g. via `vercel build` running locally), proceed with the existing snapshot. ### Deploy Project `sbo3l-docs` (prj_hHoNf5CiV1uCB7vfY8AAbV6Z5F0l) created under `babjak-daniel-5461s-projects`. Deployed via: cd apps/docs vercel build --prod # uses local git, copies upstream openapi.yaml vercel deploy --prebuilt --prod # uploads .vercel/output as-is Live verification: - https://sbo3l-docs.vercel.app/ HTTP 200, "SBO3L Documentation" - https://sbo3l-docs.vercel.app/quickstart HTTP 200, Starlight render - https://sbo3l-docs.vercel.app/api HTTP 200, Redoc bundle - https://sbo3l-docs.vercel.app/openapi.yaml HTTP 200, raw spec 35 pages built (every Starlight content entry + the Redoc page). Pagefind search index built (33 indexed, 2317 words). Sitemap generated. ### 4. Cmd+K target on marketing Updated `apps/marketing/src/components/Nav.astro::docsUrl` from the GitHub `/docs` tree fallback to `https://sbo3l-docs.vercel.app/`. The marketing site's Cmd+K shortcut now opens the live docs site (with built-in Pagefind search) instead of GitHub's tree view. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(kh-a5): R19 Task D — KeeperHub protocol upstream PR opened (KeeperHub/cli#57) (#449) Upstream PR opened at KeeperHub/cli#57 ("docs: propose policy-receipt envelope fields for upstream-proof workflow submits (SBO3L reference)"). Proposes 6 OPTIONAL `sbo3l_*`-prefixed fields on workflow webhook submit envelope (sbo3l_policy_hash, sbo3l_audit_root, sbo3l_pubkey_ed25519, sbo3l_receipt, sbo3l_capsule_uri, sbo3l_evidence_chain_position) so agents can attach signed trust-receipts to every workflow execution. Composition with existing 5-issue track ======================================== KH issues #52-#56 are the OPERATIONAL ergonomics track (HTTP error codes, mock fixtures, timeout SLO, schema versioning, payload size). The new #57 is the PROTOCOL track — different layer, complementary not redundant. The issues + companion SBO3L reference PRs (#402-#406) show consumer-side adapter changes that land once each KH issue ships. The new proposal is the protocol-level ask that sbo3l-keeperhub-adapter v1.2.0 already implements; canonicalising it upstream means the rest of the agentic-DeFi ecosystem can converge. Comms posture ============= Luca (KH team) said "Happy final sprint" → going dark for engineering Qs. This PR is open-loop public evidence; no expectation of pre-merge feedback. The upstream URL is what matters for the bounty submission. Per memory `competitor_intel_2026-05-03.md`. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(marketing): mobile rendering — table scroll-wrap + tap targets + PassportCapsule scaling (R20 Task A) (#439) Pre-empt Heidi UAT mobile test on iPhone SE (375×667) + iPad (768×1024). Code-side audit of the four pages most likely to fail. global.css — tap-target floor .btn now `display: inline-flex` + `min-height: 44px` so every primary/ghost button hits WCAG 2.5.5 enhanced target size at any viewport. Padding unchanged on desktop (the min-height only kicks in if computed height would otherwise be <44px). status.astro — table horizontal scroll Each truth-table section now wraps its <table> in a `<div class="table-wrap" role="region" aria-label="..." tabindex="0">`. Outer container gets overflow-x: auto + a right-edge scroll-shadow gradient hint so iPhone SE doesn't horizontally scroll the entire page; only the table scrolls within its container. tabindex=0 makes the scroll region keyboard-reachable; role=region + aria-label make it screen-reader-discoverable. Inner table preserves its full width (760px desktop, 640px below 720px) so cells with prose don't squeeze unreadably. proof.astro — PassportCapsule scaling PR #420 mounted the open spread with explicit width=760, which renders >viewport on phones. Wrapped in a `.passport-frame` that constrains to 100% of the column; the SVG's viewBox + preserveAspectRatio scales it down. !important on the inner svg rule overrides the inline width attribute the component sets. Verified: pnpm --filter @sbo3l/marketing build → 47 pages, clean. What's NOT in this PR (rationale): /roadmap stacks 3-col → 1 at 1100px (already correct) /kh-fleet stacks 5-col grid → 1 at 900px (already correct); .exec-id has word-break: break-all (long ULIDs wrap) Nav ⌘K pill hidden at 640px already /demo step 1 artifact-side panel stacks at 640px already Tap targets on links inside truth-table cells are inline text; WCAG exemption applies to inline text per 2.5.5 §exception. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(ens): R19 Task A — ENSIP-26 upstream submitted to ensdomains/ensips (#440) Upstream PR opened at ensdomains/ensips#71 ("ENSIP-26: Agent Identity Records for Autonomous Agent Discovery"). What this PR adds in the SBO3L repo: - docs/proof/ensip-upstream-pr.md — judge-clickable evidence pointing at upstream PR #71. Captures the reciprocal link, the upstream branch, and reproducibility commands. - docs/submission/bounty-ens-most-creative-final.md — adds an R19 row to the deliverables table referencing the upstream PR. Live status: OPEN upstream. What ENSIP-26 specifies upstream: Seven standardised text-record keys (agent_id, endpoint, pubkey_ed25519, policy_hash, audit_root, capability, reputation_score) so any ENS-aware client reads agent metadata with zero bespoke decoders. 363 LOC, draft frontmatter template-conformant with the ensips repo style. Composes with ENSIP-25 (verification) and ERC-8004 (on-chain registry) — no overlap, different consumer shapes. Upstream branch: B2JK-Industry/ensips:ensip-26-agent-identity-records Reference impl: this SBO3L repo (60-agent fleet, mainnet apex sbo3lagent.eth, deployed Sepolia OffchainResolver). Why this matters: Dhaiwat (ENS contact) confirmed late entrants accepted ("you still have time"). The upstream submission is a judge-clickable evidence artifact moving the ENS Most Creative track from "we built a thing on ENS" to "we contributed a spec to ENS that the broader ecosystem can adopt." Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(examples): 5 polished langchain-keeperhub demos (KH-D follow-up) (#441) Bundles 5 focused, one-file Python demos under examples/langchain-keeperhub-demos/ showing distinct shapes of the SBO3L → KeeperHub policy gate. Goal: a judge or eval reader opens the dir, sees 6 distinct usage patterns, immediately understands 'real framework integration, not a one-off demo.' Per-file pattern (each ~70-140 LOC, runnable against mock-mode daemon): simple-keepalive.py — minimum viable: one APRP → SBO3L decide → kh_execution_ref. Bare floor. multi-step-research.py — chain 3 KH workflows under one shared budget. Step 3 denied as budget-exhausted before KH ever runs. cross-agent-attestation.py — agent A delegates to agent B via audit_event_id reference. Distinct receipts; chain visible in B's metadata. retry-with-backoff.py — wrapper retries SBO3L transport.* errors with jittered exp backoff. Deny envelopes pass through without retrying (policy decision, not transport — re-trying burns nonces). observability.py — each tool call emits an OTel span carrying SBO3L's audit_event_id + kh_execution_ref + deny_code as indexed attributes. Console exporter fallback when OTEL_EXPORTER_OTLP_ENDPOINT not set. README.md cross-references all 5 + Devendra's package + the underlying kh-py adapter. Common prereqs documented once at the top of the README; each demo's docstring lists its own extras (e.g. observability.py needs opentelemetry-api/sdk/exporter-otlp-proto-http). Test plan: All 5 files pass python3 -c 'import ast; ast.parse(...)' syntax check. No imports beyond what's shipped in sbo3l-sdk + sbo3l-langchain-keeperhub + (optional) opentelemetry. No new dependencies in the repo's package graph (each demo's deps are pip-installable in the demo's own venv). * fix(marketing): a11y WCAG 2.1 AA compliance (R20 Task B) (#442) Code-side a11y audit of recent components. Three real issues caught, plus one defensive aria-current addition. WCAG 1.4.3 contrast violation — /status .cell.empty (P1) `.cell.empty { color: var(--border) }` rendered the "—" placeholder in `var(--border) #2a2a3a` on `var(--bg) #0a0a0f`. Computed contrast ratio: ~2.3:1. Fails the 4.5:1 minimum for normal text. The "—" carries semantic meaning ("no entry in this column") so it must pass AA. Switched to `var(--muted) #9999a8` (~7.5:1, AAA) with opacity 0.55 to keep the visual de-emphasis without dropping contrast. The empty-cell cells are present in every truth-table row across all sections. WCAG 2.4.7 focus-visible — ZeroGUploader (P2) `.zg-drop:hover, .zg-drop:focus { outline: none }` killed the keyboard focus ring AND the hover outline simultaneously. Mouse hover gets `border-color: var(--accent)` as substitute, but keyboard tab landed with no visible ring (border alone isn't reliable for users with reduced color sensitivity). Restored 2px accent outline on `:focus-visible` so keyboard tabs ring; mouse clicks stay quiet via the `:focus-visible` selector matching only keyboard-derived focus. WCAG 2.4.8 location — Nav aria-current (defensive) Added server-side `aria-current="page"` to whichever nav link matches the current route (computed from `Astro.url.pathname`). Screen readers now announce "current page, link, Status" instead of "link, Status" when the user is on /status. Visual: same link gets accent color + bottom border so sighted users see the same hint. What I checked + didn't change (clean): - Color contrast on accent (#4ad6a7) vs bg/code-bg/fg/muted — all ≥ AA across the dark theme palette. - All <img> tags have alt text (3 in /demo, plus dynamic ones on the index card grid). - All form inputs have <label> wrappers or aria-label. - All decorative SVGs (Cinematic scenes, KeyFlowDiagram membrane lines) carry aria-hidden="true"; meaningful SVGs have role="img" + <title> + <desc>. - prefers-reduced-motion is honored on Cinematic + KeyFlow + Hero. - Skip-link works (existing in BaseLayout, focusable on Tab). - Cmd+K shortcut works without mouse — already keyboard-only by construction. Build: 47 pages, clean. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(uat): final comprehensive pre-submit UAT — 0 P0, 1 P1 outstanding, ready (#443) Comprehensive 8-round UAT per Daniel's pre-submit brief. Treated as a first-time judge with zero prior context. Method: headless agent — curl + cargo + cast + node + pip; no browser. Browser-only checks formally DELEGATED to Daniel hands-on. Findings: ✅ 16/16 marketing routes HTTP 200 (14 fast, 2 slow) ✅ 7/7 sponsor sub-pages HTTP 200 + link-clean (3 false-positive SPA-blocked URLs verified via API) ✅ /playground 8 scenarios; /playground-api healthz ok ✅ /proof WASM 2.4MB binary serves correctly (drag-drop DELEGATED) ✅ cargo install + npm install + sbo3l doctor PASS ✅ Mainnet sbo3lagent.eth: 5 records, verdict PASS ✅ 7/7 Sepolia contracts deployed + bytecode-verified ✅ /sitemap-0.xml has 47 URLs (matches brief) ✅ All repo hygiene files present (LICENSE/SECURITY/AI_USAGE/CHANGELOG/ README/SUBMISSION_FORM_DRAFT) ✅ Live counts: 10 crates + 5 PyPI + 14 npm at 1.2.0 🟡 P1 #1: /playground/live UI implies live behavior; backend /api/v1/audit/chain returns SKELETON {"status":"skeleton","todo":"wire Postgres + anchor join"}. Recommend a 🚧 banner OR redirect. 🟡 P1 #2: old OR address 0x7c6913…A8c3 leaks in 5 user-facing doc mentions across docs/submission/{READY,HANDOFF-FOR-DANIEL, live-url-inventory}.md. **Fixed in this PR** — bulk-replaced with new 0x87e99508C222…b1F6. 🟢 P2 #3: /trust-dns-story is a "coming soon" stub 🟢 P2 #4: /playground/live load time 3.82s (over 3s threshold) 🟢 P2 #5: "943/943 tests" claim from brief not in user-facing docs 🟢 P3 #6: /trust-dns-story load 2.10s (close to threshold) Verdict: 🟢 SUBMIT-READY. 0 P0. Daniel can submit after: (1) Acknowledging or fixing the Tier 3 truthfulness P1 (5 min); (2) The 6-step HANDOFF-FOR-DANIEL hands-on rehearsal; (3) Optionally completing the 10 browser-only spot-checks listed in the doc. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(0g-uploader): 6 edge case improvements + Playwright e2e spec (#445) R20 batch B follow-up to PR #399. Three of the six edge cases (#1-3 non-JSON / empty / not-a-capsule input handling) were already covered; the remaining three (#4 localStorage quota, #5 popup blocked, #6 mobile copy swap) are new code. ## Code changes apps/marketing/src/components/ZeroGUploader.astro: - drop zone copy now has dual desktop/mobile spans; @media (pointer: coarse) swaps which is visible. 'Drag a capsule' on desktop becomes 'Tap to pick a capsule' on touch primary devices. - fallback panel reveals .zg-popup-blocked-warning element with 'Heads up' inline guidance when window.open returns null/blocked. - success panel reveals .zg-quota-warning when localStorage write fails; the rootHash itself stays valid + visible. - new <details class='zg-recent'> section renders the recently-uploaded list (last 5 rootHashes) hydrated from localStorage at first paint + after each successful upload. Includes 'Clear history' button. - CSS rules for: .zg-popup-blocked-warning, .zg-quota-warning, .zg-recent (+ list, +clear), and the @media pointer: coarse swap. apps/marketing/src/lib/zerog-uploader.mjs: - new exports: persistRecent, readRecent, clearRecent, isPopupBlocked - new constants: RECENT_STORAGE_KEY, RECENT_HISTORY_LIMIT - persistRecent returns structured {ok, reason} so caller can branch on quota / unavailable / format - readRecent + persistRecent both filter malformed entries defensively (recovers gracefully from corrupt JSON in storage) apps/marketing/public/zerog-uploader-runtime.js: - duplicates persistAndRenderRecent + safeReadRecent + safeWriteRecent inline (CSP forbids module imports from this static script — same pattern as the existing pure helpers; sister test suite locks both implementations to the same contract) - handleUpload() now detects popup-blocked from window.open's return: null OR closed=true synchronously → reveal the inline warning; cross-origin closed-access throws → popup DID open, don't flag - on showSuccess: persists rootHash to recent list + renders or shows quota warning if localStorage write fails ## Tests apps/marketing/src/lib/zerog-uploader.test.mjs: - 16 new test cases under node --test covering all 6 edge cases - localStorage stub with throwOnSet flag for QuotaExceededError simulation - cross-origin window stub for popup-blocked detection - de-dup + LRU cap + corrupt JSON recovery all locked - 26 → 42 tests; 0 failures apps/marketing/tests/e2e/zerog-uploader.spec.ts: - 7 Playwright specs covering all 6 edge cases + happy path sanity - Spec is NOT wired into CI (would add ~700MB Chromium dep) - tests/e2e/README.md documents the local-run procedure + when to promote to a separate workflow if real-browser regressions appear ## Test plan apps/marketing && npm test → 42/42 ✓ (was 26) apps/marketing && npm run typecheck → unchanged 2 pre-existing errors (CapsulePlayground, getEntry); 0 new errors apps/marketing && npm run build → 47 pages in 4.32s ✓ rendered HTML inspection → all new elements (.zg-popup-blocked-warning, .zg-quota-warning, .zg-recent, .zg-drop-prompt-mobile) present in dist/try.html No new package.json deps. No CI changes. * docs(uniswap): R19 Task B — Universal Router upstream PR opened + evidence (#448) Upstream PR opened at Uniswap/universal-router#477 ("examples: policy-guarded swap pattern for autonomous agents (SBO3L reference)"). What the upstream PR contributes: - examples/policy-guarded-swap/README.md — pattern explanation, executor_evidence JSON shape, counterfactual analysis - examples/policy-guarded-swap/PolicyGuardedRouter.sol — illustrative on-chain wrapper (~200 LOC) showing how a policy-engine signed receipt gates a forwarded UR.execute call What this PR adds in the SBO3L repo: - docs/proof/uniswap-universal-router-pr.md — judge evidence pointing at upstream PR #477. Captures the reference impl pointer, ENSIP-26 composition, and discussion-thread note. Per-command policy gating prevents the canonical "swap-only gate misses appended SWEEP" attack on autonomous agent multicalls. SBO3L's full Rust impl at crates/sbo3l-execution/src/uniswap_router.rs is the working reference. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(cli): verify-ens follows CCIP-Read OffchainLookup (loop-7 UAT) (#446) Heidi's UAT loop iteration 7 caught: `sbo3l agent verify-ens` was calling `text(node, key)` directly on the resolver address, which reverts with EIP-3668 `OffchainLookup` for ENSIP-10 resolvers (the SBO3L Sepolia OffchainResolver lineage). The CLI then surfaced "RPC reported error: 3 execution reverted" — the only ENSIP-10 client that couldn't read SBO3L's own published records, even though viem / ethers / the ENS App handle it transparently. This commit teaches `LiveEnsResolver::resolve_raw_text` the full EIP-3668 dance: - New `RpcError::Reverted { data: Vec<u8> }` variant captures the Solidity revert payload from the JSON-RPC `error.data` field. `ReqwestTransport` populates it for both geth-shape (hex string) and Alchemy-shape (`{ "data": "0x..." }`) error envelopes. - New `JsonRpcTransport::http_get` method (default impl errors out) for fetching gateway URLs without coupling tests to mockito. - `LiveEnsResolver` now dispatches on `supportsInterface(0x9061b923)`: * ENSIP-10 -> `resolve(dnsEncode(name), text(node,key))` and follow `OffchainLookup` revert via the gateway round-trip. * Legacy -> direct `text(node, key)` (PublicResolver path unchanged for mainnet `sbo3lagent.eth`). - `find_resolver` walks parent names if the leaf has no direct registry entry — covers the ENSIP-10 wildcard pattern that some OffchainResolver deployments rely on. - New `ccip_read::follow_offchain_lookup` orchestrates: substitute `{sender}`/`{data}` in URL template, GET (try fallback URLs on 4xx), parse `{data, ttl}`, build `callbackSelector || abi.encode(response, extraData)`, eth_call the resolver, decode the inner `(bytes)` -> `(string)` tuple. Trust root is on-chain: `resolveCallback` verifies the gateway signature itself; we don't re-implement signature verification in Rust. - `UniversalResolver` also detects `Reverted` (in addition to its existing `Server { message }` string-match fallback) so the fast-path doesn't regress when an RPC properly surfaces the revert payload. Tests: - 5 new unit tests in `ccip_read.rs` (URL substitution, callback encoding/offsets, single-bytes tuple round-trip). - 3 new unit tests in `ens_live.rs`: * `resolve_raw_text_follows_offchain_lookup_via_ensip10` — end-to-end mock of the full 5-step CCIP-Read flow. * `resolve_raw_text_legacy_text_path_when_resolver_not_ensip10` — regression cover for the PublicResolver path. * `find_resolver_walks_parents_when_leaf_has_no_entry`. - 2 new live integration tests in `tests/ccip_read_sepolia_live.rs` gated by `SBO3L_SEPOLIA_RPC_URL`. Verified locally against `research-agent.sbo3lagent.eth` -> "research-agent-01" via Alchemy Sepolia + `sbo3l-ccip.vercel.app` gateway. Matches viem byte-for- byte. CLI live smoke: $ SBO3L_ENS_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/... \ sbo3l agent verify-ens research-agent.sbo3lagent.eth \ --network sepolia verify-ens: research-agent.sbo3lagent.eth (network: sepolia) --- - sbo3l:agent_id actual="research-agent-01" - sbo3l:endpoint actual="https://app.sbo3l.dev/v1" - sbo3l:policy_hash actual="e044f13c5acb..." ... verdict: PASS Gates: cargo test -p sbo3l-cli -p sbo3l-identity (215 + 188 lib tests pass; live tests skip cleanly without the env var) / cargo clippy --all-targets -D warnings / cargo fmt --check. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
R19 Task B delivered. Universal Router policy-guarded swap pattern opened as upstream PR at Uniswap/universal-router#477.
What landed upstream
In the B2JK-Industry/universal-router fork branch
examples-policy-guarded-swap:examples/policy-guarded-swap/README.mdexamples/policy-guarded-swap/PolicyGuardedRouter.solWhat lands in this PR (SBO3L repo)
docs/proof/uniswap-universal-router-pr.md— judge evidence pointing at upstream PR feat(kh-plugin): @sbo3l/elizaos-keeperhub — ElizaOS policy-guarded KH executor (R22-C) #477.Why this matters
Most autonomous-agent / agentic DeFi implementations today either sign opaque multicalls, implement bespoke pre-flight checks, or skip policy entirely. Per-command pattern + reference impl in the Universal Router repo means the community can converge on a consistent policy-boundary shape.
Reference implementation context
SBO3L's full Rust implementation at
crates/sbo3l-execution/src/uniswap_router.rsdecodes UR multicalls into aVec<UniversalRouterCommand>enum, runs the policy engine per-command, and emits canonicalexecutor_evidenceJSON. Composes with ENSIP-26 for the audit-anchor commitment.🤖 Generated with Claude Code