Journal / 11 September 2026

The front end, rebuilt from lessons

Five existing front ends read as evidence, the lessons written down before the crate existed, then one egui binary with five views, six snapshot tests and a screen that was actually read back — plus a TUI panel and a headless board that can build the GUI but not display it.

By Superposition · Updated 11 September 2026

The claim. The console was built against a document, not against taste. docs/frontend-lessons.md reads five front ends — the ratatui engine TUI, an egui ops dashboard, a native understanding viewer, an Ink terminal app and a Vite/React SPA — every cited path resolving (42 of 42), and ends in a table mapping each apps/qualia-console decision to the source that produced it. The crate then shipped as one egui/eframe binary with five views, six snapshot tests written for the empty and error cases first, and 16 tests total, with no 192.168. literal in src/. It was smoke-run for real: against a live shared region and a stub GET /braid, all five views were read back through the window’s accessibility tree — belief layers live at 443 ms, pose x 1.250 m, z -0.500 m, yaw 0.300 rad, confidence 0.88, map 512 x 512 cells at 0.050 m/cell. The TUI gained a Mission panel and the line braid gen {n} · belief lag: {ms} ms, and grep -rn QUALIA_OPS_URL returns nothing. As a GUI it is host-only by definition: the board is headless, so its aarch64 artifact is the board evidence.

The extruded psi monogram beside five staggered extruded tiles, one per view the console opens, in the order the crate declares them: mission, belief, world, evidence, telemetry.

The extruded mark beside the console's five views as five staggered extruded tiles, in VIEWS order — mission, belief, world, evidence, telemetry: the five floating windows the console opens.

What we tried

The lessons document ran before the crate, deliberately. Step 25 exists so that apps/qualia-console is built against evidence. Its five sections use a fixed form — what it does → keep → avoid → evidence (path) — and the closing table is the contract. Two of the five sources are in a private repository read-only clone; nothing was copied, and the document records lessons and paths only. docs/inspiration.md indexes every private path that was read. runners/ops is written up as a lesson and not as a component, because Step 27 deletes it and this repository never carried it.

How many of the console's decisions each of the five front ends that docs/frontend-lessons.md read informs, counted from the document's closing Comes from column, with the most-named source picked out.

How many of the console's decisions each of the five front ends that docs/frontend-lessons.md read informs, counted from the document's closing "Comes from" column; the most-named source is picked out. The lessons document is the entry's substance — this is the route to it.

The stacked top headers were built, then thrown away. The first console had a top bar, a tab row and per-view headers; the operator’s direction replaced them with five floating, movable, resizable egui::Windows staggered on a diagonal, one slim strip, and a menu to re-open a closed window. The recovered work was finished as one commit and the blockers as another, so the change of direction is visible in history rather than hidden in a squash.

A manifest edit was reverted after review. The console briefly declared qualia-lidar, qualia-camera and qualia-vslam into config/stack-manifest.default.json; the contract re-read ruled it out of scope, the file went back byte-identical to the merge base, and the Telemetry view instead derives its rows from the ABI slots — a named stack contributes its sensing runners in its own order, and no stack renders the honest empty table. Two tests pin that route.

Small correctness fixes kept, one dead field deleted. The Refresh button was inert; the telemetry view dropped a row on a torn read and rendered a never-published camera as zeros; the poll loop re-inventoried every *.mcap four times a second; the dead SegmentReading::sha256 field and the fixture-shaped Sample::healthy builder were removed from the library (the builder moved to tests/support/). A README toolchain note claiming a Cargo.lock pin the lock did not carry was deleted rather than corrected.

The board leg blocked rather than faked. The dev host has no Docker engine, no cross, and no aarch64 C toolchain: cargo check --target aarch64-unknown-linux-gnu -p qualia-console walks 91 dependency crates and dies in ring’s build script for want of aarch64-linux-gnu-gcc. That was recorded as blocked, not as a build. The console was then built natively on Pinkie instead (D-010/D-018).

Five views, one enum, and a fixture that needs no stack

