# 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, and `prefers-reduced-motion` gets 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's `defines` relation and deeper
  hops are `calls`)
- Both layouts are computed in `codemble/graph/mapview.py` and 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 the `file:line` where 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-`http` only
  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.md` and 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
