rdmsm4x-changelog-20260916-1324-bitroo-888-app-catalog-ported-layout-engine
2026-09-16 13:24:42 EDT · rdmsm4x · session_012cXdr2uPhnPS1cQfbt9pPQ
The whole 888-app Tidbyt catalog is ported at the layer that
is portable: layout. Implemented its render vocabulary natively
rather than transcribing ~1M lines of Starlark. bitROO
ae9a6a7.
Why the method changed
The measurement decided it. The catalog is 956,531 lines of Starlark (median app 249, p90 760, max 584,659) — but the render vocabulary is fifteen primitives: Box 4412, Text 4132, Row 2680, Column 2346, Image 1415, Root 1404, Padding 1248, Marquee 985, WrappedText 769, Stack 624, Animation 371, Plot 157, Circle 141, Sequence 47, PieChart 6.
It is not 888 designs; it is 888 compositions of a small vocabulary. So the port is the vocabulary, not the transcript.
Coverage: 888 of 888
Sources/BitRooCore/Layout/ implements the widget set
with Tidbyt's real semantics — main_align,
cross_align, main_axis_size, and
start · center · end · space_between · space_around · space_evenly.
Every app maps to one of 13 ported archetypes:
| headline 443 · quote 93 · progressBoxClock 87 · iconCard 61 · statusList 59 · seriesCard 53 | | departures 27 · fullBleedImage 24 · scoreboard 12 · bigValue 11 · animation 11 · fuzzyClock 6 |
Per-app mapping: docs/tidbyt-archetype-map.tsv.
What "ported" means, precisely
- LAYOUT: all 888. The engine renders every structure the catalog uses.
- DATA: still gated for 691 (570 live services, 121 Tidbyt-encrypted secrets). Unchanged by any of this — but those gate the feed, never the layout. Every archetype takes its data as arguments, so it renders with no token, network or device.
- CONTENT: deliberately not copied. Apache-2.0 covers Tidbyt's code, not embedded artwork.
The conformance sheet earned its place on the first render
preview/layout-conformance.png produced six
alignment panels that were pixel-identical when all six must
differ. Cause: draw(row/column) handed each child
its own intrinsic size as available space, so a nested Row saw
its measured width instead of 64, main_axis_size: max had
nothing to expand into, and every space_* mode computed
free = 0 and collapsed to .start. Children now
receive the parent's cross-axis extent, and a test asserts all six
differ.
Second thing only looking caught: departures and
statusList rendered as an unreadable blob. Tidbyt's default
tb-8 is 8px tall so its rows get spacing free;
Font3x5 is 5px and stacked rows touch. Porting a
layout faithfully is not the same as porting it legibly.
A regression of mine, found and fixed
scripts/render_contact_sheet.zsh (shipped yesterday)
hand-assembled swiftc flags, and broke the moment
BitRooCore gained a libwebp dependency from another
session's work — it duplicated dependency knowledge SwiftPM already had,
so the two drifted the first time the package changed. Both renderers
are now package targets (swift run contactsheet,
swift run layoutsheet) and cannot drift that way again.
Honest gaps, recorded not rounded away
- Animation is a still frame here.
marqueetakes anoffset; animation apps render per-frame. Deliberate — a frame at offset 24 is testable, an animation is not — but not what the originals do. - No PieChart (6 apps); fonts differ; archetypes are shapes, not pixel-exact reproductions.
- Measurement caveat: the classifier greps
render.X, soneotracker— which aliases the import tor— read as UNMAPPED until inspected. A classifier keyed on a naming convention undercounts wherever the convention is aliased. 888/888 means "no app was found the widget set cannot express", not a proof.
Verification
swift test -> 39 tests, 0 failures (32 before)
layoutsheet -> 30 panels: every widget, all six alignment modes, inspected
contactsheet -> 38 scenes, still correct
make_app.zsh -> "architectures ok: x86_64 arm64"
iOS clean build -> BUILD SUCCEEDED
wiki -> FEAT-20260916-02 200, bogus path 404 as control
Notes
Another session shipped FEAT-20260915-05 (universal2 WebP) and FEAT-20260915-04 (App Intents) — both tickets I filed yesterday — while this ran. Their work is in the same tree; I committed only my paths.
Filed ISSUE-20260916-16: git tracks bitROO's docs
directory as Docs/ while the disk name is
docs/. Harmless on case-insensitive APFS, splits in two on
a case-sensitive filesystem. Pre-existing, and not fixed
now — a case-only rename is a two-step git operation and
another session is actively committing here.
No secrets appear in this record.