Skip to content

Dev - #2139

Open
pikonha wants to merge 136 commits into
mainfrom
dev
Open

Dev#2139
pikonha wants to merge 136 commits into
mainfrom
dev

Conversation

@pikonha

@pikonha pikonha commented Aug 24, 2026

Copy link
Copy Markdown
Member

No description provided.

brunod-e and others added 30 commits August 13, 2026 13:19
The panel's TheSectionLayout title/description is replaced by the two-card
hero from the Panel v2.1 spec: a judgment headline, a subhead framing the
Stage system, and a link to the framework docs beside a "Governance risk,
right now" card.

DaoProtectionLevels moves from vertical Recharts bars to the horizontal
Stage 0/1/2 bars in the design, sized against the busiest stage, with the
per-stage hover kept on the design-system tooltip. Treasury Monitoring and
Delegated Supply History are retired with no replacement cards, per spec.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A one-line strip between the hero and the Monitored DAOs table: the LATEST
FINDING label, the finding sentence, and a link out to the case write-up.

The sentence and its URL come from a mock for now — swapping in a fetch of
the newest Paragraph publication only has to replace the two fields the
ticker reads.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The v2.1 panel is a scrolling page, not a single viewport: drop the table's
fillHeight and the min-h-0/flex-1 chain that made it scroll inside the
section, and let main scroll on desktop the way it already does on mobile.

The table itself is untouched — same columns, tooltips, and sorting.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three outcome-framed case cards (ENS, Uniswap, Arbitrum) that link out to
the write-ups, and a testimonial carousel below them.

ClickableCard grows an optional href so the Figma "Clickable Card" can be
what the design annotates it as — a link — instead of a button.

Case copy is final; only the ENS post has a published URL, and the
testimonial set carries just the wording already verified in the X mentions
audit. Both are marked for follow-up rather than filled with invented
attributions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two equal-height feature cards with bottom-aligned links: Alerts into the
in-app /alerts route, and API + MCP out to the docs.

The alerts page gets the explainer the spec asks for above the channel
cards — what gets pinged and that the triggers are the reader's choice — so
the CTA lands on something self-explanatory.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…oints

ENS DAO proposals stall after passing because queue() and execute() on
the Governor are permissionless but nobody pays the gas. These endpoints
let the relayer sponsor those transactions on demand: callable manually
today, and by an automated trigger (e.g. the notification system) later.

Given a proposalId, the relayer fetches the execution args from the
Anticapture API (GET /proposals/{id}), proves they belong to that
proposal via the governor's hashProposal (the API stays untrusted),
checks on-chain state (Succeeded for queue; Queued past its eta for
execute), guards the wallet balance, simulates, then broadcasts.

The endpoints are only registered when ANTICAPTURE_API_URL is set.

The e2e forks mainnet one block before a real proposal's ProposalQueued
tx and replays its lifecycle through the HTTP endpoints — no voting-
period mining, so it runs in ~15s on any RPC serving recent state
(verified against rpc.mevblocker.io).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drops the feature-flag conditional: the queue/execute endpoints are
always registered, consistent with how the app treats the rest of its
config. Deployments must set ANTICAPTURE_API_URL before their next
deploy or env validation fails at boot.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ected fetch

msw is the monorepo's convention for HTTP-service unit tests (see
apps/api dune/coingecko/treasury tests) and was already in the relayer's
devDependencies; AnticaptureProposalSource now uses global fetch with no
injection seam.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Unit tests use the repo's stub-factory pattern (createStubChain/
  createStubSigner/createService, as in relay.test.ts) instead of
  bespoke fake classes with mutable knobs.
- EnactmentChainReader now extends the shared ChainReader type instead
  of redefining its overlap.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A single compact row closing the page: the Blockful service lines and a
link to the contact page.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ProposalEnactmentService now depends on a domain-level GovernorGateway
(hashProposal/state/proposalEta/blockTimestamp/balanceOf/simulate/
waitForReceipt) instead of a raw viem reader, following the
IChainStateService precedent. ViemGovernorGateway owns all ABI plumbing
and is exercised for real by the e2e.

