squad: UI/UX polish — 375px stranger drill of the aha surfaces + entity-space sweep - #653
Open
nategeier wants to merge 7 commits into
Open
squad: UI/UX polish — 375px stranger drill of the aha surfaces + entity-space sweep#653nategeier wants to merge 7 commits into
nategeier wants to merge 7 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
nategeier
added a commit
that referenced
this pull request
Aug 18, 2026
…p on the ask-failures feed Both lanes added ?internal=1 to /api/admin/ask-failures + /dashboard/failures: #650 via the new typed is_internal column (hidden by default in the WHERE), #653 via a raw-SQL id read tolerant of the missing column + ?kind= slicing. Merged: #653's structure (kind filter, page toggles/tag/poll) on #650's typed column; raw reader retired; internalHidden counted server-side; response carries kind + internal + per-row internal. test-api: both appended check blocks kept. Duplicate 'internal' field in the page type dropped. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ty-space sweep Round-1 drill (375px + 1280px, both themes) of /links mint stage, /i, /inbox, /agents, /docs/desk, the rail inbox and the unified sign-in modal on a prod build. Fixes, all surgical: - ChatSignInGate: the guest banner sat ON the composer below lg (bottom-28 ignored the 48px bottom tab bar) — rides higher on mobile only. - CreateAccountButton: the Google lane was a wide glyph-only button; it now carries its visible label like the wallet + email lanes. - /inbox rows: 'Review & sign' crushed the ask into a word-per-line column at 375 — min-w on the text block wraps the CTA under instead. - SplashDashboard tile header: 'WHAT / PANTESSA / NOTICED' beside a clipped subtitle — title stays one line, subtitle wraps to its own line. - MintLinkForm fine-print toggle: text-left + non-shrinking chevron when it wraps at 375. - JobsRailTab inbox row: 'from Risk Bot· tap' (entity-space bug) fixed. - SWC entity-space sweep across rendered public HTML: 27 glued sites in /docs/* (desk, embed, links, jobs, trust, privacy, terms, spend-policy, transactions, creator-earnings, first-five-minutes, host-buttons, embedded-wallet), /pricing, /activity feed + trace terminal. - test:api: entity-space fence over 23 prose routes (letters, opening paren/quote, spaced em dash glued to a closing inline tag). Gates: tsc + build + test:api 1483/1 known-red vs :3801. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…advance hint, wrapping receipt, /rebrand pointer, optional-explicit save bar Ideation's premortem of the ten-strangers drill (lead ask: Swap $20 USDC→ETH on Base via an /i link, MetaMask/Rabby EOA, Uniswap v3 approve→swap as a SendTxChain) named these /i-runtime fixes: - reportWalletRefusal (lib/wallet-refusal.ts) now fires from SendTxButton (pre-broadcast errors + refused network switch; artifact 'tx', or 'tx-chain' with the refresh kind as build path when inside SendTxChain) and SignOrderButton (typed-data refusal, 'cow-order'). The #1 predicted failure — approve fails, USDC present, zero ETH for gas — now lands in /dashboard/failures as kind wallet-refused with the wallet's words, connector and chain. Fire-and-forget; human rejections dropped in the beacon; reverts after a hash stay the chain's. - SendTxChain: one-line hint under the current step — "once this confirms, the next step (<title>) opens in your wallet automatically" — so the ~2s auto-advance stops reading as "why twice". - SendTxChain done receipt: the summary line WRAPS instead of truncating (it carries the amount out — the closest thing to "you now hold X ETH" without adding a balance RPC; none added, by design). - /i splash: "Pantessa · formerly Yeetful" → /rebrand pointer (the page has no site footer; every other page carries it). - Post-receipt save bar: "Optional — you're done here; the money moved…" (it read as a third signature). The /i door already leads with "Connect a wallet" (Google, then email below) — no prop change needed. - test:api: /i rebrand pointer pin + a wallet-refusal wiring audit over every signTypedDataAsync/sendTransactionAsync caller (11 senders; queued ones allowlisted BY NAME with a reason). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s, live poll pill, internal rows hidden by default The ten-strangers drill has Nate watching /dashboard/failures and the per-link funnel while a recruit signs; GTM verified ?funded=1 was not read, nothing auto-refreshed, and useIntentLinks loaded once. - /dashboard/failures reads ?funded=1 / ?kind=wallet-refused / ?internal=1 on mount and writes them back on every toggle (replaceState) — a watch link opens on the right slice. New "wallet refused" + "internal" toggles. - components/LivePill.tsx: useLivePoll (visible-only interval, pauses when the tab is hidden, refires on return) + the "live · updated Xs ago" pill. Failures page polls quietly every 25s; useIntentLinks re-reads every 30s and exposes updatedAt — pill on the rail Links tab + /dashboard/links. - /api/admin/ask-failures: ?kind= filter, ?internal=1 opt-in; rows carry internal:boolean read from ask_failures.is_internal via a raw query that tolerates the column's absence (#650 adds it) — never a 500; stamped rows hidden by default, counted as internalHidden, tagged "internal" when shown. - test:api pins: ?kind slice + internal tag + ?internal=1 zeroes the hidden count; page source pin for the URL params + pill. Live-proven on :3801 as the burner (real SIWE via mock EIP-6963 + local signer): toggles write the URL, router.push with the query lights the toggles on mount, pill ticks on failures + /dashboard/links, a stamped drill row wears the tag only under ?internal=1. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d, switch-refusal = named chain + switch-and-retry button
- EmptyState reserves the guest banner's height below the example gallery
(guestBannerPad, below lg only) — the last chip scrolls clear of the
banner instead of sitting under it (375 proven: chip bottom 296 < banner
top 542 at scroll end).
- SignHlActionButton: the venue's raw "Must deposit before performing
actions" (fresh wallet on the delegated door — even approveAgent gets it)
→ honest line + the chat's own deposit ask ("deposit 10 usdc to
hyperliquid", round-trips parseHlIntent → guarded Bridge2 transfer).
Copy-only: in organic traffic the build's has-collateral guard
(lib/hyperliquid-exec.ts:558) + planHlCollateralShortfall (:670) offer
the deposit before any card renders; the drive reached the card only
because the artifact was canned from a funded wallet.
- SendTxButton: a refused network switch names the chain inline and the
button itself becomes "Switch to <chain> & retry" (re-runs the switch +
sign) — never just red text.
- test:api: source pin for both card copies. 1488/1 known-red.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ply, wallet door, CTA above the fold, eyebrow aligned
From Visuals' frame-by-frame H1 storyboard (what a recruit sees when it
counts):
- lib/sign-cta.ts SIGN_CTA_CLASS: the current step's sign/send button is
THE primary accent CTA on SendTxButton (→ SendTxChain), SignOrderButton
and SignHlActionButton — one class, both themes (.text-black light remap);
everything else on the card stays quiet. Was a ghost text button.
- /i (simple) leads with the human line — "Swap 20 USDC → ~0.010555 ETH ·
on Base · fee 0.5% · your wallet signs" — and folds venue/pool/slippage
behind a details disclosure (lib/simple-reply.ts pure splitter, three
builder shapes; components/chat/SimpleArtifactReply.tsx). Only
artifact-bearing replies split; chat + embed print the reply unchanged.
- The /i door (walletConnectOnly) is titled "Connect a wallet" with the
wallet icon (no "sign in", rule 6); the email submit is a real loading
state ("Preparing the email lane…" + spinner) while CDP boots, never a
disabled button stuck on "Starting…".
- /i splash ≤sm: the CTA leads and the three contract cards follow (flex
order) — the door was below the fold on a phone.
- MintLinkForm mint-stage eyebrow: INTENT LINK · YOUR WALLET SIGNS (mirrors
the r2 OG card; no more TAP TO RUN).
- test:api: splitter pinned on the Uniswap + LiFi shapes and the plain
pass-through; source pins for the CTA class on all three buttons, the door
title, the ≤sm order, the eyebrow. 1491/1 known-red vs :3801.
Frames on the r5 build (squad-2026-08-18/shots-uiux/h1-r5/, cdp.mjs recipe,
mock wallet impersonating nategeier.eth read-only, fixture link deleted):
dark-1280 / light-1280 / dark-375 04-built = lead line + details toggle +
accent "Sign & send approve" + the auto-advance hint.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… refusal rows, "Confirm in your wallet…", /i exit ramps gated, eyebrow = the OG card Merge hygiene (QA r3): rebased onto feat/squad-security 4a222c0 and resolved the ask-failures overlap exactly as the integration branch did (8a91da0): #653's structure (?kind= slice, page toggles/tag/poll) on #650's typed is_internal column; the raw-SQL id reader is retired. - lib/wallet-refusal.ts walletErrorWords: the row's reply carries the wallet's ACTUAL words — viem wraps RPC failures so e.message leads with "An internal error was received."; the diagnosable line lives in .details / .data.message / .cause — first specific line wins. Used at every beacon site (SendTxButton, SignOrderButton, SignHlActionButton). - N1: the in-flight label is "Confirm in your wallet…" on every sign/arm button (was "Sign in wallet…" — read as a login). - N2: the /i header exit ramps (MAKE A LINK / OPEN THE APP) render only on receipt or flow-nudge — never above the card mid-flow. - N3: linkEyebrow (lib/intent-links) mirrors the OG card: From @handle · your wallet signs / Call by <agent> · … / Intent link · from <sender> · … (branded splash keeps · powered by Pantessa); the /i page passes the creator's claimed handle. No more "CALL · BY @handle". - Pins: walletErrorWords on viem/node/plain shapes; linkEyebrow pure + rendered creator/house eyebrows; N1/N2 source pins. 1513/1 known-red vs :3801 on the rebased branch (Security's pins included). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
nategeier
force-pushed
the
feat/squad-uiux
branch
from
August 18, 2026 10:37
b5d631b to
89ff1be
Compare
…der's generic details (MetaMask -32603), card copy uses the same helper QA's final smoke: a -32603 stored "Internal JSON-RPC error." — viem's OUTER details (the provider's generic envelope) beat the wallet's words nested in cause.data.message, and the card showed "An internal error was received." for the same reason. Now: candidates carry depth + fromData; the deepest data.message wins, then the deepest specific line; GENERIC covers "Internal JSON-RPC error.", "An internal error was received.", "An unknown RPC error occurred.", "Request failed.", bare "Internal error"/"RPC error". SendTxButton, SignOrderButton and SignHlActionButton show the same words on the card. Pinned on QA's exact MetaMask -32603 wrapper shape. 1513/1 known-red vs :3801. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
STACKED on #650 — merge #650 first; GitHub retargets this to main when #650's branch is deleted (or retarget by hand). Rule: retarget before merging, top-down.
Squad 2026-08-18 — UI/UX lane (round 1; round 2 accumulates on this PR)
Stranger drill at 375px + 1280px, both themes, on a prod build (
, /agents/, /docs/desk, the rail "For you" inbox (mock-EIP-6963 connect-only), and the unified sign-in modal on /chat + /dashboard.next start -p 3801) of the new aha surfaces: /links mint stage (U3 recipient field), /i splash + runtime, /inbox/What broke → what was fixed
bottom-28ignored the 48px mobile tab bar)ChatSignInGate:max-lg:bottom-[calc(7.25rem+48px+safe)], desktop untouchedCreateAccountButton: rendersContinue with Googlebeside the glyphmin-w-[14rem]→ CTA wraps under; 1280 unchanged (inline)whitespace-nowrap, subtitle drops to its own linetext-left+ non-shrinking chevronscan_walletreads,Sign caps—,Pantessa Inc.(“,/NATIVE VENUES,$idle —,newmints, … across /docs/{desk,embed,links,jobs,trust,privacy,terms,spend-policy,transactions,creator-earnings,first-five-minutes,host-buttons,embedded-wallet}, /pricing, /activity{' '}after the inline element at every siteClean at both widths/themes: /i splash + runtime, /agents/, /docs/desk (pre blocks scroll internally), /links mint stage incl. the recipient field, sign-in modal (all three lanes full-width, no crush).
Harness
</em|strong|a|code>glued to a letter /(/“/ spaced—) — the sweep is now un-regressable.tsc+build+test:api1483 passed / 1 known-red (router-select) vs :3801.Not changed (findings for the coordinator)
/l/nate404s locally (no claimed handle in this DB) — not a bug.🤖 Generated with Claude Code
Round 2 — the /i sign path (ideation premortem of the ten-strangers drill)
Lead ask:
Swap $20 of USDC to ETH on Baseon an /i link, MetaMask/Rabby EOA → Uniswap v3 approve→swap as a SendTxChain.SendTxButton(pre-broadcast errors + refused network switch; artifacttx/tx-chainw/ build path) andSignOrderButton(typed-data refusal,cow-order) — the added postgres #1 predicted failure (approve fails: USDC present, zero ETH for gas) now lands in /dashboard/failures aswallet-refusedwith the wallet's words + connector + chain. Fire-and-forget; human "no" dropped in the beacon; post-hash reverts stay the chain's.Pantessa · formerly Yeetful→ /rebrand (the page has no site footer).signTypedDataAsync/sendTransactionAsynccaller (11 senders; the queued ones — DCA/spot arms, grants, NFT listing, x402 payment sigs, votes — allowlisted by name with a reason).Round 3 — watchable /dashboard/failures + links funnel
/dashboard/failuresreads?funded=1/?kind=wallet-refused/?internal=1on mount and writes them back on every toggle (replaceState); new wallet refused + internal toggles.components/LivePill.tsx:useLivePoll(visible-only interval, pauses hidden, refires on return) + the "live · updated Xs ago" pill. Failures page polls quietly every 25s;useIntentLinksre-reads every 30s → pill on the rail Links tab + /dashboard/links./api/admin/ask-failures:?kind=filter,?internal=1opt-in; rows carryinternalread fromask_failures.is_internalvia a raw query that tolerates the column's absence (squad: security review + honest arrival denominator #650 adds it) — stamped rows hidden by default, counted asinternalHidden, tagged internal when shown.?kindslice + internal tag +?internal=1zeroes the hidden count; page-source pin for the URL params + pill.router.pushwith the query lights the toggles on mount; pill ticks on failures + /dashboard/links; a stamped drill row wears the tag only under?internal=1.Gates after r3: tsc + build + test:api 1487 passed / 1 known-red vs :3801.
Round 4 — small polish off QA + my own finding
EmptyStatereserves the banner height below the gallery on mobile (guestBannerPad) — last chip scrolls clear (375 proven).deposit 10 usdc to hyperliquidround-tripsparseHlIntent). Copy-only — organic traffic hitshas-collateral(lib/hyperliquid-exec.ts:558) +planHlCollateralShortfall(:670) before any card; the drive reached the card only because the artifact was canned from a funded wallet.SendTxButton: refused chain switch → inline line names the chain and the button becomes "Switch to & retry" (re-runs switch + sign).Round 5 — the moment of truth on /i (Visuals' H1 storyboard)
lib/sign-cta.tsSIGN_CTA_CLASS(accent pill, both themes) on SendTxButton (→ SendTxChain), SignOrderButton, SignHlActionButton — was a ghost text button; everything else on the card stays quiet.Swap 20 USDC → ~0.010555 ETH · on Base · fee 0.5% · your wallet signs— router/pool/slippage folded behind "Details" (lib/simple-reply.ts+components/chat/SimpleArtifactReply.tsx; simple surface only, chat/embed unchanged).INTENT LINK · YOUR WALLET SIGNS(matches the OG card).squad-2026-08-18/shots-uiux/h1-r5/{dark-1280,light-1280,dark-375}/04-built.png(cdp.mjs recipe; fixture link deleted after).Round 6 — merge hygiene + stranger-eye copy
feat/squad-security(4a222c0); the/api/admin/ask-failures+/dashboard/failuresoverlap resolved as the integration branch did (8a91da0): squad: UI/UX polish — 375px stranger drill of the aha surfaces + entity-space sweep #653 structure on squad: security review + honest arrival denominator #650's typedis_internal, raw reader retired.walletErrorWords: refusal rows store the wallet's real words (viem.details/.data.message/.causechain), not "An internal error was received." — pinned.From @handle · your wallet signs;linkEyebrowpinned, page passes the claimed handle).Round 7 — last: the wallet's words, for real
walletErrorWordsnow prefers the deepestdata.messageover any shallower generic (Internal JSON-RPC error./An internal error was received./ … added to GENERIC) — QA's exact MetaMask -32603 wrapper pinned; the card copy on SendTxButton / SignOrderButton / SignHlActionButton uses the same helper.