The default face

A generic CPU renderer in mrlyui::face: any app's view - state, actions, canvas - becomes pixels, then a PNG. Terminal-esque, uniform, deliberately plain. It is the agent's eyes: a screenshot of any app on any tick, no browser in the loop.

The two shot kinds

frame fact rendered raw. Apps define availability: no frame fact, no shot. Frameless apps fail with "nothing to shoot here". Unchanged.

app. Renders the whole view and embeds the canvas raster in its body when one exists.

Geometry

320x452 fixed - the sheet. 452/320 tracks the square root of 2 within 0.2%, so a sheet halves into two sheets of the same shape: 320x452 -> 226x320 -> 160x226 -> 113x160. Body fills from the top, the action bar anchors to the bottom, slack in between stays board-colored. Rendered at scale 3 - PNGs are 960x1356. Pure function of the input: no clock, no RNG, byte-identical across runs.

Layout

beat verb right-aligned muted, hairline rule.

308x192; undecodable, oversized, or empty facts degrade to a muted frame WxH row), then state rows in map order (frame, shade, md skipped): scalars as key/value rows, all-scalar arrays inline, number grids as key 16x16 summaries, object arrays listed capped at 12 with + n more, nested objects one indent level then brief summaries, data: strings as [png Nb] tokens. A md string renders text-only: H1 scale 2, H2 accent, paragraphs pixel-wrapped, lists with hanging indent, code lines on a faint backdrop; emphasis and links strip to plain text.

capped at 8 plus + n more; zero actions reads no actions.

Theme

Board and ink follow darkmode; muted and faint are mixes between them. The accent is ROLLABLE[hash(route) % 13] - deterministic per app. Text uses the bitmap font; unsupported glyphs (emoji included) draw a hollow box, never blank. No emoji atlas yet - the sprite atlas is a later phase.

Totality

The face never fails: null state renders no state, hostile or oversized state truncates with .. and + n more against the height budget, and every string passes through the same per-char engine. face_png is total over anything peek returns.

Surfaces

glue in mrlynet::face::{face_frame, face_rgba, face_png, canvas_rgba}.

:face [path]. shot is the canvas kind and is untouched.

np.frombuffer(buf, np.uint8).reshape(h, w, 4).

six lived-in gauntlet shots to data/face/.

One pixel pin guards the whole stack (face_pixels_are_pinned in mrlyui); re-record it on deliberate layout changes.