Unit-test stubs collapse to plain Partial<GovernorGateway> overrides —
no viem generics, no casts, no functionName switch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Railway image builds with `pnpm --filter ... build`, which bypasses
turbo's codegen dependency, so @anticapture/client's gitignored
generated/ sources were missing. Run codegen explicitly with the same
ARG wiring infra/mcp-server already uses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Isadora pointed at the source: the X mentions audit already carries the
verified wording, handles and links, so the carousel now ships five real
testimonials — Ethereum Foundation, Lefteris Karapetsas, @blockbanzai,
@cupOJoseph and ENS DAO — instead of one entry waiting on sign-off.

Nothing about this data is mocked any more, so it moves out of
mocked-data/ into shared/constants/track-record.ts. Each entry keeps the
tweet it was lifted from as its link.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three pixel-level gaps found by measuring the rendered page against the
Figma frame:

- the hero cards split 597/565 instead of 582/582, because flex items
  default to `min-width: auto` and the left card's content set the floor;
- the row came out 184px tall against the design's 186px;
- the mono card title tracked at 0.72px, the fixed value behind
  `tracking-wider`, where 13px Alternative/Small calls for 0.78px (the
  token is right for the 12px labels, wrong one step up).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Same one-step-off letter-spacing as the hero card title: `tracking-wider`
resolves to a fixed 0.72px, which is the 12px value, not the 0.78px the
13px Alternative/Small style calls for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Figma card carries the same 1px borders/default outline as the case
cards above it; the class was there but the border width never was, so it
rendered flush against the background. Section label tracking corrected to
0.78px alongside.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ng it

Adds --tracking-alternative-sm alongside the existing --tracking-wider, so
the two mono label sizes both have a named value: 0.72px at 12px, 0.78px at
13px. Both are the same 6% the type styles specify — CSS letter-spacing
just can't take the percentage.

Drops the fixed hero height too. The remaining 2px against the frame comes
from the chart card's own rhythm, and pinning it would trade one magic
number for another.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copy link
Copy Markdown
Collaborator

🎨 UI Review

