Files
zeekayandHanzo Dev 5c1562944c Build the governance interface on our own design system
lux.vote was served by an interface derived from Decent DAO under AGPL-3.0.
This is a fresh app on @hanzo/gui with no Decent lineage — the replaced app's
route table was read to enumerate what the interface must do, and nothing else.

No Tailwind anywhere. @luxfi/ui is not a dependency: its prebuilt components
carry arbitrary-utility class strings and are the only reason the exchange
scans for them. Dropping it means replacing two things it provided —
createGui, which GuiProvider alone does not call and without which the tree
throws and the document is blank, and luxUi()'s aliases, now read from
node_modules/@hanzogui at config time so an upgrade cannot leave a package
undeduplicated.

Twelve screens over the Governor, the votes token, the Timelock, the work
market, Roles, Karma and the gauges, wired to luxfi/standard's Foundry
artifacts rather than to its stale ABI barrel. The contracts are not what the
prose says: Bounty has no escrow, arbiter or dispute state; MultiDAOGovernor
swaps Executed and Expired; Karma emits no Transfer so no holder list exists.
The Governor's clock is mode=timestamp, which is asked for rather than assumed
because 96369 produces blocks on demand and reading seconds as blocks turns one
day into months.

Every read reports one of four outcomes — deployed, not deployed, not read, no
record. A contract with no code answers with empty data rather than an error,
so an absent contract and an idle one arrive identically at the call site;
only one of them is a statement about governance. /deployment asks eth_getCode
for every address on every chain on load, because the written records disagree
with the chain and with each other.

Endpoints are the /v1/bc/C/rpc form. The bare host serves the same chain to
curl and refuses a browser — 405 on preflight, no allow-origin header — which
would report every Governor unreadable while the Governor was fine.

Wallet login is @luxwallet/connect, imported by subpath: its root barrel pulls
a connector factory naming all seven chains, and a bundler follows every branch
into optional peers the dev server never resolves. It signs a CAIP-122 message
and offers no provider, transactions or chain switching, so viem is built over
our own EIP-6963 discovery for the calls that write.

Telemetry off: the design system posts to api.hanzo.ai on load by default, and
who reads a proposal is not this interface's to report.

Gates ported and made real. The class check ran against the Suspense fallback
until a negative control caught it passing on a route with an injected utility
class; every gate now waits for the screen's own h1.

22 unit tests, 135 browser tests against the built output.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-30 13:18:35 -07:00

23 lines
1.4 KiB
JavaScript

import { chromium } from '@playwright/test'
const [url, out, w, h, wait] = process.argv.slice(2)
const b = await chromium.launch()
const p = await b.newPage({ viewport: { width: +w || 1280, height: +(h || 900) }, deviceScaleFactor: 1 })
p.on('console', (m) => { if (m.type() === 'error') console.log('CONSOLE ERROR:', m.text().slice(0, 400)) })
p.on('pageerror', (e) => console.log('PAGE ERROR:', String(e).slice(0, 400)))
await p.goto(url, { waitUntil: 'networkidle', timeout: 60000 }).catch((e) => console.log('nav:', e.message))
await p.waitForTimeout(+(wait || 2500))
await p.screenshot({ path: out, fullPage: true })
// An empty document reports equal widths and passes every layout check, so the
// child count is printed beside the measurement rather than trusted from it.
const kids = await p.evaluate(() => document.getElementById('root')?.children.length ?? -1)
const ow = await p.evaluate(() => [document.documentElement.scrollWidth, document.documentElement.clientWidth])
const styled = await p.evaluate(() => {
const h1 = document.querySelector('h1')
if (!h1) return 'no h1'
const s = getComputedStyle(h1)
return `h1 font=${s.fontFamily.split(',')[0]} size=${s.fontSize} color=${s.color}`
})
const bg = await p.evaluate(() => getComputedStyle(document.body).backgroundColor)
console.log('root children', kids, 'scroll/client', ow.join('/'), '|', styled, '| body bg', bg)
await b.close()