From 5277385ee25552f32ab84d3cf3a0c7808d6142f2 Mon Sep 17 00:00:00 2001 From: Sean Goodwin Date: Sat, 24 Oct 2026 11:38:45 -0700 Subject: [PATCH 1/3] feat(gateway): /gateway, a candidate front door: the record, the plan, install, join (MAJOR, draft) A new page, not a replacement for the home page or hero. Kept out of search (robots noindex) until Sean decides whether it becomes the landing page. - The record: seven documented AI failures from 2024-2025, each with its source link, date, a paraphrase from the source and a quote matched word for word against the fetched text (lib/ai-incidents.ts). - The plan, in Sean's voice: HAL, RepID, receipts, x402, testnet and portability, each with a "Today" line true of the shipped code and live engine and a "Not yet" line, following the 2026-10-23 claims audit. - Install: the CLI (Inspect and the sentence check), the npm package and the MCP server, reusing the home page's own install constants, then the six-stage ramp (/agents to /leaderboard). - Join: email plus an optional note into a new gateway_signups table (SQL for Sean in the report). Not waitlist: its insert trigger mails a TrustTrader promotion. Fails closed until the table exists. Tests: tests/gateway-page.test.ts renders the page (20 checks, two mutants caught); tests/e2e/gateway-walk.mjs drives it in Chromium with a stubbed Supabase origin (21/21). Co-Authored-By: Claude Opus 5.5 --- app/gateway/page.tsx | 256 +++++++++++++++++++++++++++++++++ components/gateway-install.tsx | 111 ++++++++++++++ components/gateway-join.tsx | 113 +++++++++++++++ lib/ai-incidents.ts | 128 +++++++++++++++++ package.json | 1 + tests/e2e/gateway-walk.mjs | 173 ++++++++++++++++++++++ tests/gateway-page.test.ts | 160 +++++++++++++++++++++ 7 files changed, 942 insertions(+) create mode 100644 app/gateway/page.tsx create mode 100644 components/gateway-install.tsx create mode 100644 components/gateway-join.tsx create mode 100644 lib/ai-incidents.ts create mode 100644 tests/e2e/gateway-walk.mjs create mode 100644 tests/gateway-page.test.ts diff --git a/app/gateway/page.tsx b/app/gateway/page.tsx new file mode 100644 index 00000000..9ca21df7 --- /dev/null +++ b/app/gateway/page.tsx @@ -0,0 +1,256 @@ +import type { Metadata } from 'next'; +import { AI_INCIDENTS } from '@/lib/ai-incidents'; +import { GatewayInstall } from '@/components/gateway-install'; +import { GatewayJoin } from '@/components/gateway-join'; +import { JourneySteps } from '@/components/journey-steps'; + +const DESCRIPTION = + 'AI is useful and not yet trustworthy: real cases, each with its source. How we are building trust in, piece by piece, what runs today and what is still direction, and how to run it on your own machine.'; + +export const metadata: Metadata = { + title: 'Trust before autonomy — TrustShell', + description: DESCRIPTION, + // A candidate front door, kept out of search until Sean decides whether it replaces the landing page. + robots: { index: false, follow: true }, + openGraph: { title: 'Trust before autonomy — TrustShell', description: DESCRIPTION, type: 'website' }, +}; + +/** + * /gateway: a candidate front door (Sean, 2026-10-24). Four jobs, in order: show that today's AI is + * not yet trustworthy (real cases, lib/ai-incidents.ts), say how we believe trust gets built in, get + * the visitor to install it locally, and let them join. + * + * THE BELIEF IS SEAN'S, THE STATUS LINES ARE THE CODE'S. Each piece pairs the idea with a "Today" line + * that is true of the shipped package and the live engine, and a "Not yet" line for the rest. The + * Today lines follow the README after the 2026-10-23 claims audit (#615, #619, #644): the hosted check + * is two checkers and a second opinion, not proof; reputation that moves with an agent is the aim; + * Carry is built and not released; x402 buying is key-gated; the Inspect record is digested, not + * signed. A piece moves from "Not yet" to "Today" when the code does, not when the copy does. + * + * The two on-chain receipts are the engine's own hero receipt (GET /api/v1/receipts/hero), both + * transactions read back from Base Sepolia on 2026-10-24 with status 1: the USDC transfer to the + * Base Sepolia USDC contract and the write to the ERC-8004 ReputationRegistry 0x8004B663…. + */ +const SETTLEMENT_TX = '0x2a7ac151c23983f59564fc3da5c7ea74fdbe390f9e97fcbf70c79be27089967a'; +const REPUTATION_TX = '0xd362c1b0c819e2e1ee7bce601531afb0be1eef20c1be4ab8dc643e524d19e917'; +const basescan = (tx: string) => `https://sepolia.basescan.org/tx/${tx}`; + +const PIECES: ReadonlyArray<{ id: string; name: string; idea: string; today: React.ReactNode; notYet: string }> = [ + { + id: 'hal', + name: 'HAL, the Hallucination Assessment Layer', + idea: 'AIs fact-check each other, so no single model gets the last word.', + today: + 'Send a sentence and secrets are scrubbed on your device first. Then two AI checkers from different model families read it. Both must agree for Checks out or Caught; anything else is Not checked, never a pass. Two checkers agreeing is a second opinion, not proof.', + notYet: 'More checkers, each weighted by a reputation it has earned.', + }, + { + id: 'repid', + name: 'RepID, reputation that is earned', + idea: 'An agent’s standing comes from what it has done, not from what it says about itself.', + today: + 'Our engine scores agents and writes the score as ERC-8004 feedback on Base Sepolia, where anyone can read it. The scoring code is public. A new agent starts at the bottom tier.', + notYet: 'Reputation that moves with your agent to other platforms. That is the aim, and it is not a property of this release.', + }, + { + id: 'receipts', + name: 'Receipts: provenance and history', + idea: 'Your agent’s work is checked and recorded, so it learns and earns trust before it gets autonomy.', + today: ( + <> + Inspect checks what an agent said about a GitHub Actions run against GitHub's own record. Its record is canonical + JSON with a SHA-256 digest; it is not signed yet. On chain, our own house agents trade with each other: the first + settlement, on 24 May 2026, moved 0.10 test USDC ( + + payment + + ), and the reputation write that followed is on Base Sepolia too ( + + ERC-8004 write + + ). + + ), + notYet: 'Feedback bound to its receipt, its payment, the delivered work and an independent check is not built yet.', + }, + { + id: 'x402', + name: 'x402: agents exchanging value', + idea: 'As your agent proves it keeps the guardrails you set for your Personal AI, it can trade with other agents, and its value grows.', + today: + 'The package refuses a payment that has no policy, or is over the cap the policy states, before anything is signed. The calling code supplies the policy, so this stops a mistaken agent, not one that writes its own. Buying from another agent needs an API key and a funded test wallet, so it is paused for anyone without them.', + notYet: 'Paying only for work that checked out.', + }, + { + id: 'testnet', + name: 'A test network, so nothing real is at risk', + idea: 'Train and test an agent with no money on the line.', + today: + 'Everything on chain here runs on Base Sepolia, a test network, not mainnet. Its tokens are free from a public faucet and worth nothing.', + notYet: 'Mainnet.', + }, + { + id: 'yours', + name: 'Portable, private, yours', + idea: 'Use any model without vendor lock-in, and keep your privacy and your controls.', + today: + 'Inspect’s only network call is to api.github.com. The MCP server runs on your machine inside Claude Desktop, Cursor or Claude Code, and the sentence check works on what any model told you. The code is open source, Apache 2.0.', + notYet: 'Carry, which takes your profile, rules and notes to another machine, is built and not yet released.', + }, +]; + +const H2 = 'text-2xl sm:text-3xl font-bold text-white text-wrap'; +const SECTION = 'px-4 sm:px-6 py-14 border-t border-slate-800'; + +export default function GatewayPage() { + return ( +
+
+
+

Trust before autonomy

+

+ AI is useful. It is not yet trustworthy. +

+

+ It invents policies, cites cases that do not exist, and acts without permission, and it sounds just as sure when + it is wrong. Below: what that has already cost, each case with its source, then how we believe trust gets built + in, and how to run it on your own machine today. +

+

+ + Install it + + + Join us + +

+
+
+ +
+
+

+ It has already happened +

+

+ Seven documented cases from 2024 and 2025. Every detail comes from the linked source, and every quote matches it + word for word. If you find one we got wrong, tell us. +

+
    + {AI_INCIDENTS.map((c) => ( +
  1. +

    + {c.when} · {c.failure} +

    +

    {c.title}

    +

    {c.what}

    +
    “{c.quote}”
    +

    + Source:{' '} + + {c.source.outlet} + + , {c.source.published} +

    +
  2. + ))} +
+
+
+ +
+
+

+ How we believe trust gets built in +

+

+ We believe a safe and ethical AI people can trust is built, not announced. It should be portable, so you can use + any model without vendor lock-in, and it should leave you holding your own privacy and controls. We are building + that trust harness and calling it TrustShell. Here is each piece: the idea, what runs today, and what does not yet. +

+
    + {PIECES.map((p) => ( +
  • +

    {p.name}

    +

    {p.idea}

    +

    + Today + {p.today} +

    +

    + Not yet + {p.notYet} +

    +
  • + ))} +
+

+ Coming soon: TrustMarket.dev and TrustTrader.dev. Neither is part of TrustShell today. +

+
+
+ +
+
+

+ Install it and try it on your own machine +

+

+ A browser demo shows you a result. Running it yourself shows you how it gets there: the command line, the npm + package in your own code, or the MCP server inside the AI app you already use. All three are the free, open-source + package @hyperdag/trustshell. +

+ +
+

Then take an agent through the whole ramp

+

+ Create an agent, claim it with two signatures from your own wallet, fund it from a public faucet, back it with a + deposit, let it trade, and watch its RepID move. No step uses real money: the chain is the Base Sepolia test + network. TrustShell never sends you tokens; a public faucet does. +

+ +
+
+
+ +
+
+

+ Help us build agents people can depend on +

+

+ We are learning, in the open, how to train agents to be dependable and trustworthy, so that together we can build a + safe, ethical and benevolent AGI for human flourishing. Leave your email, tell us what would earn your trust, and + join the conversation. +

+
+ +
+ +
+
+
+ ); +} diff --git a/components/gateway-install.tsx b/components/gateway-install.tsx new file mode 100644 index 00000000..099b9651 --- /dev/null +++ b/components/gateway-install.tsx @@ -0,0 +1,111 @@ +'use client'; + +import { useState } from 'react'; +import { AGENT_TABS, INSTALL, TERMINAL_COMMAND, mcpPaste } from '@/components/home-agent'; + +/** + * /gateway, "install it": the three ways to run TrustShell on your own machine. Every command comes + * from the constants the home page already uses (components/home-agent.tsx), so a version bump there + * moves this page too, and the two cannot disagree. The Inspect line is the README's own first + * command. The SDK lines are the README's usage (`new TrustShell()`, `verifyOutput`). + */ +export const INSPECT_COMMAND = + 'npx @hyperdag/trustshell@latest check https://github.com/OWNER/REPO/actions/runs/1234567890 --claims-file claims.txt'; + +export const SDK_INSTALL = 'npm install @hyperdag/trustshell'; + +export const SDK_SNIPPET = `import { TrustShell } from '@hyperdag/trustshell'; + +const shell = new TrustShell(); // no key needed for a check +const result = await shell.verifyOutput('The Eiffel Tower is located in Rome, Italy.'); +console.log(result.verdict, result.evidence);`; + +const CODE = + 'max-w-full min-w-0 overflow-x-auto whitespace-pre-wrap break-all rounded-xl border border-slate-800 bg-slate-950 p-4 font-mono text-xs text-indigo-200'; + +function Copyable({ text, label }: { text: string; label: string }) { + const [copied, setCopied] = useState(false); + // A person's click only; the text goes to their own clipboard and nowhere else. + async function copy() { + try { + await navigator.clipboard.writeText(text); + setCopied(true); + } catch { + setCopied(false); + } + } + return ( +
+
+        {text}
+      
+

+ + + {copied ? 'Copied.' : ''} + +

+
+ ); +} + +export function GatewayInstall() { + return ( +
+
+

1. The command line

+

+ Check what your AI agent said about a public GitHub Actions run against GitHub's own record. Its only network + call is to api.github.com: no account, no key, nothing uploaded. Put your agent's words in{' '} + claims.txt, one plain sentence per paragraph, and cite the run id. +

+ +

+ Or check one sentence an AI told you. This one leaves your machine: secrets are scrubbed on your device first, then + the sentence goes to our hosted checkers. +

+ +

To keep the commands installed:

+ +

+ Needs Node 22.13 or newer. New to it? The five-minute Inspect challenge{' '} + walks you through one true and one false claim. +

+
+ +
+

2. The npm package, in your own code

+

+ The same checks from JavaScript or TypeScript. The verdict is PASS,{' '} + FLAG, VETO or{' '} + NOT_CHECKED, and NOT_CHECKED is never a pass. +

+ + +

+ Reference: API reference and the{' '} + package on npm. +

+
+ +
+

3. The MCP server, inside the AI app you already use

+

Paste this block into your app's MCP settings file and restart the app.

+
    + {AGENT_TABS.map((tab) => ( +
  • + {tab.label}: {tab.where} +
  • + ))} +
+ +
+
+ ); +} diff --git a/components/gateway-join.tsx b/components/gateway-join.tsx new file mode 100644 index 00000000..fd469351 --- /dev/null +++ b/components/gateway-join.tsx @@ -0,0 +1,113 @@ +'use client'; + +import { useState } from 'react'; +import { createClient } from '@/lib/supabase'; + +/** + * /gateway, "join us": an email and an optional note, saved to its own table. + * + * NOT `waitlist`. Every insert into `waitlist` fires two triggers [MEASURED 2026-10-24, pg_trigger]: + * `on_waitlist_insert` mails the address a TrustTrader welcome ("0% vs 49.63% without veto", "$499/mo + * value", from hello@trusttrader.dev), and `trg_notify_new_signup` posts the address to Telegram. A + * page about trust cannot answer a signup with claims nobody has checked, so the gateway writes to + * `gateway_signups`, which has no triggers. Its SQL is in E:\dev\reports\2026-10-24\GATEWAY_PAGE.md for + * Sean to apply (DDL is his). Until it exists the insert fails and the form says so: nothing saved, + * here is GitHub instead. A failure is never shown as a success. + * + * Browser insert with the publishable key, the pattern BuilderWaitlist used against `waitlist` in + * production (rows with source trustshell.dev/builder-form, 2026-09). The anon role gets INSERT only. + */ +export const SIGNUP_TABLE = 'gateway_signups'; +export const SIGNUP_SOURCE = 'trustshell.dev/gateway'; +export const MAX_NOTE = 1000; +const EMAIL_RE = /^[^@\s]+@[^@\s]+\.[^@\s]+$/; + +type Status = 'idle' | 'sending' | 'saved' | 'failed'; + +const FIELD = + 'w-full min-h-11 rounded-lg border border-slate-700 bg-slate-950 px-3 py-2 text-white placeholder:text-slate-500 focus:outline-none focus:ring-2 focus:ring-amber-500/60'; + +export function GatewayJoin() { + const [email, setEmail] = useState(''); + const [note, setNote] = useState(''); + const [status, setStatus] = useState('idle'); + + async function submit(e: React.FormEvent) { + e.preventDefault(); + if (!EMAIL_RE.test(email.trim())) return; + setStatus('sending'); + try { + const { error } = await createClient() + .from(SIGNUP_TABLE) + .insert({ email: email.trim(), note: note.trim() || null, source: SIGNUP_SOURCE }); + setStatus(error ? 'failed' : 'saved'); + } catch { + // No key in this build, or the request never left: still a failure, never a success. + setStatus('failed'); + } + } + + if (status === 'saved') { + return ( +

+ Saved. Thank you. Nothing is emailed to you automatically; we will write when there is something worth your time. +

+ ); + } + + return ( +
+
+ + setEmail(e.target.value)} + className={FIELD} + placeholder="you@example.com" + /> +
+
+ +