Automated review · Figma: found but unreachable (task 86aehhuqw "Panel v2.1 (Merged App-First Home)" names file mUgy2KpQ3gJ07yZaUaXu8l, frame 3604:89944, but the Figma MCP integration only resolves a "Cover" page for that file key — the referenced frames aren't accessible from here) · Preview
ℹ️ This is a dev → main promotion rolling up ~6 already-developed features. Reviewed via code + the detailed Panel v2.1 spec text pulled from ClickUp (exact copy/behavior tables) + the Storybook preview + UX-expert evaluation. The main dashboard preview isn't deployed for this PR, so live regression checks are limited to diff-level analysis. Scope prioritized the new Panel v2.1 sections and the Request-a-Feature drawer.


Panel v2.1 — Homepage hero / stage chart

  • Heading levels skip from h1 straight to h3 before any h2 appears: PanelHero.tsx renders the page's only h1 ("See which DAOs could be captured…"), and the very next heading in the DOM is the h3 "Governance risk, right now" inside DaoProtectionLevels.tsx:76-78, rendered before the page's first h2 ("Latest finding" in LatestFindingTicker.tsx:12). Every other new Panel v2.1 section title (ticker, track record, use-it-now, services) correctly uses h2. Bump DaoProtectionLevels.tsx:76 to <h2> to keep the outline sequential. (apps/dashboard/features/panel/components/DaoProtectionLevels.tsx:76) [Code-only]

Panel v2.1 — Testimonial carousel

  • Prev/next arrows are size-9 (36px) IconButtons (TestimonialCarousel.tsx:29-37,86-94) — under the 44px touch-target guideline for a control a mobile visitor will tap repeatedly to cycle through 5 testimonials. Consider size="lg" or padding the hit area via a wrapper. (apps/dashboard/features/panel/components/TestimonialCarousel.tsx:29) [Code-only, nice-to-have]

Governance — Cast Your Vote modal (Tornado Cash)

  • For Tornado proposals, submitDisabled now also depends on isTornDelegatorListIncomplete and tornDelegatorsError (VotingModal.tsx:250-257), but nothing in the modal communicates why Submit is greyed out while the delegator list pages in, and if the fetch errors (tornDelegatorsError) Submit stays disabled indefinitely with no visible error or retry. A Tornado voter opening the modal just sees a dead button. Surface a small inline note ("Loading your delegators…") or route the Submit Button's loading state through isTornDelegatorListIncomplete, and show an error message when tornDelegatorsError is set. (apps/dashboard/features/governance/components/modals/VotingModal.tsx:250, button at :391) [Code-only]

Validated — no change needed

  • Track-record case copy (ENS/Uniswap/Arbitrum) and the testimonial quotes/handles/avatars in track-record.ts match the ClickUp spec's finalized copy verbatim, including the institutional entries (Ethereum Foundation, ENS DAO) that replace the old placeholder Vitalik quote.
  • LatestFindingTickergetLatestParagraphPost() has a 3s timeout and falls back to a static publication link on any transport/parse failure, so a flaky external RSS feed can't break the new homepage's SSR.
  • TestimonialCarousel correctly pairs aria-live="polite" + aria-atomic="true" on the swapped quote so screen-reader users hear a testimonial change instead of dead arrow buttons, and disables both arrows (rather than hiding them) when there's nothing to cycle to.
  • ClickableCard's new href mode correctly falls back to the disabled <button> branch even when isDisabled is combined with href, so keyboard focus/disabled semantics aren't lost to an always-focusable anchor.

Generated by Claude Code

brunod-e and others added 3 commits August 24, 2026 12:45
…ction settles

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…short viewport

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@brunod-e

Copy link
Copy Markdown
Collaborator

Review feedback and the E2E failure are addressed in #2140 (targets dev, so this PR picks the fixes up once it merges):

  • UI review: DaoProtectionLevels heading is now an h2, the testimonial arrows grew to 44px touch targets, and the Tornado voting modal now explains a disabled Submit ("Loading your delegators..." note while the list pages in, error message + Retry when the fetch fails).
  • Codex (relayer): the enactment dedupe lock is now held past a receipt timeout until the transaction settles, so duplicates join the pending transaction instead of broadcasting again.
  • Dashboard E2E: panel.spec.ts hard-assumed the Monitored DAOs table outgrows the 640px viewport; removing Shutter dropped it to 613px. The test now asserts the actual invariant (no inner scrollbox on the table container) and survives DAO count changes.

The "Check unconsumed changesets" failure is the release gate: merge the open Version Packages PR #2131 on dev first, then refresh this PR.

brunod-e and others added 2 commits August 24, 2026 12:54
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix: address PR #2139 review feedback and the panel E2E failure
This reverts commit 93cf755, reversing
changes made to 1e88530.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 907dac9083

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@@ -136,9 +179,10 @@ export const VotingModal = ({
return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Exclude the voter from Tornado delegated-vote addresses

When a TORN account delegates and later undelegates, the TORNGovernor:Undelegated handler records its current delegate as the account itself, and the delegators repository intentionally returns self-delegations. This filter only deduplicates those results, so the connected wallet remains in from; the nonempty list selects castDelegatedVote, even though the Tornado handler's own invariant says including the voter reverts because self-delegation is forbidden. Consequently, affected users cannot vote until the address is filtered out case-insensitively before choosing between castVote and castDelegatedVote.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in #2142: the from list for castDelegatedVote now drops the connected voter's own address case-insensitively (the delegators query intentionally returns the self-delegation row), so the vote no longer reverts; a voter left with no delegators routes to castVote. Covered by unit tests.

brunod-e and others added 2 commits August 24, 2026 13:34
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
revert: restore the Shutter DAO in the dashboard

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8a5060668a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/relayer/src/services/proposals/proposal-enactment.ts Outdated
brunod-e and others added 2 commits August 25, 2026 18:36
… wait throws

A transient RPC error from the initial waitForReceipt rejected runEnactment
and released the in-flight lock while the transaction could still be pending,
so a retry could broadcast a duplicate. The failed poll is now treated as an
unsettled broadcast and handed to the bounded settlement hold.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The delegators query intentionally returns self-delegations (the Undelegated
handler records an account as its own delegate), but TORN's governor forbids
self-delegation, so a from list containing the voter made castDelegatedVote
revert and blocked the vote. The voter is now dropped case-insensitively; a
voter left with no delegators routes to castVote.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix: PR #2139 review feedback (Tornado voter filter, relayer receipt errors)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c51d8f08d6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

const counterKey = `rate-limit:${key}:${window}`;

try {
const response = await fetch(`${url.replace(/\/+$/, "")}/pipeline`, {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bound the durable rate-limit request

When the configured Redis REST endpoint accepts a connection but stalls, this fetch has no timeout, so checkDurableRateLimit never reaches its documented in-memory fallback and the feature-request submission remains blocked until the hosting platform terminates the function. Add a short abort deadline so transient store failures preserve endpoint availability rather than preventing the email from being sent.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants