Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion apps/web/THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ upstream repository: <https://github.com/vscode-icons/vscode-icons/blob/master/L

The 3D scene, playback, and trace/citymap type code under `src/mindwalk/` is
ported from the [`mindwalk`](https://github.com/cosmtrek/mindwalk) project's
`web/src` frontend (vendored in this repo at `.repos/mindwalk`).
`web/src` frontend (vendored in this repo at `.repos/mindwalk`). The HUD,
timeline, inspector, dock, and view-panel components under `src/mindwalk/ui/`
are derived from the same source — their structure, prop contracts, and
explanatory copy are upstream's, restyled onto this app's design tokens.

Copyright (c) 2026 Ricko Yu

Expand Down
127 changes: 116 additions & 11 deletions apps/web/src/mindwalk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,93 @@
`web/src` (MIT, © 2026 Ricko Yu — see `../../THIRD_PARTY_NOTICES.md`), vendored
at `.repos/mindwalk` at the revision this copy was taken from.

`WatchAgentSurface.tsx` and `surface.css` are ours, written against T3 — the
equivalent of mindwalk's `App.tsx`, `state/`, and `api/`, which are the parts of
the port deliberately not copied. The verbatim rule below binds only the copies.
`WatchAgentSurface.tsx`, `palette.ts`, and `surface.css` are ours, written
against T3 — the equivalent of mindwalk's `App.tsx`, `state/`, and `api/`,
which are the parts of the port deliberately not copied. The verbatim rule
below binds only the copies.

`ui/` is mindwalk's structure restyled onto T3: the components keep upstream's
markup shape, prop contracts, derivations, and hint copy, but their 2,452 lines
of `styles.css` are gone, replaced by Tailwind on T3's design tokens. Treat
these as ours to edit, not as copies to diff.

Verbatim on purpose: the squarified-treemap math, instanced-mesh buffer
indexing, and colour handling in this code render _almost_ right when
indexing, and colour handling in `scene/` render _almost_ right when
mistranslated, and that class of bug costs days to bisect. Deviations are
limited to what this repo's stricter tsconfig forces (non-null assertions and
casts, all erased at runtime) plus the pre-commit `vp fmt` autoformat, and each
must preserve behavior. Diff against `.repos/mindwalk/web/src` before editing
anything here.
casts, all erased at runtime), the pre-commit `vp fmt` autoformat, and the
deliberate list below. Diff against `.repos/mindwalk/web/src` before editing
anything in `scene/` or `playback/`.

## Light and dark

Mindwalk is dark-only: a nocturnal observatory where _light is data_, and only
touch states and trails may glow. T3 has a real light theme, so the surface
carries a second palette rather than pinning itself dark.

Light mode inverts the metaphor with the background — a **daylight survey**,
where ink is data. Near-white ground, graphite masses, touch states as
saturated ink. Hue is preserved exactly, because hue is the meaning the HUD
legend promises; only lightness flips. The glow model flips with it:
`AdditiveBlending` emits onto darkness, `NormalBlending` absorbs onto paper.
Both preserve the two properties the scene actually depends on — soft falloff,
from the sprite's alpha, and accumulation, where overlapping marks deepen.

Every value for both palettes lives in `palette.ts`, which is also where the
chrome's legend swatches come from, so a dot in the HUD cannot disagree with
the material it describes. **Dark mode remains the fidelity reference**: it is
what a live `mindwalk serve` renders, and what screenshot parity is checked
against.

## Neutrals are resolved, not declared

Every grey in the scene comes from T3 at runtime. A WebGL canvas cannot
inherit `bg-background` and `text-muted-foreground` the way the chrome does, so
the surface reads them off a probe element inside itself and hands the result
to both scenes (`resolveScenePalette`). The values in `palette.ts` are only the
fallback for when that probe cannot run.

Mindwalk's structural greys — the plain, the branches, unvisited and ghost
files, the floor plates — were a cool blue-grey family tuned against its navy
`#12151c` sky. Against T3's neutral surfaces they read as a foreign object, so
they are now expressed as _distances_ rather than colours: a percentage from
`--background` toward `--foreground` (`STRUCTURE_MIX`). That keeps mindwalk's
ordering intact — ghost dimmer than unvisited, a lit branch brighter than one
at rest — while putting every value on whatever axis T3 currently uses. One
ratio serves both themes, since "toward the foreground" already means "more
present" in either: it darkens on paper and lightens at night.

