Skip to content

feat(scene): surface wallet balance as a right-aligned status segment#1001

Merged
esengine merged 1 commit into
mainfrom
rust-scene-status-segments
May 16, 2026
Merged

feat(scene): surface wallet balance as a right-aligned status segment#1001
esengine merged 1 commit into
mainfrom
rust-scene-status-segments

Conversation

@esengine
Copy link
Copy Markdown
Owner

First concrete consumer of the flex layout primitive from #1000 and
the smallest visible step toward the multi-segment status bar the
design mock points at. Wallet balance is the most direct visible
signal of reasonix's cheap-positioning claim — users see how slowly
the number goes down across a session.

What

```
3 cards · busy · awaiting tools wallet ¥184.20
```

  • New `SceneTraceInput.walletBalance` + `walletCurrency` scalars
    — primitives so effect deps stay stable (no JSON encoding for one
    number + one string).
  • `statusRow` upgrades from a single text node to a row box only
    when the balance is present
    : left segments
    (`cardCount · busy/idle · activity`) + fill spacer + right segment
    (`wallet ¥184.20`). When balance is null/undefined the row stays
    a single text node — back-compat with the existing test that
    asserts `kind === "text"` on the status row.
  • Currency rendering: `¥` for CNY/RMB/JPY, `$` for USD, `€` EUR,
    `£` GBP; unknown codes fall back to `CODE 5.00` so nothing
    silently looks like the wrong currency.
  • `App.tsx` forwards `balance.total` and `balance.currency` from
    `useSessionInfo` — both null until the first successful
    `getBalance()` call, so the wallet segment appears once the
    endpoint responds and stays hidden offline.

Where next

The design mock also wants cache-hit %, branch, spent (this session),
jobs count on the same row. Each is a small isolated wiring step
from here. Doing them one segment per PR keeps risk + scope low and
lets the bottom row evolve incrementally.

Tests

`tests/scene-trace-frame.test.ts` — 4 new cases:

  • status row stays `kind === "text"` when wallet is undefined
    (back-compat)
  • right-aligned wallet segment when balance + currency given
    (verifies the row structure: text + fill-spacer + text)
  • USD uses `$`, unknown codes use a `CODE prefix` fallback
  • balance missing → wallet segment hidden even with currency set

`npm run verify` green via prepush gate.

Refs #868

First concrete consumer of the new flex layout primitive (#1000) and
the smallest visible step toward the multi-segment status bar the
design mock points at. Wallet balance is the most direct visible
signal of reasonix's cheap-positioning claim — users see how slowly
the number goes down across a session.

- New SceneTraceInput.walletBalance + walletCurrency scalars,
  primitives so effect deps stay stable.
- statusRow upgrades from a single text node to a row box only when
  the balance is present: left segments (cardCount · busy/idle · activity)
  + fill spacer + right segment (`wallet ¥184.20`). When balance is
  null/undefined the row stays a single text node — back-compat with
  the existing test that asserts `kind === "text"` on the status row.
- Currency rendering: ¥ for CNY/RMB/JPY, $ for USD, € EUR, £ GBP;
  unknown codes fall back to `CODE 5.00` so nothing silently looks
  like the wrong currency.
- App.tsx forwards `balance.total` and `balance.currency` from
  useSessionInfo — both null until the first successful
  getBalance() call, so the wallet segment appears once the
  endpoint responds and stays hidden offline.

Cache-hit %, branch, spent (this session), jobs count all also belong
in this row; each is a small isolated wiring step from here.

Refs #868
@esengine esengine merged commit 857a9de into main May 16, 2026
5 checks passed
@esengine esengine deleted the rust-scene-status-segments branch May 16, 2026 02:57
esengine added a commit that referenced this pull request May 16, 2026
…/ContextPanel layout (#1003)

Stage 1 toward the user's design mock — restructure from a flat
column of rows to the classic IDE three-pane shape:

  ┌───────────── title (full width) ─────────────┐
  │ SIDEBAR (24) │   MAIN (fill)   │  CTX (32)   │
  └───────────── status (full width) ────────────┘

The middle band is a `direction: "row"` box with `height: "fill"`,
made possible by the flex-sizing infra from #1000. Sidebar and ctx
pane have fixed cell widths; main pane fills the remainder. Both
side panes auto-hide on narrow terminals — sidebar below 60 cols,
ctx pane below 100 cols — so an 80-col terminal still works the way
it did before, just with a sessions-rail on the left.

## Main pane content (unchanged)

The cards stack, composer / approval / sessions-picker takeover,
slash overlay — exactly the same nodes as before, now living inside
the main pane's column instead of inline in the root.

## Sidebar (stage-1 placeholder)

Just a `─ SESSIONS ─` header + `use /sessions to browse` hint. The
real session list goes here in stage 2 once App.tsx surfaces a
permanently-loaded list (today it's loaded only when the picker is
open).

## Context pane (uses what's wired)

`─ CONTEXT ─` + `model · cards · wallet`. Wallet moves from the
status row into the ctx pane when both are visible — avoids
duplicating it. At cols < 100 the ctx pane is hidden and wallet
stays on the right of the status row (as in #1001).

## Test rewrite

The flat-children shape was load-bearing in 15 tests. Added two
helpers — `mainOf(f)` / `statusOf(f)` / `titleOf(f)` — and rewrote
each test to drill through the new structure. Coverage is identical
in spirit (still asserts behavior of card rows, composer, approval
modal, sessions picker, slash overlay, status segments) but
expressed in terms of the new hierarchy.

3 new shape tests:
- root is now `[title, middle, status]` (3 children, not 4-7)
- sidebar hidden below 60 cols
- ctx pane hidden below 100 cols

Refs #868

Co-authored-by: reasonix <reasonix@deepseek.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant