6 Commits
Author SHA1 Message Date
zeekayandHanzo Dev e17ce018c7 read the bounty struct the contract answers with
`bounties(uint256)` returns eighteen components. This board declared thirteen,
in an order that predates the reward asset being split from the stake asset.
Every component is a static type, so the short list did not revert: it read
thirteen words off the front of the answer and named them by the wrong list.
Position 1 is `rewardKind`, an enum in 0..3, which came back as
`token: 0x00…03`, and every address after it moved up one slot — funder read as
approver, approver as arbiter, worker as a deadline. The board rendered, and
credited the wrong people.

The events were stale in the same way. `BountyProposed` carries ten parameters,
not seven: `rewardKind`, `rewardTokenId` and `stakeToken` joined it when the
assets were split, and with a seven-parameter fragment `issueRef` — the only
dynamic member, so the one whose offset moves — decoded to noise.
`BountyFunded` and `BountyCancelled` name their third parameter `reward`.
`DisputeResolved`, `StakeSlashed` and `RewardRecovered` were not declared at
all; `ActivityKind` already had names for two of them, so the activity log had
been promising steps it could not read. All twelve lifecycle events are now
read.

The single `token` field is gone. A reward is `rewardKind` / `rewardToken` /
`rewardTokenId` / `reward` and a stake is `stakeToken` / `stake`, because a
reward may be an NFT while the worker's stake stays fungible. Both are read
through one `Asset`, so the board can show a stake beside a reward without a
second formatter. `parseReward` inferred the reward kind from whether the token
address was zero; the kind is recorded now, so the inference is deleted rather
than kept as a fallback, and `RewardType` takes the contract's name for it,
`AssetKind`. `Task` stops carrying a derived copy of the reward: the render site
reads it off the struct.

`src/abi.test.ts` pins the eighteen names and types, then encodes a bounty whose
every field differs and decodes it back through the fragment, so the order is
measured by what it does and not only by what it says. Swapping funder and
approver, dropping a component, or restoring the seven-parameter
`BountyProposed` each fail it.

Fixture rebuilt to the eighteen-field shape — in the old order it would have
enshrined the decode it was written under. Its Pars address and the README's
address tables were the superseded V1 set, which answers a different struct;
both now name the deployment in lp-0020.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-04 00:52:49 -07:00
zeekayandHanzo Dev 559d46cdd9 feat(work-board): one icon set — the hand-rolled 37 are Lucide now
src/ui.tsx carried its own icon set: a local `svg()` factory and 37 glyphs drawn
by hand at strokeWidth 1.7 — Lucide is 2 — so every icon on the live 4-org hub
was a half-step lighter than the same icon in @luxfi/ui rendered beside it.
IconHalfCircle went further and painted a filled half-disc over an outline
circle, making the "in progress" chip the only duotone mark on a board that is
otherwise monochrome. And the reward row drew its NFT placeholder as the emoji
🖼️, which is not an icon at all — it is a colour font glyph, immune to
`currentColor` and sized by the text.

All 37 are now re-exported from `@luxfi/ui/icons` under the same `Icon*` names,
so not one view changed: `export { House as IconHome, Kanban as IconBoard, ... }`.
The emoji is Lucide `Image`. @luxfi/ui moves 7.4.0 -> 7.4.3, which is where
`./icons` lives.

Discord, X and GitHub keep their hand-drawn marks. A logo is not a UI glyph and
no icon set gets to redraw someone's mark.

Measured on the running preview, same page, same build pipeline:
  before  22 <svg>, 0 lucide-classed, body 996 chars, 0 page errors
  after   22 <svg>, 18 lucide-classed, body 996 chars, 0 page errors
