v0.4.0 — the galaxy UX overhaul
Codemble v0.4.0 — the galaxy UX overhaul
The galaxy read as flat spheres on a plain background, connections were hard to
follow at any zoom level, and once a project was bound the only way to open a
different one was killing the server. This release lands the redesign, adds a
second way to look at the same graph, and finally puts what the parser already
knew on screen.
No breaking changes: the CLI and the on-disk progress format are unchanged, and
existing ~/.codemble/ progress is read as-is.
Highlights
Seeing the code
- Stars are drawn as light: canvas-generated halos and an
UnrealBloomPass
tuned so understood amber blooms hard while the unlit ramp barely registers - A background starfield seeded from the project's own file hashes — the same
code still produces the same sky - Python, JavaScript, and TypeScript systems sit in a faint language-tinted
nebula at galaxy level; any other language renders no fog rather than
borrowing a hue that would imply evidence Codemble does not have - A visible keyboard focus reticle beside the existing live text readout
- Passing a region's checks plays a 1.2s nebula dawn at galaxy level — amber
washing out through the system's halo and fog and receding. The lit state is
saved before the animation runs, so the dawn marks a fact instead of
delivering one, andprefers-reduced-motiongets the finished lit state with
no animation at all - Edge direction arrows below the galaxy level, hover tooltips naming both
structures, the relationship, its certainty and the line it was seen on, and
hover/selection highlighting. Studying a structure now keeps its connections
visible instead of dimming the whole scene - System members orbit by call depth, so position encodes flow: ring 1 is
what the module's entry node calls directly plus every member no sibling
calls, and only certain calls decide placement
A second way to look
- A 2D Map layer beside the 3D galaxy, switchable from the header, with an
Architecture tab (modules as boxes grouped by directory, layered by import
distance from Home) and a Workflow tab (the call tree from your
entrypoint, where the first hop is the parser'sdefinesrelation and deeper
hops arecalls) - Both layouts are computed in
codemble/graph/mapview.pyand served by a new
GET /api/map, so the Map and the galaxy cannot disagree - The Map is plain SVG and needs no WebGL, so a machine that cannot draw the
galaxy can still read the project
Reading what the parser knows
- The study panel leads with a structural summary rendered from parser facts
through fixed templates — no model, no key, no network - Grounded narration now actually reaches the panel; the explanation endpoint
had shipped but was never called - A Connections section lists every relationship into and out of the
selected structure, grouped inbound and outbound, each row carrying direction,
certainty, and thefile:linewhere that structure is defined, each row
clickable, above a small SVG diagram of callers → this → callees - Local narration through Ollama: explicit opt-in, loopback-and-
httponly
enforced at construction, no credential sent, and the same grounding
validation every other provider gets - Centrality now counts distinct callers rather than call sites, so
brightness stops overstating a helper called repeatedly from one place. The
study panel's label follows: "Callers", not "Calls in"
Staying in the app
- Switch project releases the bound project and returns to the picker — no
more killing the server - Change Home reopens the entrypoint picker whenever the parser ranked a
candidate, and the choice now survives a restart - In-app retry instead of "restart Codemble", a React error boundary, and a
<noscript>fallback - Easy/Expert audience mode: Easy uses plain language for narration, check
questions, panel labels, Lens notes and the legend, reduces visual density,
opens on the Map, and shows a hint chip naming the nearest unlit region to
Home by import-route hops. It never changes graph truth, coordinates,
progress, or how a check is scored - First-run coach-marks, a clickable breadcrumb, and a legend that describes
only the encodings the layer on screen actually draws
How uncertainty is drawn, per layer
The Correctness Contract requires an unproven relationship to stay visibly
unproven. The two renderers encode that differently, and the legend swatch
follows whichever layer is on screen:
| Layer | A "possible" relationship |
|---|---|
| 3D galaxy | A distinct colour, and no drifting particles. 3d-force-graph has no line-dash support, so 3D edges are never dashed |
| 2D Map (SVG) | Genuinely dashed, plus the same certainty wording |
| Study panel diagram | Dashed |
Drifting particles mark certain call edges only, at system and study level, and
stop entirely under prefers-reduced-motion.
Known limits
- The project scale cap is still ~300 supported source files; above that,
scope to a subdirectory in the picker or with--path - No threaded parse and no parse-progress screen in this release. That work,
along with raising the cap, is specified in
docs/superpowers/plans/2026-07-19-galaxy-ux-phase-c.mdand is planned, not
shipped - Language tint is drawn as nebula colour at galaxy level and on the Map's
Architecture tab only; system and study levels and the Workflow tab carry no
tint - Source adapters still cover Python, JavaScript, and TypeScript; unsupported
languages are not parsed or described - Dynamic or configuration-dependent JS/TS resolution remains explicitly
possible rather than promoted to fact - Syntax-error files remain visible as unchartable raw source
- Narration is optional. With a local model, grounding validation catches an
invented identifier but not a wrong claim about a real one, and smaller local
models make that second kind of mistake more often — the structural summary,
source, Lens, and checks are model-free either way - The original unaided learner-acceptance issue remains open; this technical
release does not fabricate human onboarding evidence