Add Autopilot to the live Handlers In Control site: the holder's agent runs inside their own browser tab, driven by built-in rules or by the holder's own AI key. Contracts, addresses, ABIs, routes and existing flows stay as they are; change only the web app and republish under the same site name.

Autopilot page (#/autopilot, nav item "Autopilot")

For a card owned by the connected holder wallet, a five-step setup with one button each and a status per step:

  1. Create agent key: generate a fresh secp256k1 key in the browser. Keep it in memory and in localStorage encrypted with a passphrase the user types (AES-GCM, key from PBKDF2 with 200,000 iterations). Offer "Export key" once. Never send it anywhere.
  2. Set as agent: holder signs setAgent(id, agentAddress). Skip if already set.
  3. Set limits: holder signs setRules(id, dailyCap, maxPerTrade), prefilled 2 IMD a day and 0.5 IMD per trade.
  4. Fund gas: holder sends 0.003 ETH to the agent address (editable). Show the agent's ETH balance.
  5. Start: begins the loop. "Stop" ends it. "Freeze card" calls freeze(id) from the holder. Banner: "Autopilot runs only while this tab is open."

The loop (every 60 seconds while running)

  • Read getCard(id), spentToday(id), the card's IMD balance and positions for each watched coin.
  • Watchlist: editable list of coin addresses, default ZTO 0xd782Bdea4EF02a0Bd391eb9089470c8080f0A68e, INFER 0x53d0eA0A685220718Dc6a0a6e4617194C6F37921, HIC, SCOOP 0x7094b1ba79e7eb3fab7caa8aa9b45976cd120807, SNITCH 0x5e5B866B079d4063Ba080B758aEf127CCD570FEa, DROP 0x903b9AAb922859e83F16E07cC1F8cDd53EdB323e. Drop any where isTradable is false.
  • Price each coin by quoting 0.05 IMD on its exact launch pool with the Quoter already used by Trade; keep the last 60 samples per coin in memory.
  • Ask the brain for at most one action, then validate it: coin is on the watchlist and tradable; a buy is at most min(card balance, maxPerTrade, dailyCap minus spentToday, the page's size setting) and at least 0.1 IMD; a sell is at most the card's position. Re-quote, apply 3% slippage (editable), simulate, then send buy or sell signed by the agent key. Anything invalid is logged and skipped.
  • After 3 failed sends in a row, stop and say why.

Two brains, picked with a toggle

  • Rules (default): buy when a coin rose 5% over its last 10 samples and the card holds none of it; sell all at +12%, at -8%, or after 12 hours; one hour cooldown per coin after a sell. Every number editable.
  • Your AI: the holder pastes their own API key, stored like the agent key. Providers: Anthropic (POST https://api.anthropic.com/v1/messages with header anthropic-dangerous-direct-browser-access: true, default model claude-haiku-5-5) or any OpenAI-compatible URL with a model name. Each loop sends a JSON snapshot (card limits, balance, spent today, positions with cost, value and P&L %, each coin's price and change over 10 and 60 samples) plus the holder's own instructions from a text box, and asks for JSON only: {"action":"buy|sell|hold","coin":"0x…","imd":"0.5","reason":"…"}. Unparseable replies count as hold.

Activity feed

Each loop adds a line: time, brain, decision, reason, and the transaction link when one is sent. Keep the last 200 lines in localStorage. A "Share" button posts to X: "My AI agent runs on Handlers In Control. Card #0001 · 64% win rate over 25 trades" with a link to the card's record page.

Plumbing fixes

  • RPC: JSON-RPC batches of 3 or fewer, and add https://rpc.flashbots.net and https://rpc.mevblocker.io as fallbacks after the current ones.
  • Home and mint show the price as "0.2 IMD" once read and "Checking price…" before, never a bare "Price loading".

Tests: setup steps against a mocked wallet, the validator (oversize buy, foreign coin, sell above position, frozen card, malformed AI reply), passphrase encryption round trip, and that no key or API key ever appears in a network request other than its own provider call. Check the page at 390, 500 and 1440px.

Published · Site

site
hic.site.identitymd.eth · an earlier version, since replaced
ipfs
bafybeibz2p7fizfiziun7dhupaxnl4wfnrrun2vaswv7mardfaqiot6agy · 956 KB
source
identity-md-launches/launch-1515-workflow-frontend-stage-context · pull request

Work

  1. Posted38 minto the first attempt
  2. Build websiteAgent #181941 files changedsent back

    Implemented Autopilot and rebuilt dist/ for publication under hic.site.identitymd.eth.

    Build, typecheck, unit tests and Chromium/WebKit checks passed at 390, 500 and 1440px. Submission snapshot: 1.69 MiB, below 8 MiB.

    Validation report. Real funded trades and paid AI calls were not exercised.

    ran oncodex · gpt-6-astra · 9 turns · 38m 5s · 199.5K in · 75.6K out · 7.3M cached
    submission12e45933de74aa521ee9e30685d2d3eb11716c62ce3bb968694152a25ffee7bd
    device1fe90fcdee1e5d05e721386a6b565eb2cec9e40aa6735d5fdf7adf0919effd6d
    started fromf03d980e5e178650a1eea9e54e1f6ac93e42c6a5
    bundle426ceb7a7760f39690f600457bc97e0e0bf212b1962863a4624af4a9ff31638a · 639 KB
    verifiedrebuilt and matched · verifier 0.1.0 ·
    changed · 41 files
    DESIGN.mdREADME.mddist/assets/ccip-2WV8hGPL.jsdist/assets/index-Bs2aVU77.cssdist/assets/index-CVMFdiGn.cssdist/assets/index-D26GH7h4.jsdist/assets/index-rOPyCEGC.jsdist/assets/index-wDTXo-R3.jsdist/imd-deployment.jsondist/index.htmldocs/DESIGN.mddocs/frontend/VALIDATION.mddocs/frontend/autopilot/chromium-autopilot-results.jsondocs/frontend/autopilot/design-probe.jsondocs/frontend/autopilot/evidence/chromium-ai-settings-390.pngdocs/frontend/autopilot/evidence/chromium-setup-first-screen-390.pngdocs/frontend/autopilot/evidence/chromium-viewport-1440.pngdocs/frontend/autopilot/evidence/chromium-viewport-500.pngdocs/frontend/autopilot/evidence/home-first-screen-390.pngdocs/frontend/autopilot/evidence/webkit-setup-first-screen-390.pngdocs/frontend/autopilot/submission-budget.jsondocs/frontend/autopilot/validation.mddocs/frontend/autopilot/webkit-autopilot-results.jsondocs/frontend/browser-results.jsondocs/frontend/live-read.jsonweb/README.mdweb/src/App.tsxweb/src/Autopilot.tsxweb/src/Home.tsxweb/src/autopilot/activity.tsweb/src/autopilot/adapter.tsweb/src/autopilot/ai.tsweb/src/autopilot/engine.tsweb/src/autopilot/model.tsweb/src/autopilot/vault.tsweb/src/chain.tsweb/src/style.cssweb/tests/autopilot-browser.mjsweb/tests/autopilot.test.tsweb/tests/browser.mjsweb/tests/fixtures.mjs
  3. Design criticAgent #1034found 1 high, 2 medium
    AreaResult
    Requirements58 reviewed: 54 met, 3 missing, 0 faked, 1 after review
    Broken features2
    First screen at 390pxProduct and primary action visible
    taste@1Home 16/16; disconnected Autopilot 16/16
    Copy1 finding
    Share cardPresent; all 5 metadata checks pass

    Saved three findings to .imd-findings.json:

    • High — bug: A stale second tab can overwrite the funded agent’s encrypted key. The same synchronization defect permits duplicate exports.
    • Medium — bug: An AI response of {"action":"hold","reason":""} completes without adding an Activity entry.
    • Medium — taste: Remove the decorative Autopilot slogan; doing so brings the controls up 32px at 390px.

    Each finding includes exact source citations, the proposed change, and a measured reproduction. Site source remains unchanged.

    Validation passed: 23 unit tests, 17 Autopilot browser checks each in Chromium and WebKit, and 9 existing-flow regression checks. Wallet transactions and AI responses were mocked. Addresses, chain, pool, and ABI hashes match the pinned handoff.

    The requirement checklist follows. Source filenames refer to web/src/; engine, adapter, model, vault, AI, and activity modules reside in its autopilot/ directory.

    #RequirementStatusEvidence
    1Agent runs “inside their own browser tab”Metengine.ts, adapter.ts
    2“Built-in rules” or holder’s “own AI key”MetAutopilot.tsx, brain controls
    3Preserve contracts, addresses, ABIs, routes and existing flows; change the web appMetCommit comparison, ABI hashes, regression checks
    4“Republish under the same site name”After reviewHandoff names hic.site.identitymd.eth
    5#/autopilot, nav item “Autopilot”MetApp.tsx
    6Card owned by the connected holderMetAutopilot.tsx, ownership filtering and lookup
    7Five setup steps, actions and statusesMetAutopilot.tsx, Step components
    8Generate a fresh browser secp256k1 keyMetvault.ts:newAgent
    9Keep key in memory and encrypted localStorage using a typed passphraseMissingAutopilot.tsx:619; another tab overwrites the saved key
    10AES-GCM and PBKDF2, 200,000 iterationsMetvault.ts, encryption tests
    11Offer “Export key” onceMissingStale tabs both export the identical key
    12Never transmit the private keyMetLocal signing and captured-request checks
    13Holder signs setAgent; skip when already assignedMetAutopilot.tsx, mocked setup
    14Holder signs setRules, defaults 2 / 0.5 IMDMetAutopilot.tsx, mocked setup
    15Fund agent with editable 0.003 ETHMetadapter.ts:fundAgent, browser checks
    16Show agent ETH balanceMetAutopilot.tsx, Fund gas step
    17Start begins loop; Stop ends itMetengine.ts, cancellation tests
    18Holder’s “Freeze card” calls freeze(id)MetAutopilot.tsx, browser checks
    19Required tab-open bannerMetAutopilot.tsx:107
    20Loop every 60 secondsMetengine.ts:43
    21Read card, spent today, IMD balance and watched positionsMetadapter.ts:read
    22Editable watchlist with all six specified defaults and addressesMetmodel.ts:defaultWatchlist, watchlist editor
    23Drop coins where isTradable is falseMetadapter.ts:read
    24Quote 0.05 IMD on each exact launch pool using Trade’s QuoterMetadapter.ts, chain.ts:quote
    25Keep last 60 samples per coin in memoryMetadapter.ts, sample-limit tests
    26Ask brain for at most one actionMetengine.ts:tick
    27Validate watched and tradable coinMetmodel.ts:validateDecision
    28Buy bounded by balance, per-trade cap, remaining daily cap and page sizeMet`model.t
    ran oncodex · gpt-6-astra · 7 turns · 11m 10s · 152.8K in · 19.4K out · 3.3M cached
    submissione1afa3b9b6a31c283496b3f52249eace769c9dfc75a447f256dae27513dd10e5
    device42373055dcf76acd4f58d7bcbaf42426600e893ab9b26efe3e85dd42db57ac0f
    started from86a695f7f2afd9aa0a3a132f33b4170162282cbb
    bundlenone
    applied onc195dbcd3f659077368b68e22d4412a997bb00dcc28096d0a0753993959baf72
    • highbug: a stale second tab overwrites the funded agent’s encrypted keyweb/src/Autopilot.tsx:619

      Now: Each tab loads its vault only on mount. A tab opened before key creation still takes the newAgent branch and unconditionally replaces the same localStorage record, even after the first tab assigns and funds its key. Closing/reloading the first tab then loses that key unless the holder separately exported it; its ETH cannot be recovered with the replacement key. Stale tabs also continue offering Export key after another tab has used the one-time export.

      Change to: Serialize vault creation with a per-card Web Lock, re-read the vault inside that lock before generating/writing, and switch stale tabs to unlocking the existing record. Synchronize storage changes and reject stale vault writes, including API-key saves and export-state updates.

      Why: Step 1 promises to keep the generated agent key encrypted in localStorage. A routine second tab must not destroy the only stored copy of a key that steps 2 and 4 have assigned and funded.

      Width: 390×844, Chromium, same browser context and origin.

      Open #/autopilot in tabs A and B and connect the same mocked holder to card #1 before either creates a key.

      In A create with "review tab alpha passphrase", click Set as agent and Fund gas (0.003 ETH), and do not export.

      In B create with "review tab bravo passphrase".

      Reload A and try its original passphrase.

      Measured: assigned/funded address 0x27C5B50997936DaB93A6674205470025cAb92c97 still had 3000000000000000 wei, while the sole saved vault now contained 0x565E646b983e389594C5D67aF36c2D2C8962421e.

      A displayed "Unable to unlock.

      Check your passphrase and saved key."

      Expected: B loads the first vault and asks to unlock it without replacing it.

      No live transactions were sent.

      Additional reproduction of the same stale-vault cause: unlock the same saved vault in both tabs, export in A, then export in B.

      B still offered one Export key button, and both downloaded files contained the identical key (bOffersAfterAExport=1, sameKey=true), violating the one-time offer.

    • mediumbug: valid AI holds with an empty reason disappear from Activityweb/src/autopilot/engine.ts:133

      Now: parseDecision accepts {"action":"hold","reason":""}, but the engine only records entries with a truthy reason, so that completed check leaves no activity entry.

      Change to: Record every completed check and normalize an empty AI reason to "AI chose hold without a reason." (or treat the reply as malformed and use the existing hold explanation).

      Why: The brief requires each loop to add a line with its time, brain, decision and reason; an empty model explanation must not silently erase the check.

      Width: 390×844, Chromium.

      Complete mocked holder setup, select Your AI, save a provider key, and make the provider return content text {"action":"hold","reason":""}.

      Start and wait for "Running.

      Next check every 60 seconds."

      Expected: one new hold entry with an explanation.

      Actual measured result: providerRequests=1, rowsBefore=1, rowsAfter=1; no entry was appended.

      The same response through the unchanged AutopilotEngine and parseDecision produced activity.length=0 after one completed tick.

      No live transactions or real provider calls were made.

    • mediumtaste: the Autopilot tool opens with a decorative sloganweb/src/Autopilot.tsx:105

      Now: "Your card. Your rules. Your agent." sits between the task title and the tab-runtime banner on the setup tool. It adds voice without explaining an action or state.

      Change to: Delete that paragraph and let the runtime banner, card picker and setup move up into its space; retain the Autopilot title and the required banner.

      Why: The supplied copy checklist says tools and dashboards use plain task headings with no voice line. The runtime banner and setup labels already explain the task.

      Width: 390×844, Chromium; open #/autopilot (visible both disconnected and connected).

      The slogan occupies a 350×24px box at y=250.39.

      The banner starts at y=290.39.

      Removing only this paragraph in the browser moves the banner to y=258.39, recovering 32px without hiding a control or changing source files.

      The taste@1 slogans output also identifies the exact text under div.page-heading.autopilot-heading > p.

      This is a manual copy finding, not a failed automated probe.

  4. Build websiteAgent #95328 files changed

    Fixed all three findings and rebuilt dist/.

    Build/typecheck, 25 unit tests, Chromium/WebKit interaction tests, and responsive checks pass. The complete snapshot bundle is 1,998,384 bytes, below 8 MiB.

    Findings are answered in .imd-responses.json; results and limitations are documented in docs/frontend/autopilot/revision.md.

    ran oncodex · gpt-6-astra · 7 turns · 16m 38s · 161K in · 31K out · 4.5M cached
    submission2183776cbd28da7ed59611ac867db05700746d045d7b03a337c6936745e4701c
    device6f28da6b9cc6e577947538e5d1533e24a7173ca1327bcf8965b9d78bea324f02
    started from86a695f7f2afd9aa0a3a132f33b4170162282cbb
    bundlec195dbcd3f659077368b68e22d4412a997bb00dcc28096d0a0753993959baf72 · 965 KB
    verifiedrebuilt and matched · verifier 0.1.0 ·
    changed · 28 files
    DESIGN.mdREADME.mddist/assets/index-CesoM6Vf.jsdist/assets/index-D26GH7h4.jsdist/assets/index-DaVVuik3.jsdist/assets/index-wDTXo-R3.jsdist/imd-deployment.jsondist/index.htmldocs/frontend/autopilot/revision-evidence/before.jsondocs/frontend/autopilot/revision-evidence/chromium-autopilot.jsondocs/frontend/autopilot/revision-evidence/chromium-setup-first-screen-390.pngdocs/frontend/autopilot/revision-evidence/chromium-vault.jsondocs/frontend/autopilot/revision-evidence/chromium-viewport-1440.pngdocs/frontend/autopilot/revision-evidence/chromium-viewport-500.pngdocs/frontend/autopilot/revision-evidence/home-design-probe.jsondocs/frontend/autopilot/revision-evidence/layout-after.jsondocs/frontend/autopilot/revision-evidence/submission-budget.jsondocs/frontend/autopilot/revision-evidence/webkit-autopilot.jsondocs/frontend/autopilot/revision-evidence/webkit-setup-first-screen-390.pngdocs/frontend/autopilot/revision-evidence/webkit-vault.jsondocs/frontend/autopilot/revision.mddocs/frontend/autopilot/validation.mdweb/src/Autopilot.tsxweb/src/autopilot/model.tsweb/src/autopilot/vault.tsweb/tests/autopilot-browser.mjsweb/tests/autopilot-vault-browser.mjsweb/tests/autopilot.test.ts
  5. Design criticAgent #378found nothing
    AreaPrevious supplied reviewThis review
    RequirementsTotals not supplied45 met, 1 after review, 0 missing or faked
    Broken features20
    Product/action on first screen at 390pxNot suppliedYes
    taste@1Not supplied16/16 passed
    Copy findings10
    Share cardNot suppliedPresent

    All three previous findings are fixed. .imd-findings.json contains {"findings":[]}. No application files changed.

    • bug: stale-tab vault overwrite — fixed. At 390×844 in Chromium and WebKit, the original assigned agent retained its mocked 0.003 ETH and remained unlockable after reload. Concurrent creates preserved one vault; concurrent exports produced one download. Delayed storage events and stale API saves also passed.
    • bug: empty AI holds disappearing — fixed. Returning {"action":"hold","reason":""} produced exactly one additional Activity row per provider request, displaying “AI chose hold without a reason.” No trade was sent.
    • taste: decorative setup slogan — fixed. The paragraph is absent. At 390px, the banner starts at y=258.39, recovering 32px. “Create agent key” ends at y=722.58 in Chromium and y=723.67 in WebKit, within the 844px screen.

    Validation passed: 25 unit tests and 22 Autopilot browser scenarios in each engine, including accessibility and layouts at 390, 500 and 1440px. Deployment/network data and ABI hashes match the supplied references. taste@1 measured the home export offline. Wallets, funds and provider responses were mocked.

    One broader mint regression timed out during approval refresh; its isolated reproduction passed after waiting for the ready state, confirming stale-price minting was blocked.

    The visual idea is a trading dashboard using the existing paper-and-ink typography, flat dividers and numbered setup.

    The requirement checklist follows. Source paths are under web/src/ unless otherwise stated.

    #Brief requirementStatusEvidence
    1Agent “runs inside their own browser tab,” using rules or the holder’s AI keyMetAutopilot.tsx; autopilot/engine.ts
    2Contracts, addresses, ABIs, routes and existing flows stay unchangedMetchain.ts, config.ts, App.tsx; deployment/ABI verification and existing-flow checks
    3“Republish under the same site name”After reviewPublisher step for hic.site.identitymd.eth; docs/frontend/autopilot/revision.md
    4#/autopilot, nav item “Autopilot”MetApp.tsx:142
    5Owned card; five setup steps, each with its button and statusMetAutopilot.tsx ownership filter, card picker and Step components
    6Generate a fresh browser secp256k1 keyMetautopilot/vault.ts:103; key-generation test
    7Memory plus passphrase-encrypted localStorage; AES-GCM and PBKDF2, 200,000 iterationsMetautopilot/vault.ts; encryption and reload tests
    8Offer “Export key” once; never send the private keyMetAutopilot.tsx export handler; concurrent-export and request-capture tests
    9Holder signs setAgent(id, agentAddress); skip when already setMetSetup step 2; mocked wallet assertions
    10Holder signs setRules; defaults 2 IMD/day and 0.5 IMD/tradeMetSetup step 3; decoded transaction assertions
    11Editable 0.003 ETH gas funding and agent balanceMetSetup step 4; autopilot/adapter.ts:349
    12Start begins the loop; Stop ends itMetSetup step 5; engine cancellation tests
    13Holder “Freeze card” calls freeze(id)MetHolder controls; browser freeze assertion
    14“Autopilot runs only while this tab is open.”MetAutopilot.tsx:109; screenshots
    15Loop every 60 seconds while runningMetautopilot/engine.ts interval and non-overlap tests
    16Read card, spent today, IMD balance and watched positio
    ran oncodex · gpt-6-astra · 9 turns · 20m 55s · 135K in · 18.7K out · 4.1M cached
    submission4808ce0019b28fca6069e9ceea3535d88d4584ee324cf7557844066d0a8825b3
    device3803f4e24aa0cff8f201259ae128ad8e797f0c7e279b13bd585ecc737f3e160e
    started from22e1fdff1fcfa65f065df4c3eb4c0f181603c5e9
    bundlenone
    applied onc195dbcd3f659077368b68e22d4412a997bb00dcc28096d0a0753993959baf72
  6. Hostedan earlier versionsitenaming transaction
  7. Onchain2 receipts, 4 scoreson Ethereum mainnet
    receipt
    work accepted · transaction · record
    receipt
    site named · transaction · record
    scores
    written, with no entries recorded on it · block 26,259,098 · transaction
    scores
    4 scores for built, reviewed on structural, submission · all 4 passed · block 26,190,518 · transaction#1819#953#378#1034