1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
# GUI plan
Decisions and rationale live in `docs/adr/0001-gui-frontend-architecture.md` and
`0002-version-lockstep.md`. This file is the order of work.
## Non-goals
Audio, 3D, macOS, auto-update, a browser client, and pixel-golden tests in CI.
## Phase 0 — version handshake (v4.0.0)
Breaking wire change, released for client and server together.
- `HELLO <version>` is the first line after TLS. The server answers
`HELLO <version> latest=<version> url=<download-url>` and rejects every other
message with `ERROR HELLO required` until it has seen one.
- MAJOR.MINOR must match; PATCH may differ. A mismatch is refused before any
credentials are sent.
- The client measures its connect latency with the `HELLO` round trip and
prints a notice when the server advertises a newer version.
- `DOWNLOAD_URL` is read from the environment by the server, with the public
site as the fallback.
**Gate:** mismatch refused in both directions, `HELLO` required before auth,
existing game flows unchanged, new tests for version parsing and gating.
## Phase 1 — core boundary and roulette (done)
Complete in v4.0.7. Every game plus `Lobby` and `History` are structured views;
the core builds the view and frontends send `Command`. The client transport
(TCP, rustls, TOFU, `HELLO`, auto-login) lives in `client::transport` behind a
trust callback. The command line moved out of the core in two pieces:
`client::input` owns the editor, history and key mapping, and `client::shell`
parses a finished line into a core `Command` or an adapter action (connect,
login, register, set-credential, host maintenance). `ClientCore` no longer
holds a `Key`, a prompt buffer, or any of the old TUI-shaped effects
(`Interactive`, `SetPrompt`, `ListHosts`, `ForgetHost`, `AnimateRoulette`); the
roulette wheel animation is derived from the `Result` view by the adapter.
"Log out" (`logout`) and "forget saved login" (`forget-login`) are distinct: the
latter drops the credential for the pinned key and keeps trust.
The `Connect` and `Trust` screens are adapter-owned for now: the terminal asks
in the transcript, and the GUI will draw them as its own screens over the same
`client::transport` callback. They are not core state because the core never
sees a certificate.
- Introduce `Command` and `View`; move terminal-only concerns (prompt editing,
wheel animation, interactive prompts) into the TUI adapter.
- App screens: `Connect`, `Trust`, `TrustMismatch`, `Login`, `Lobby`,
`History`, `Game`.
- Port roulette first: `PlaceBet(BetTarget)`, `SetChip`, `ClearBets`, `Spin`,
and a `FeltView` carrying chips, cursor, and the last result.
- Add `forget-login` so "log out" and "forget saved login" are distinct in both
frontends.
- Auto-login stays: a stored credential for the pinned fingerprint logs in
automatically after the trust check.
**Gate:** met. The TUI behaves as before (same boards, keys and prompts), its
tests drive the real adapter path (`shell::parse`, `Editor`, `game_input`), and
`ClientCore` contains no terminal types.
## Phase 2 — the other three games
Slots, blackjack, crash ports with their own `GameView` variants and commands.
Server push (`CRASH_BUSTED`) feeds the same `View`. The TUI keeps animating the
crash board from its local clock.
**Gate:** all four games playable in the TUI through `Command`/`View`.
## Phase 3 — `gui/` skeleton and the style spike
**Code complete in v4.1.0; awaiting the screenshot sign-off.**
- `gui/` is a workspace member (`zagan-bet-gui`). It depends on the core with
`default-features = false`, so neither egui nor native-tls enters the TUI or
server build graph. The build uses the workspace's `gui-release` profile
(opt-level `z`, LTO, stripped).
- `gui/src/theme.rs` holds the tokens: the terminal-derived dark palette, felt
green kept for the table, a 4/8/12/16/24 spacing scale, radii, and the type
scale. Two embedded fonts: Open Sans (OFL) for text, Hack (MIT) for numbers,
chips and labels. Licences sit next to the files in `gui/assets/fonts/`.
- `gui/src/roulette.rs` draws the felt, chips and wheel from a `RouletteView`;
it owns the geometry, not the rules. The felt is pointer-first: the hover
snaps to the fine lattice, so the inner half of a cell is a straight, an edge
is a split and a crossing is a corner. Left click adds the selected chip,
right or middle click takes one back, and a translucent chip previews the
target under the pointer.
- `gui/src/app.rs` composes the persistent header (connection, account,
balance) with the table and the betting sidebar. The demo state animates a
2.4 s wheel spin, highlights the winning pocket and cell, and reports the
amount paid and the net for the round. SPIN and CLEAR sit side by side so
clearing is never below the fold.
- `gui/tests/layout.rs` covers the pure maths (money grouping, wheel angle,
table aspect, bet names). UI wiring tests arrive with `egui_kittest` in
Phase 4.
Measured on Linux at 1080p with llvmpipe software GL:
| Check | Result |
| --- | --- |
| Linux binary | 6.0 MB |
| Windows x86_64 binary | 4.7 MB |
| Cold start to window | 52 ms |
| Idle RSS | 137 MB |
| Idle CPU | 0% |
The approved reference lives at `docs/screenshots/gui-roulette-1080p.png`, with
the result state at `docs/screenshots/gui-roulette-result-1080p.png`.
**Gate:** the screenshot needs your approval. Frame rate on integrated graphics
still needs a run on real hardware.
## Phase 4 — GUI wiring
## Phase 4 — GUI wiring
- Network thread with channels, request deadlines in the shared adapter.
- Trust modal, version-mismatch screen, login/register, lobby, history panel.
- All four games, per-frame painting and tier 1–2 effects.
- Update notice from the handshake in the lobby.
**Gate:** manual checklist per game at 60 fps, `egui_kittest` wiring tests,
modem-throttled run.
## Phase 5 — packaging
- `publish.sh` emits `zagan-bet-gui-<version>-<platform>-<arch>[.exe]`.
- Bash and PowerShell installers that verify the SHA-256, install to the user
directory, and create `.desktop`/Start-menu entries.
- Download page lists raw binaries and installers; add the source-code link.
**Gate:** `deploy.sh` verifies both artifact kinds; a clean machine installs
from the page and launches.
## Testing split
- `View`/`Command` tests in the core: flows, gating, state. Always.
- The TUI adapter remains the regression net through Phases 1–2.
- `egui_kittest` for wiring that `View` cannot see; no pixel goldens in CI.
- Manual for feel, animations, and layout at different window sizes.
|