Repository navigation
Description
Important
Problem — The current working indicator is split across two surfaces: a standing-wave SVG with cycling gerund text ("Fidelitymaxxing...") in the ThinkingLine, and a separate yellow breathing dot on the thought rail. The wave+word indicator is visually noisy, occupies vertical space in the transcript, and doesn't connect to the brand's identity (harmonic modes of a physical system). The rail dot — which already marks the active step — is underutilized.
Approach — Remove the wave and gerund from ThinkingLine (keep only the elapsed/token metadata), and promote the thought-rail dot into a morphing spherical-harmonic indicator: when running, the dot grows from 7px to ~13px and its shape cycles through 2D polar-projected silhouettes of Y_l^m modes (circle → dumbbell → pinched → clover), rendered as SVG path morphs via SMIL <animate>. A slow CSS rotation (~12s period) adds organic life. The metadata line stays in its current position below the message.
Scope — in: ThinkingLine simplification, harmonic-dot geometry module, HarmonicDot component, thought-rail integration, grow/shrink transition, reduced-motion support · out: wave file deletion (kept for potential reuse), tab/sidebar status indicators, done-dot styling
Acceptance Criteria
- When a turn is streaming, the tail step's rail dot renders as a ~13px SVG that morphs through four spherical-harmonic silhouettes on a ~2.3s hold per mode
- The morph uses SMIL path interpolation — all four paths have identical point counts (64 samples)
- The dot slowly rotates (~12s per full turn) via CSS transform on a parent
<g> - The dot grows from 7px (done size) to ~13px with a smooth CSS transition (~150ms ease-out) when it enters the running state
- When the step completes, the dot shrinks back to 7px ink circle (the existing done styling)
- The ThinkingLine no longer renders the wave SVG or cycling gerund — only the meta row (elapsed, tokens, esc hint)
- Under
prefers-reduced-motion: no morph animation, no rotation; the running dot renders as a static 13px yellow circle - The morphing dot fits within the existing pl-6 (24px) content inset — no layout shift to surrounding content
- Both light and dark themes render correctly (accent fill is visible on both grounds; accent-edge border defines the shape on light where yellow alone is ~1.2:1 contrast)
Testing Decisions
- Visual verification in the running app (localhost:4444 dev server) across light/dark themes
- Verify
prefers-reduced-motionvia DevTools emulation → Rendering → Emulate CSS media feature - Confirm no layout shift with the browser's Layout Shift debugger or by observing content reflow
- Unit-testable: the geometry module (harmonic-geometry.ts) should be testable standalone — correct point counts, normalized radii, valid SVG path syntax
Key Decisions
- SVG path morph via SMIL — all four harmonic outlines are sampled at 64 angular points (equal
M/Lcommand counts), enabling native<animate attributeName="d">interpolation without JS frame loops or third-party libraries - 13px running size — centered on LINE_X (11px), extends 4.5–17.5px, stays inside the 24px content gutter with no gutter-width changes needed
- Slow rotation on parent
<g>— CSStransform: rotate()on the<g>wrapper, separate from the SMILdmorph on the<path>, so the two animations compose cleanly - Keep wave files —
amico-wave.tsxandwave-geometry.tsstay in the tree (potential reuse on marketing surfaces) but are no longer imported by ThinkingLine - Meta line retained as-is — elapsed time, token count, and interrupt hint continue rendering in their current DOM position below the message; only the wave+word above them is removed
Constraints & Invariants
- The rail's geometry rules (documented in thought-rail.tsx header) remain intact — dot centre alignment, segment cap logic, adjacency-based completion
- Done dots remain 7px ink circles — the morph is exclusively a running-state behavior
- The NODE constant (7px) stays for done-state rendering; a new RUNNING_NODE (~13px) applies only inside HarmonicDot
- No new runtime dependencies — pure SVG + CSS + SMIL, framework-agnostic geometry module
- The ThinkingLine's metadata row must not reflow or jump when the wave is removed (the grid layout simplifies but the meta's position is stable)
Prior Art
packages/ui/src/amicode/wave-geometry.ts— the standing-wave approach (modal paths, timing constants, pure geometry module pattern)packages/app/src/pages/session/timeline/thought-rail.tsx— the rail's six geometry rules, especially Rule 5 (gutter sizing) and Rule 6 (lone running dot)packages/ui/src/amicode/amico-wave.tsx— SMIL-compatible multi-mode SVG animation pattern
Notes
- The four harmonic modes chosen (Y_0^0, Y_1^0, Y_2^0, Y_2^2) are recognizable at small sizes: circle, peanut, elongated pinch, and four-lobe clover. Higher harmonics (l=3+) have too many lobes to resolve at 13px.
- The mode cadence (2.3s) matches the wave's existing MODE_HOLD_MS, maintaining the same temporal rhythm the eye is already trained on.
- The grow transition (7→13px) serves double duty: it signals "this step just started" and it gives the morph enough pixels to be legible.
Activity
feat(ui): add harmonic-geometry module for spherical-harmonic morphin…
feat(app): integrate HarmonicDot into thought-rail, simplify Thinking…