That includes the two biggest meshes on the stage, the ground plane and the
survey grid, which mindwalk declared inline as `#14171e` and friends. They are
easy to miss and expensive to get wrong: the ground is six times the map's
extent and mostly sits inside the fog, so a dark plane under a light sky is not
a dark plane — it is a full-stage gradient wash. By day the ground is the paper
itself and the gradient collapses to nothing.

The columns' baked vertical shade is themed for the same reason. Mindwalk
multiplies each column's touch colour from `0.34` at the base to `0.82` at the
crest so glow pools at the top and falls off into the plain. Multiplying toward
zero means "toward black", which only reads as falloff on an unlit stage; on
paper it puts a dark smudge at the foot of everything. By day the columns are
flat (`[1, 1]`) and the scene's own lighting does the shading.

What stays declared is what encodes _meaning_ and has no T3 counterpart: the
touch states, the timeline's action spectrum, and the mark colours. T3 has no
token for "read but not edited".

A theme switch rebuilds the scene rather than mutating materials in place. It
happens rarely, and the alternative is a second construction path that has to
stay in step with the first forever.

## Deliberate deviations from verbatim

These behavioral deviations are intentional and permanent, because AGENTS.md's
"no continuously repainting animations" rule outranks fidelity here:
Behavioral, and permanent:

- **`scene/frameLoop.ts` is ours, not mindwalk's.** Both scenes drive it
instead of mindwalk's unconditional `requestAnimationFrame` loop, so a
visible but idle scene issues zero draw calls. See the file's header for the
three inputs that book a frame.
visible but idle scene issues zero draw calls. AGENTS.md's "no continuously
repainting animations" rule outranks fidelity here. See the file's header for
the three inputs that book a frame.
- **`controls.autoRotate` is time-bounded.** Mindwalk drifts the camera until
the first interaction, which on a view you open and never touch is unbounded
motion on a parked, visible host. The drift is kept — it is how the scene
Expand All @@ -35,3 +101,42 @@ These behavioral deviations are intentional and permanent, because AGENTS.md's
the `playing` prop both scenes now take.
- **`DirLabelSet.ease`, and the height/halo lerps, report whether they moved.**
The loop needs to know when an animation has finished; upstream never asked.
- **The Timeline's transport keyboard shortcuts are gone.** Upstream installs a
`window`-level listener for Space, arrows, Home/End, and `S`/`E`/`X`/`M`,
which is fine when it owns the window and wrong in a panel that can sit
inactive behind chat or a terminal. Any bindings this surface grows belong to
T3's own keybinding system, not a second one. The UI labels that advertised
them went with them.
- **Video export is stripped.** `playback/recorder.ts`, `onExport`, and the
`exporting`/`locked` plumbing that existed only to serve it are all deleted.

Visual, and the point of the restyle:

- **Both themes**, as above.
- **T3's type and tokens.** Mindwalk's Fraunces display face and Schibsted
Grotesk body are replaced by T3's `--font-sans` (DM Sans) and `--font-mono`.
This includes `textures.ts:labelTexture()`, whose in-scene directory labels
asked for a face this app does not ship and were silently falling back.
- **T3 primitives replace hand-rolled ones** where the swap is presentational:
`ui/button` for every transport, dock, and close control, `ui/tooltip` for the
`[data-hint]` `::after` bubble, `ui/separator` for the dock divider, and
`ui/toggle-group` for the view switch (which gains the roving tabindex and
arrow-key navigation upstream explicitly declined). Focus rings, disabled
treatment, icon sizing, and hit targets then track the app rather than being
restated here. The Dock's own open/close logic stays — a pop is allowed to
coexist with an open sheet, which is not what a popover means.
- **Type comes from T3's scale.** Mindwalk's three hand-set sizes
(`0.65`/`0.68`/`0.9rem`) are gone; hierarchy in the dense rows is carried by
colour, which was already doing most of the work.
- **Responsive rules are keyed to the container, not the viewport.** Mindwalk's
own breakpoints are preserved (`1180px` drops the timeline legend, `900px`
turns the dock into a bottom sheet and hides the position dial), but as
`@container` queries, because this surface is a resizable panel whose width
is independent of the window. A viewport query would give a maximized panel
and a narrow one the same layout.

## Not ported

`ui/SessionRail.tsx`, `ui/ReportPanel.tsx`, `ui/AgentsPanel.tsx`,
`ui/LogoMark.tsx`, and `ui/shortcuts.ts`. The rail and the judge are out of
scope for this effort; the agents panel waits on the agent-graph endpoint.
Loading