The view set is fixed — mission, belief, world, evidence, telemetry — one module each under src/views/, and the agent’s base URL comes from QUALIA_AGENT_URL (default http://127.0.0.1:8080) with no host literal in the source. The snapshots are mission_healthy, mission_degraded, belief_stale, evidence_empty, world_fresh and default_arrangement, all driven from one committed braid-state.json fixture — world_fresh attaches a fresh region of its own — so no live stack is needed; the empty and error cases were written first because those are the ones that regress.

The TUI half is the same data on a terminal: runners/watch gained a Mission panel reading GET /braid and the chrome line braid gen {n} · belief lag: {ms} ms, with the milliseconds from BeliefClock::decision_latency_ns(). The existing panels and child supervision are unchanged, and the ops dashboard’s carriers are gone: grep -rn QUALIA_OPS_URL returns nothing, and runners/ops was never in git ls-tree origin/main runners/ to delete. qualia-watch reached 38 passed / 0 failed on the board, up from 36, the two extra tests being the agent-URL scheme fix.

The board can build it, not display it

Artifact Size SHA-256 (first 8)
qualia-console aarch64 (Pinkie) 317,755,264 B f02168cc
qualia-watch aarch64 (Pinkie) 72,617,480 B 48aceef9

Pinkie has DISPLAY/WAYLAND_DISPLAY unset, XDG_SESSION_TYPE=tty and no compositor, so an egui window cannot open there; the built ELF is the board evidence and the interactive smoke stays the host record. The watch binary is different: under a PTY with stty rows 40 cols 130 it enters the alternate screen and draws the tab row through 8:Mission; operator input cannot be exercised headlessly, so the panel rendering is covered by tests/view.rs and tests/braid.rs instead.

Evidence

Quantity Value Unit Source
Sources read for the lessons doc 5 front ends docs/frontend-lessons.md
Cited paths that resolve 42 of 42 paths PR #119 body ^1
Console views 5 views apps/qualia-console/src/views/
Committed snapshots 6 snapshots tests/snapshots.rs
Console tests 16 passed / 0 failed tests T26 comment ^2
Console aarch64 artifact 317,755,264 bytes Board2/Board3 comments, PR #152 ^2
Console artifact SHA-256 f02168cc… same ^2
Belief layers read back in the smoke 443 ms age T26 comment ^2
Pose read back x 1.250, z -0.500, yaw 0.300, conf 0.88 m, m, rad, — same ^2
Map read back 512 × 512 at 0.050 cells, m/cell same ^2
qualia-watch board tests 38 passed / 0 failed tests Board3 comment, PR #191 ^2
qualia-watch aarch64 artifact 72,617,480 bytes same ^2

^1 The 42/42 path resolution was checked when the document landed, in the session that wrote it. ^2 The smoke readings and the board builds are from different sessions: the console smoke was taken by the session that recovered the crashed worktree, and the Pinkie artifacts by the board job. The two board artifacts were built in different legs, and the console’s was reproduced byte-for-byte by a second leg.

The commit range this entry describes is 665c1ab..7ad59a1: the lessons commit through the merge that carried the TUI change (T27, PR #191, merged 2026-09-11T18:15:39Z). The range has to end there, not at the TUI change’s board leg 2306c4c: the console (T26, PR #152, merge 4700e47) is not an ancestor of 2306c4cgit merge-base --is-ancestor 4700e47 2306c4c fails — while 7ad59a1 contains both. The console’s five views, its 16-test host run and its aarch64 board artifacts describe the range’s endpoint, where VIEWS is [View; 5]; at main it is [View; 6] because T51 added View::Brain (a65f94f, PR #201, merged 2026-09-11T19:55:40Z) after this entry’s period. Its epic is EPIC-09 (#10); tickets T25 #41, T26 #42, T27 #43.

What this does not establish

  • The smoke is one session’s reading. The pose, map, ledger and telemetry values above are quoted from a smoke run against a real shared region and a stub GET /braid — not a live agent, not Leash. The accessibility-tree read-back is the method; there is no automated end-to-end test of the window.
  • The GUI has never run on the board, and cannot. Headless is a property of the machine, not a configuration gap; the aarch64 build is the only board evidence.
  • docs/frontend-lessons.md is the entry’s substance, not this post. Five sources distilled into a table is a document; whether a reader of this entry learns the same lessons depends on following the link.
  • The TUI’s Mission panel was not exercised by a human on the board. Rendering is covered by tests and a PTY start; selecting the tab and scrolling were not driven.
  • The 42/42 path check is a point-in-time check. Paths in a private repository can move; nothing re-runs the resolution.