`tsc --noEmit && vite build` clean.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 15:15:15 -07:00
zeekayandHanzo Dev f0f4a4d6ca work-board: regenerate package-lock with npm 10 to match node:22 CI (fix npm ci drift)
The @luxfi/[email protected] migration regenerated the lock with npm 11, which dedupes the
[email protected] that @luxfi/ui's @expo/* deps require — but the Dockerfile builds on
node:22-alpine (npm 10) via 'npm ci', which demands those nested entries and failed
EUSAGE 'Missing: [email protected] from lock file'. Regenerate the lock with npm 10 so it
matches the build tool; no bypass of npm ci.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-18 23:48:58 -07:00
zeekayandHanzo Dev d1fce1def1 work-board: consume @luxfi/[email protected] from npm + drop local line-height pin
Phase-1 built @luxfi/ui locally and consumed it via `file:`, which blocked the
merge. 7.4.0 is now published to npm WITH dist/ (real tarball, 192 dist entries)
via the KMS-gated release path, so switch the dep `file:` -> `@luxfi/[email protected]`
(exact, matching the sibling @hanzogui pins). package-lock now resolves the
registry tarball (integrity sha512-LfUYgZFP…).

Drop the local `body .font_body { line-height: 1.5 }` pin from src/index.css:
7.4.0's AppProvider now ships that Tailwind-Preflight reset itself (injected once
via useInsertionEffect), so every consumer — not just the work-board — inherits
it. One place, one way.

Verified against the npm package: build green (tsc + vite 8.1.5, 1622 modules);
visual-regression 25/25 goldens within 2% (21 zoo + 4 pars white-label), incl.
the task-detail sheet + ⌘K palette overlays that the pin originally fixed.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-18 16:13:31 -07:00
zeekayandHanzo Dev ebacc91ff7 work-board: migrate onto @luxfi/[email protected] (@hanzo/gui Tamagui engine) — Phase 1
Run the live 4-org Dework hub on the @luxfi/ui / @hanzo/gui (Tamagui) engine
without regressing the owner-approved look/feel.

- Vite+Tamagui weld (proven exchange recipe): react-native->react-native-web
  alias, dedupe + single-copy of @hanzo/gui/@hanzogui/core/@hanzogui/web,
  optimizeDeps pre-bundle, __DEV__/EXPO_OS/IS_WEB defines, commonjsOptions so
  the engine stays in React's chunk. guiPlugin extraction deferred (its 7.3.0
  peer pins [email protected]); app renders on the runtime style-injection path.
- Wrap in AppProvider (GuiProvider + TanStack Query); brand = VALUE: root theme
  row dark_${BRAND_KEY} + --brand sourced from @luxfi/ui LUX_BRAND (hex identical
  to brands.ts, zero cross-brand leak).
- tokens.css remap layer maps the @luxfi/ui --color-* contract onto the Dework
  palette + brand (no wholesale exchange-palette import).
- Text fields -> @luxfi/ui Input/Textarea (native inputs, onChangeText<->onChange
  bridge): CommandPalette ⌘K, Suggestions editor, TaskDetail comment, chrome
  Toolbar, Leaderboards search. Keystroke round-trip verified.
- Fix Leaderboards mobile clip: page container was a flex item whose mx-auto
  disabled cross-axis stretch, so min-w-[460px] tables forced cards to 460px and
  bled past 390px. w-full + min-w-0 chain + overflow-hidden cards -> tables now
  scroll inside rounded cards, no horizontal page scroll.

Build green (tsc + vite). Visual-regression: 19/21 golden views pixel-match
(<=2%); 2 mobile bottom-sheet overlays (task-detail, palette) diverge ~3% (under
review). Preview branch — do NOT merge to main until owner review.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-18 11:08:50 -07:00
zeekayandHanzo Dev 436a88e5f6 Zoo DAO work board: standalone repo + CI + k8s manifests
On-chain bounty kanban (Vite+React+viem static SPA) that reads the live
BountyV1/EscrowV1/ReputationV1 work-market on Zoo (chain 200200) directly
over the CORS-enabled JSON-RPC. Split out of luxfi/dao into its own repo so
CI builds a clean image.

- .github/workflows/docker.yml: canonical hanzoai/.github reusable build,
  bakes VITE_RPC_URL=https://api.zoo.network/v1/bc/C/rpc, pushes
  ghcr.io/luxfi/work-board:sha-<commit> on self-hosted arcd runners.
- k8s/: Deployment (2 replicas) + Service (80->3000) + Ingress
  (hanzoai/ingress class, host work.zoo.network, letsencrypt-prod).

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-16 20:31:29 -07:00